offline.go 3.32 KB
Newer Older
Jeromy's avatar
Jeromy committed
1 2 3
package offline

import (
4
	"context"
Jeromy's avatar
Jeromy committed
5 6 7
	"errors"
	"time"

8
	dshelp "github.com/ipfs/go-ipfs/thirdparty/ds-help"
Jeromy's avatar
Jeromy committed
9

Jeromy's avatar
Jeromy committed
10
	ds "gx/ipfs/QmRWDav6mzWseLWeYfVd5fvUKiVe9xNH29YfMF438fG364/go-datastore"
Jeromy's avatar
Jeromy committed
11
	logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log"
Jeromy's avatar
Jeromy committed
12
	proto "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
Jeromy's avatar
Jeromy committed
13 14
	routing "gx/ipfs/QmbkGVaN9W6RYJK4Ws5FvMKXKDqdRQ5snhtaa92qP6L8eU/go-libp2p-routing"
	cid "gx/ipfs/QmcTcsTvfaeEBRFo1TkFgT8sRmgi1n1LTZpecfVP8fzpGD/go-cid"
15 16
	record "gx/ipfs/QmdM4ohF7cr4MvAECVeD3hRA3HtZrk1ngaek4n8ojVT87h/go-libp2p-record"
	pb "gx/ipfs/QmdM4ohF7cr4MvAECVeD3hRA3HtZrk1ngaek4n8ojVT87h/go-libp2p-record/pb"
Jeromy's avatar
Jeromy committed
17
	pstore "gx/ipfs/QmeXj9VAjmYQZxpmVz7VzccbJrpmr8qkCDSjfVNsPTWTYU/go-libp2p-peerstore"
18 19
	"gx/ipfs/QmfMmLGoKzCHDN7cGgk64PJr4iipzidDRME8HABSJqvmhC/go-libp2p-peer"
	ci "gx/ipfs/QmfWDLQjGjVe4fr5CoztYW2DYYjRysMJrFe1RCsXLPTf46/go-libp2p-crypto"
Jeromy's avatar
Jeromy committed
20 21
)

Jeromy's avatar
Jeromy committed
22
var log = logging.Logger("offlinerouting")
Jeromy's avatar
Jeromy committed
23 24 25 26 27 28 29 30 31 32

var ErrOffline = errors.New("routing system in offline mode")

func NewOfflineRouter(dstore ds.Datastore, privkey ci.PrivKey) routing.IpfsRouting {
	return &offlineRouting{
		datastore: dstore,
		sk:        privkey,
	}
}

Jeromy's avatar
Jeromy committed
33 34 35
// offlineRouting implements the IpfsRouting interface,
// but only provides the capability to Put and Get signed dht
// records to and from the local datastore.
Jeromy's avatar
Jeromy committed
36 37 38 39 40
type offlineRouting struct {
	datastore ds.Datastore
	sk        ci.PrivKey
}

41
func (c *offlineRouting) PutValue(ctx context.Context, key string, val []byte) error {
42
	rec, err := record.MakePutRecord(c.sk, key, val, false)
Jeromy's avatar
Jeromy committed
43 44 45 46 47 48 49 50
	if err != nil {
		return err
	}
	data, err := proto.Marshal(rec)
	if err != nil {
		return err
	}

51
	return c.datastore.Put(dshelp.NewKeyFromBinary(key), data)
Jeromy's avatar
Jeromy committed
52 53
}

54 55
func (c *offlineRouting) GetValue(ctx context.Context, key string) ([]byte, error) {
	v, err := c.datastore.Get(dshelp.NewKeyFromBinary(key))
Jeromy's avatar
Jeromy committed
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
	if err != nil {
		return nil, err
	}

	byt, ok := v.([]byte)
	if !ok {
		return nil, errors.New("value stored in datastore not []byte")
	}
	rec := new(pb.Record)
	err = proto.Unmarshal(byt, rec)
	if err != nil {
		return nil, err
	}

	return rec.GetValue(), nil
}

73 74
func (c *offlineRouting) GetValues(ctx context.Context, key string, _ int) ([]routing.RecvdVal, error) {
	v, err := c.datastore.Get(dshelp.NewKeyFromBinary(key))
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
	if err != nil {
		return nil, err
	}

	byt, ok := v.([]byte)
	if !ok {
		return nil, errors.New("value stored in datastore not []byte")
	}
	rec := new(pb.Record)
	err = proto.Unmarshal(byt, rec)
	if err != nil {
		return nil, err
	}

	return []routing.RecvdVal{
		{Val: rec.GetValue()},
	}, nil
}

94
func (c *offlineRouting) FindProviders(ctx context.Context, key *cid.Cid) ([]pstore.PeerInfo, error) {
Jeromy's avatar
Jeromy committed
95 96 97
	return nil, ErrOffline
}

Jeromy's avatar
Jeromy committed
98 99
func (c *offlineRouting) FindPeer(ctx context.Context, pid peer.ID) (pstore.PeerInfo, error) {
	return pstore.PeerInfo{}, ErrOffline
Jeromy's avatar
Jeromy committed
100 101
}

102
func (c *offlineRouting) FindProvidersAsync(ctx context.Context, k *cid.Cid, max int) <-chan pstore.PeerInfo {
Jeromy's avatar
Jeromy committed
103
	out := make(chan pstore.PeerInfo)
Jeromy's avatar
Jeromy committed
104 105 106 107
	close(out)
	return out
}

108
func (c *offlineRouting) Provide(_ context.Context, k *cid.Cid) error {
Jeromy's avatar
Jeromy committed
109 110 111 112 113 114 115
	return ErrOffline
}

func (c *offlineRouting) Ping(ctx context.Context, p peer.ID) (time.Duration, error) {
	return 0, ErrOffline
}

Jeromy's avatar
Jeromy committed
116
func (c *offlineRouting) Bootstrap(context.Context) error {
117 118 119
	return nil
}

Jeromy's avatar
Jeromy committed
120
// ensure offlineRouting matches the IpfsRouting interface
Jeromy's avatar
Jeromy committed
121
var _ routing.IpfsRouting = &offlineRouting{}