ipld-eth-server/vendor/github.com/libp2p/go-libp2p-routing-helpers/composed.go
Elizabeth Engelman 36533f7c3f Update vendor directory and make necessary code changes
Fixes for new geth version
2019-09-25 16:32:27 -05:00

123 lines
3.7 KiB
Go

package routinghelpers
import (
"context"
ci "github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/libp2p/go-libp2p-core/routing"
multierror "github.com/hashicorp/go-multierror"
cid "github.com/ipfs/go-cid"
)
// 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
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)