offline.go 2.56 KB
Newer Older
Jeromy's avatar
Jeromy committed
1 2 3 4 5 6 7 8
package offline

import (
	"errors"
	"time"

	"github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/goprotobuf/proto"
	ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"
9
	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
Jeromy's avatar
Jeromy committed
10 11 12 13
	ci "github.com/jbenet/go-ipfs/p2p/crypto"
	"github.com/jbenet/go-ipfs/p2p/peer"
	routing "github.com/jbenet/go-ipfs/routing"
	pb "github.com/jbenet/go-ipfs/routing/dht/pb"
Jeromy's avatar
Jeromy committed
14
	record "github.com/jbenet/go-ipfs/routing/record"
Jeromy's avatar
Jeromy committed
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
	eventlog "github.com/jbenet/go-ipfs/thirdparty/eventlog"
	u "github.com/jbenet/go-ipfs/util"
)

var log = eventlog.Logger("offlinerouting")

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
}

Jeromy's avatar
Jeromy committed
38 39
func (c *offlineRouting) PutValue(ctx context.Context, key u.Key, val []byte, sign bool) error {
	rec, err := record.MakePutRecord(c.sk, key, val, sign)
Jeromy's avatar
Jeromy committed
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
	if err != nil {
		return err
	}
	data, err := proto.Marshal(rec)
	if err != nil {
		return err
	}

	return c.datastore.Put(key.DsKey(), data)
}

func (c *offlineRouting) GetValue(ctx context.Context, key u.Key) ([]byte, error) {
	v, err := c.datastore.Get(key.DsKey())
	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
}

func (c *offlineRouting) FindProviders(ctx context.Context, key u.Key) ([]peer.PeerInfo, error) {
	return nil, ErrOffline
}

func (c *offlineRouting) FindPeer(ctx context.Context, pid peer.ID) (peer.PeerInfo, error) {
	return peer.PeerInfo{}, ErrOffline
}

func (c *offlineRouting) FindProvidersAsync(ctx context.Context, k u.Key, max int) <-chan peer.PeerInfo {
	out := make(chan peer.PeerInfo)
	close(out)
	return out
}

func (c *offlineRouting) Provide(_ context.Context, key u.Key) error {
	return ErrOffline
}

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

Jeromy's avatar
Jeromy committed
92
func (c *offlineRouting) Bootstrap(context.Context) error {
93 94 95
	return nil
}

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