-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
Copy pathrouting.go
138 lines (117 loc) · 4.59 KB
/
routing.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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// Package routing provides interfaces for peer routing and content routing in libp2p.
package routing
import (
"context"
"errors"
ci "github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer"
cid "github.com/ipfs/go-cid"
)
// ErrNotFound is returned when the router fails to find the requested record.
var ErrNotFound = errors.New("routing: not found")
// ErrNotSupported is returned when the router doesn't support the given record
// type/operation.
var ErrNotSupported = errors.New("routing: operation or key not supported")
// ContentProviding is able to announce where to find content on the Routing
// system.
type ContentProviding interface {
// 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.
Provide(context.Context, cid.Cid, bool) error
}
// ContentDiscovery is able to retrieve providers for a given CID using
// the Routing system.
type ContentDiscovery interface {
// Search for peers who are able to provide a given key
//
// When count is 0, this method will return an unbounded number of
// results.
FindProvidersAsync(context.Context, cid.Cid, int) <-chan peer.AddrInfo
}
// ContentRouting is a value provider layer of indirection. It is used to find
// information about who has what content.
//
// Content is identified by CID (content identifier), which encodes a hash
// of the identified content in a future-proof manner.
type ContentRouting interface {
ContentProviding
ContentDiscovery
}
// PeerRouting is a way to find address information about certain peers.
// This can be implemented by a simple lookup table, a tracking server,
// or even a DHT.
type PeerRouting interface {
// FindPeer searches for a peer with given ID, returns a peer.AddrInfo
// with relevant addresses.
FindPeer(context.Context, peer.ID) (peer.AddrInfo, error)
}
// ValueStore is a basic Put/Get interface.
type ValueStore interface {
// PutValue adds value corresponding to given Key.
PutValue(context.Context, string, []byte, ...Option) error
// GetValue searches for the value corresponding to given Key.
GetValue(context.Context, string, ...Option) ([]byte, error)
// SearchValue searches for better and better values from this value
// store corresponding to the given Key. By default, implementations must
// stop the search after a good value is found. A 'good' value is a value
// that would be returned from GetValue.
//
// Useful when you want a result *now* but still want to hear about
// better/newer results.
//
// Implementations of this methods won't return ErrNotFound. When a value
// couldn't be found, the channel will get closed without passing any results
SearchValue(context.Context, string, ...Option) (<-chan []byte, error)
}
// Routing is the combination of different routing types supported by libp2p.
// It can be satisfied by a single item (such as a DHT) or multiple different
// pieces that are more optimized to each task.
type Routing interface {
ContentRouting
PeerRouting
ValueStore
// Bootstrap allows callers to hint to the routing system to get into a
// Bootstrapped state and remain there. It is not a synchronous call.
Bootstrap(context.Context) error
// TODO expose io.Closer or plain-old Close error
}
// PubKeyFetcher is an interfaces that should be implemented by value stores
// that can optimize retrieval of public keys.
//
// TODO(steb): Consider removing, see https://github.com/libp2p/go-libp2p-routing/issues/22.
type PubKeyFetcher interface {
// GetPublicKey returns the public key for the given peer.
GetPublicKey(context.Context, peer.ID) (ci.PubKey, error)
}
// KeyForPublicKey returns the key used to retrieve public keys
// from a value store.
func KeyForPublicKey(id peer.ID) string {
return "/pk/" + string(id)
}
// GetPublicKey retrieves the public key associated with the given peer ID from
// the value store.
//
// If the ValueStore is also a PubKeyFetcher, this method will call GetPublicKey
// (which may be better optimized) instead of GetValue.
func GetPublicKey(r ValueStore, ctx context.Context, p peer.ID) (ci.PubKey, error) {
switch k, err := p.ExtractPublicKey(); err {
case peer.ErrNoPublicKey:
// check the datastore
case nil:
return k, nil
default:
return nil, err
}
if dht, ok := r.(PubKeyFetcher); ok {
// If we have a DHT as our routing system, use optimized fetcher
return dht.GetPublicKey(ctx, p)
}
key := KeyForPublicKey(p)
pkval, err := r.GetValue(ctx, key)
if err != nil {
return nil, err
}
// get PublicKey from node.Data
return ci.UnmarshalPublicKey(pkval)
}