offline.go 3.11 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

10 11 12
	pstore "gx/ipfs/QmPgDWmTmuzvP7QE5zwo1TmjbJme9pmZHNujB2453jkCTr/go-libp2p-peerstore"
	routing "gx/ipfs/QmPjTrrSfE6TzLv6ya6VWhGcCgPrUAdcgrDcQyRDX2VyW1/go-libp2p-routing"
	cid "gx/ipfs/QmTprEaAA2A9bst5XH7exuyi5KzNMK3SEDNN8rBDnKWcUS/go-cid"
13
	ds "gx/ipfs/QmVSase1JP7cq9QkPT46oNwdp9pT6kBkG3oqS14y3QcZjG/go-datastore"
14
	"gx/ipfs/QmXYjuNuxVzXKJCfWasQk1RqkhVLDM9jtUKhqc2WPQmFSB/go-libp2p-peer"
Jeromy's avatar
Jeromy committed
15
	proto "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
16 17 18
	ci "gx/ipfs/QmaPbCnUMBohSGo3KnxEa2bHqyJVVeEEcwtqJAYxerieBo/go-libp2p-crypto"
	record "gx/ipfs/QmbxkgUceEcuSZ4ZdBA3x74VUDSSYjHYmmeEqkjxbtZ6Jg/go-libp2p-record"
	pb "gx/ipfs/QmbxkgUceEcuSZ4ZdBA3x74VUDSSYjHYmmeEqkjxbtZ6Jg/go-libp2p-record/pb"
Jeromy's avatar
Jeromy committed
19 20 21 22 23 24 25 26 27 28 29
)

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
30 31 32
// 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
33 34 35 36 37
type offlineRouting struct {
	datastore ds.Datastore
	sk        ci.PrivKey
}

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

48
	return c.datastore.Put(dshelp.NewKeyFromBinary([]byte(key)), data)
Jeromy's avatar
Jeromy committed
49 50
}

51
func (c *offlineRouting) GetValue(ctx context.Context, key string) ([]byte, error) {
52
	v, err := c.datastore.Get(dshelp.NewKeyFromBinary([]byte(key)))
Jeromy's avatar
Jeromy committed
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
	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
}

70
func (c *offlineRouting) GetValues(ctx context.Context, key string, _ int) ([]routing.RecvdVal, error) {
71
	v, err := c.datastore.Get(dshelp.NewKeyFromBinary([]byte(key)))
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
	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
}

Jeromy's avatar
Jeromy committed
91 92
func (c *offlineRouting) FindPeer(ctx context.Context, pid peer.ID) (pstore.PeerInfo, error) {
	return pstore.PeerInfo{}, ErrOffline
Jeromy's avatar
Jeromy committed
93 94
}

95
func (c *offlineRouting) FindProvidersAsync(ctx context.Context, k *cid.Cid, max int) <-chan pstore.PeerInfo {
Jeromy's avatar
Jeromy committed
96
	out := make(chan pstore.PeerInfo)
Jeromy's avatar
Jeromy committed
97 98 99 100
	close(out)
	return out
}

101
func (c *offlineRouting) Provide(_ context.Context, k *cid.Cid, _ bool) error {
Jeromy's avatar
Jeromy committed
102 103 104 105 106 107 108
	return ErrOffline
}

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

Jeromy's avatar
Jeromy committed
109
func (c *offlineRouting) Bootstrap(context.Context) error {
110 111 112
	return nil
}

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