package offline import ( "errors" "time" key "github.com/ipfs/go-ipfs/blocks/key" routing "github.com/ipfs/go-ipfs/routing" pb "github.com/ipfs/go-ipfs/routing/dht/pb" record "github.com/ipfs/go-ipfs/routing/record" ds "gx/ipfs/QmZ6A6P6AMo8SR3jXAwzTuSU6B9R2Y4eqW2yW9VvfUayDN/go-datastore" "gx/ipfs/QmQGwpJy9P4yXZySmqkZEXCmbBpJUb8xntCv8Ca4taZwDC/go-libp2p-peer" ci "gx/ipfs/QmUEUu1CM8bxBJxc3ZLojAi8evhTr4byQogWstABet79oY/go-libp2p-crypto" pstore "gx/ipfs/QmXHUpFsnpCmanRnacqYkFoLoFfEq5yS2nUgGkAjJ1Nj9j/go-libp2p-peerstore" logging "gx/ipfs/QmYtB7Qge8cJpXc4irsEp8zRqfnZMBeB7aTrMEkPk67DRv/go-log" proto "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto" context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context" ) 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 key.Key, 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(key.DsKey(), data) } func (c *offlineRouting) GetValue(ctx context.Context, key key.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) GetValues(ctx context.Context, key key.Key, _ int) ([]routing.RecvdVal, 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 []routing.RecvdVal{ {Val: rec.GetValue()}, }, nil } func (c *offlineRouting) FindProviders(ctx context.Context, key key.Key) ([]pstore.PeerInfo, error) { return nil, ErrOffline } 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 key.Key, max int) <-chan pstore.PeerInfo { out := make(chan pstore.PeerInfo) close(out) return out } func (c *offlineRouting) Provide(_ context.Context, key key.Key) 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{}