package offline import ( "context" "errors" "time" dshelp "github.com/ipfs/go-ipfs/thirdparty/ds-help" pstore "gx/ipfs/QmNUVzEjq3XWJ89hegahPvyfJbTXgTaom48pLb7YBD9gHQ/go-libp2p-peerstore" ci "gx/ipfs/QmP1DfoUjiWH2ZBo1PBH6FupdBucbDepx3HpWmEY6JMUpY/go-libp2p-crypto" ds "gx/ipfs/QmRWDav6mzWseLWeYfVd5fvUKiVe9xNH29YfMF438fG364/go-datastore" logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log" record "gx/ipfs/QmWYCqr6UDqqD1bfRybaAPtbAqcN3TSJpveaBXMwbQ3ePZ/go-libp2p-record" pb "gx/ipfs/QmWYCqr6UDqqD1bfRybaAPtbAqcN3TSJpveaBXMwbQ3ePZ/go-libp2p-record/pb" routing "gx/ipfs/QmXiH3yLocPhjkAmL8R29fKRcEKoVXKCaVDbAS9tdTrVEd/go-libp2p-routing" cid "gx/ipfs/QmYhQaCYEcaPPjxJX7YcPcVKkQfRy6sJ7B3XmGFk82XYdQ/go-cid" proto "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto" "gx/ipfs/QmdS9KpbDyPrieswibZhkod1oXqRwZJrUPzxCofAMWpFGq/go-libp2p-peer" ) var log = logging.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, } } // offlineRouting implements the IpfsRouting interface, // but only provides the capability to Put and Get signed dht // records to and from the local datastore. type offlineRouting struct { datastore ds.Datastore sk ci.PrivKey } func (c *offlineRouting) PutValue(ctx context.Context, key string, val []byte) error { rec, err := record.MakePutRecord(c.sk, key, val, false) if err != nil { return err } data, err := proto.Marshal(rec) if err != nil { return err } return c.datastore.Put(dshelp.NewKeyFromBinary([]byte(key)), data) } func (c *offlineRouting) GetValue(ctx context.Context, key string) ([]byte, error) { v, err := c.datastore.Get(dshelp.NewKeyFromBinary([]byte(key))) 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) GetValues(ctx context.Context, key string, _ int) ([]routing.RecvdVal, error) { v, err := c.datastore.Get(dshelp.NewKeyFromBinary([]byte(key))) 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 } func (c *offlineRouting) FindPeer(ctx context.Context, pid peer.ID) (pstore.PeerInfo, error) { return pstore.PeerInfo{}, ErrOffline } func (c *offlineRouting) FindProvidersAsync(ctx context.Context, k *cid.Cid, max int) <-chan pstore.PeerInfo { out := make(chan pstore.PeerInfo) close(out) return out } func (c *offlineRouting) Provide(_ context.Context, k *cid.Cid, _ bool) error { return ErrOffline } func (c *offlineRouting) Ping(ctx context.Context, p peer.ID) (time.Duration, error) { return 0, ErrOffline } func (c *offlineRouting) Bootstrap(context.Context) error { return nil } // ensure offlineRouting matches the IpfsRouting interface var _ routing.IpfsRouting = &offlineRouting{}