Skip to content
This repository has been archived by the owner on Dec 7, 2019. It is now read-only.

make routing less DHT specific #21

Merged
merged 4 commits into from
Jun 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gx/lastpubver
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.2.22: QmZix3EdeAdc4wnRksRXWEQ6kbqiFAP16h3Sq9JnEiP71N
2.3.0: QmUHRKTeaoASDvDj7cTAXsmjAY7KQ13ErtzkQHZQq6uFUz
50 changes: 50 additions & 0 deletions options/options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package ropts

// Option is a single routing option.
type Option func(opts *Options) error

// Options is a set of routing options
type Options struct {
// Allow expired values.
Expired bool
Offline bool
// Other (ValueStore implementation specific) options.
Other map[interface{}]interface{}
}

// Apply applies the given options to this Options
func (opts *Options) Apply(options ...Option) error {
for _, o := range options {
if err := o(opts); err != nil {
return err
}
}
return nil
}

// ToOption converts this Options to a single Option.
func (opts *Options) ToOption() Option {
return func(nopts *Options) error {
*nopts = *opts
if opts.Other != nil {
nopts.Other = make(map[interface{}]interface{}, len(opts.Other))
for k, v := range opts.Other {
nopts.Other[k] = v
}
}
return nil
}
}

// Expired is an option that tells the routing system to return expired records
// when no newer records are known.
var Expired Option = func(opts *Options) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any particular reason this isnt just:

func Expired(opts *Options) error {
// ....
}

opts.Expired = true
return nil
}

// Offline is an option that tells the routing system to operate offline (i.e., rely on cached/local data only).
var Offline Option = func(opts *Options) error {
opts.Offline = true
return nil
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@
"license": "MIT",
"name": "go-libp2p-routing",
"releaseCmd": "git commit -a -m \"gx publish $VERSION\"",
"version": "2.2.22"
"version": "2.3.0"
}

78 changes: 46 additions & 32 deletions routing.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"context"
"errors"

ropts "github.com/libp2p/go-libp2p-routing/options"

cid "github.com/ipfs/go-cid"
ci "github.com/libp2p/go-libp2p-crypto"
peer "github.com/libp2p/go-libp2p-peer"
Expand All @@ -14,6 +16,10 @@ import (
// ErrNotFound is returned when a search fails to find anything
var ErrNotFound = errors.New("routing: not found")

// ErrNotSupported is returned when a search or put fails because the key type
// isn't supported.
var ErrNotSupported = errors.New("routing: operation or key not supported")

// ContentRouting is a value provider layer of indirection. It is used to find
// information about who has what content.
type ContentRouting interface {
Expand All @@ -36,26 +42,23 @@ type PeerRouting interface {
FindPeer(context.Context, peer.ID) (pstore.PeerInfo, error)
}

// ValueStore is a basic Put/Get interface.
type ValueStore interface {
// Basic Put/Get

// PutValue adds value corresponding to given Key.
PutValue(context.Context, string, []byte) error
PutValue(context.Context, string, []byte, ...ropts.Option) error

// GetValue searches for the value corresponding to given Key.
GetValue(context.Context, string) ([]byte, error)
GetValue(context.Context, string, ...ropts.Option) ([]byte, error)

// GetValues searches for values corresponding to given Key.
//
// Passing a value of '0' for the count argument will cause the
// routing interface to return values only from cached or local storage
// and return an error if no cached value is found.
// TODO
// SearchValue searches for better and better values from this value
// store corresponding to the given Key. Implementations may halt the
// search after a period of time or may continue searching indefinitely.
//
// Passing a value of '1' will return a local value if found, and query
// the network for the first value it finds otherwise.
// As a result, a value of '1' is mostly useful for cases where the record
// in question has only one valid value (such as public keys)
GetValues(c context.Context, k string, count int) ([]RecvdVal, error)
// Useful when you want a result *now* but still want to hear about
// better/newer results.
//SearchValue(context.Context, string, ...ropts.Option) (<-chan []byte, error)
}

// IpfsRouting is the combination of different routing types that ipfs
Expand All @@ -73,35 +76,46 @@ type IpfsRouting interface {
// TODO expose io.Closer or plain-old Close error
}

// RecvdVal represents a dht value record that has been received from a given peer
// it is used to track peers with expired records in order to correct them.
type RecvdVal struct {
From peer.ID
Val []byte
}

// PubKeyFetcher is an interfaces that should be implemented by value stores
// that can optimize retrieval of public keys.
//
// TODO(steb): Consider removing, see #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 the dht.
// from a value store.
func KeyForPublicKey(id peer.ID) string {
return "/pk/" + string(id)
}

func GetPublicKey(r ValueStore, ctx context.Context, pkhash []byte) (ci.PubKey, error) {
// 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) {
k, err := p.ExtractPublicKey()
if err != nil {
// An error means that the peer ID is invalid.
return nil, err
}
if k != nil {
return k, nil
}

if dht, ok := r.(PubKeyFetcher); ok {
// If we have a DHT as our routing system, use optimized fetcher
return dht.GetPublicKey(ctx, peer.ID(pkhash))
} else {
key := "/pk/" + string(pkhash)
pkval, err := r.GetValue(ctx, key)
if err != nil {
return nil, err
}

// get PublicKey from node.Data
return ci.UnmarshalPublicKey(pkval)
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)
}