// getLocal attempts to retrieve the value from the datastore func (dht *IpfsDHT) getLocal(key key.Key) (*pb.Record, error) { log.Debug("getLocal %s", key) v, err := dht.datastore.Get(key.DsKey()) if err != nil { return nil, err } log.Debug("found in db") 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 } err = dht.verifyRecordLocally(rec) if err != nil { log.Debugf("local record verify failed: %s (discarded)", err) return nil, err } return rec, nil }
// NewDagReader creates a new reader object that reads the data represented by the given // node, using the passed in DAGService for data retreival func NewDagReader(ctx context.Context, n *mdag.Node, serv mdag.DAGService) (*DagReader, error) { pb := new(ftpb.Data) if err := proto.Unmarshal(n.Data, pb); err != nil { return nil, err } switch pb.GetType() { case ftpb.Data_Directory: // Dont allow reading directories return nil, ErrIsDir case ftpb.Data_Raw: fallthrough case ftpb.Data_File: return NewDataFileReader(ctx, n, pb, serv), nil case ftpb.Data_Metadata: if len(n.Links) == 0 { return nil, errors.New("incorrectly formatted metadata object") } child, err := n.Links[0].GetNode(ctx, serv) if err != nil { return nil, err } return NewDagReader(ctx, child, serv) case ftpb.Data_Symlink: return nil, ErrCantReadSymlinks default: return nil, ft.ErrUnrecognizedType } }
func (this *fullReader) ReadMsg(msg proto.Message) error { length, err := this.r.Read(this.buf) if err != nil { return err } return proto.Unmarshal(this.buf[:length], msg) }
func readMsgCtx(ctx context.Context, r msgio.Reader, p proto.Message) ([]byte, error) { var msg []byte // read in a goroutine so we can exit when our context is cancelled. done := make(chan error) go func() { var err error msg, err = r.ReadMsg() select { case done <- err: case <-ctx.Done(): } }() select { case <-ctx.Done(): return nil, ctx.Err() case e := <-done: if e != nil { return nil, e } } return msg, proto.Unmarshal(msg, p) }
func FromBytes(data []byte) (*pb.Data, error) { pbdata := new(pb.Data) err := proto.Unmarshal(data, pbdata) if err != nil { return nil, err } return pbdata, nil }
func UnwrapData(data []byte) ([]byte, error) { pbdata := new(pb.Data) err := proto.Unmarshal(data, pbdata) if err != nil { return nil, err } return pbdata.GetData(), nil }
func MetadataFromBytes(b []byte) (*Metadata, error) { pbd := new(pb.Data) err := proto.Unmarshal(b, pbd) if err != nil { return nil, err } if pbd.GetType() != pb.Data_Metadata { return nil, errors.New("incorrect node type") } pbm := new(pb.Metadata) err = proto.Unmarshal(pbd.Data, pbm) if err != nil { return nil, err } md := new(Metadata) md.MimeType = pbm.GetMimeType() return md, nil }
func (p *ipnsPublisher) getPreviousSeqNo(ctx context.Context, ipnskey key.Key) (uint64, error) { prevrec, err := p.ds.Get(ipnskey.DsKey()) if err != nil && err != ds.ErrNotFound { // None found, lets start at zero! return 0, err } var val []byte if err == nil { prbytes, ok := prevrec.([]byte) if !ok { return 0, fmt.Errorf("unexpected type returned from datastore: %#v", prevrec) } dhtrec := new(dhtpb.Record) err := proto.Unmarshal(prbytes, dhtrec) if err != nil { return 0, err } val = dhtrec.GetValue() } else { // try and check the dht for a record ctx, cancel := context.WithTimeout(ctx, time.Second*30) defer cancel() rv, err := p.routing.GetValue(ctx, ipnskey) if err != nil { // no such record found, start at zero! return 0, nil } val = rv } e := new(pb.IpnsEntry) err = proto.Unmarshal(val, e) if err != nil { return 0, err } return e.GetSequence(), nil }
// resolveOnce implements resolver. Uses the IPFS routing system to // resolve SFS-like names. func (r *routingResolver) resolveOnce(ctx context.Context, name string) (path.Path, error) { log.Debugf("RoutingResolve: '%s'", name) hash, err := mh.FromB58String(name) if err != nil { log.Warning("RoutingResolve: bad input hash: [%s]\n", name) return "", err } // name should be a multihash. if it isn't, error out here. // use the routing system to get the name. // /ipns/<name> h := []byte("/ipns/" + string(hash)) ipnsKey := key.Key(h) val, err := r.routing.GetValue(ctx, ipnsKey) if err != nil { log.Warning("RoutingResolve get failed.") return "", err } entry := new(pb.IpnsEntry) err = proto.Unmarshal(val, entry) if err != nil { return "", err } // name should be a public key retrievable from ipfs pubkey, err := routing.GetPublicKey(r.routing, ctx, hash) if err != nil { return "", err } hsh, _ := pubkey.Hash() log.Debugf("pk hash = %s", key.Key(hsh)) // check sig with pk if ok, err := pubkey.Verify(ipnsEntryDataForSig(entry), entry.GetSignature()); err != nil || !ok { return "", fmt.Errorf("Invalid value. Not signed by PrivateKey corresponding to %v", pubkey) } // ok sig checks out. this is a valid name. // check for old style record: valh, err := mh.Cast(entry.GetValue()) if err != nil { // Not a multihash, probably a new record return path.ParsePath(string(entry.GetValue())) } else { // Its an old style multihash record log.Warning("Detected old style multihash record") return path.FromKey(key.Key(valh)), nil } }
func (rp *Republisher) getLastVal(k key.Key) (path.Path, uint64, error) { ival, err := rp.ds.Get(k.DsKey()) if err != nil { // not found means we dont have a previously published entry return "", 0, errNoEntry } val := ival.([]byte) dhtrec := new(dhtpb.Record) err = proto.Unmarshal(val, dhtrec) if err != nil { return "", 0, err } // extract published data from record e := new(pb.IpnsEntry) err = proto.Unmarshal(dhtrec.GetValue(), e) if err != nil { return "", 0, err } return path.Path(e.Value), e.GetSequence(), nil }
func IpnsSelectorFunc(k key.Key, vals [][]byte) (int, error) { var recs []*pb.IpnsEntry for _, v := range vals { e := new(pb.IpnsEntry) err := proto.Unmarshal(v, e) if err == nil { recs = append(recs, e) } else { recs = append(recs, nil) } } return selectRecord(recs, vals) }
func FSNodeFromBytes(b []byte) (*FSNode, error) { pbn := new(pb.Data) err := proto.Unmarshal(b, pbn) if err != nil { return nil, err } n := new(FSNode) n.Data = pbn.Data n.blocksizes = pbn.Blocksizes n.subtotal = pbn.GetFilesize() - uint64(len(n.Data)) n.Type = pbn.GetType() return n, nil }
// UnmarshalPrivateKey converts a protobuf serialized private key into its // representative object func UnmarshalPrivateKey(data []byte) (PrivKey, error) { pmes := new(pb.PrivateKey) err := proto.Unmarshal(data, pmes) if err != nil { return nil, err } switch pmes.GetType() { case pb.KeyType_RSA: return UnmarshalRsaPrivateKey(pmes.GetData()) default: return nil, ErrBadKeyType } }
func getRoutingProviders(ds datastore.Datastore, k key.Key) ([]*dhtpb.Message_Peer, error) { e := log.EventBegin(context.Background(), "getProviders", &k) defer e.Done() var providers []*dhtpb.Message_Peer if v, err := ds.Get(providerKey(k)); err == nil { if data, ok := v.([]byte); ok { var msg dhtpb.Message if err := proto.Unmarshal(data, &msg); err != nil { return nil, err } providers = append(providers, msg.GetProviderPeers()...) } } return providers, nil }
func getRoutingRecord(ds datastore.Datastore, k key.Key) (*dhtpb.Record, error) { dskey := k.DsKey() val, err := ds.Get(dskey) if err != nil { return nil, err } recordBytes, ok := val.([]byte) if !ok { return nil, fmt.Errorf("datastore had non byte-slice value for %v", dskey) } var record dhtpb.Record if err := proto.Unmarshal(recordBytes, &record); err != nil { return nil, errors.New("failed to unmarshal dht record from datastore") } return &record, nil }
func (this *uint32Reader) ReadMsg(msg proto.Message) error { if _, err := io.ReadFull(this.r, this.lenBuf); err != nil { return err } length32 := this.byteOrder.Uint32(this.lenBuf) length := int(length32) if length < 0 || length > this.maxSize { return io.ErrShortBuffer } if length >= len(this.buf) { this.buf = make([]byte, length) } _, err := io.ReadFull(this.r, this.buf[:length]) if err != nil { return err } return proto.Unmarshal(this.buf[:length], msg) }
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 DataSize(data []byte) (uint64, error) { pbdata := new(pb.Data) err := proto.Unmarshal(data, pbdata) if err != nil { return 0, err } switch pbdata.GetType() { case pb.Data_Directory: return 0, errors.New("Cant get data size of directory!") case pb.Data_File: return pbdata.GetFilesize(), nil case pb.Data_Raw: return uint64(len(pbdata.GetData())), nil default: return 0, errors.New("Unrecognized node data type!") } }
func (this *varintReader) ReadMsg(msg proto.Message) error { length64, err := binary.ReadUvarint(this.r) if err != nil { return err } length := int(length64) if length < 0 || length > this.maxSize { return io.ErrShortBuffer } if len(this.buf) < length { this.buf = make([]byte, length) } buf := this.buf[:length] if _, err := io.ReadFull(this.r, buf); err != nil { return err } return proto.Unmarshal(buf, msg) }
// FIXME(brian): is this method meant to simulate getting a value from the network? func (c *client) GetValue(ctx context.Context, key key.Key) ([]byte, error) { log.Debugf("GetValue: %s", key) v, err := c.datastore.Get(key.DsKey()) if err != nil { return nil, err } data, ok := v.([]byte) if !ok { return nil, errors.New("could not cast value from datastore") } rec := new(dhtpb.Record) err = proto.Unmarshal(data, rec) if err != nil { return nil, err } return rec.GetValue(), nil }
// ValidateIpnsRecord implements ValidatorFunc and verifies that the // given 'val' is an IpnsEntry and that that entry is valid. func ValidateIpnsRecord(k key.Key, val []byte) error { entry := new(pb.IpnsEntry) err := proto.Unmarshal(val, entry) if err != nil { return err } switch entry.GetValidityType() { case pb.IpnsEntry_EOL: t, err := u.ParseRFC3339(string(entry.GetValidity())) if err != nil { log.Debug("Failed parsing time for ipns record EOL") return err } if time.Now().After(t) { return ErrExpiredRecord } default: return ErrUnrecognizedValidity } return nil }
// precalcNextBuf follows the next link in line and loads it from the DAGService, // setting the next buffer to read from func (dr *DagReader) precalcNextBuf(ctx context.Context) error { dr.buf.Close() // Just to make sure if dr.linkPosition >= len(dr.promises) { return io.EOF } nxt, err := dr.promises[dr.linkPosition].Get(ctx) if err != nil { return err } dr.linkPosition++ pb := new(ftpb.Data) err = proto.Unmarshal(nxt.Data, pb) if err != nil { return fmt.Errorf("incorrectly formatted protobuf: %s", err) } switch pb.GetType() { case ftpb.Data_Directory: // A directory should not exist within a file return ft.ErrInvalidDirLocation case ftpb.Data_File: dr.buf = NewDataFileReader(dr.ctx, nxt, pb, dr.serv) return nil case ftpb.Data_Raw: dr.buf = NewRSNCFromBytes(pb.GetData()) return nil case ftpb.Data_Metadata: return errors.New("Shouldnt have had metadata object inside file") case ftpb.Data_Symlink: return errors.New("shouldnt have had symlink inside file") default: return ft.ErrUnrecognizedType } }
func (dht *IpfsDHT) checkLocalDatastore(k key.Key) (*pb.Record, error) { log.Debugf("%s handleGetValue looking into ds", dht.self) dskey := k.DsKey() iVal, err := dht.datastore.Get(dskey) log.Debugf("%s handleGetValue looking into ds GOT %v", dht.self, iVal) if err == ds.ErrNotFound { return nil, nil } // if we got an unexpected error, bail. if err != nil { return nil, err } // if we have the value, send it back log.Debugf("%s handleGetValue success!", dht.self) byts, ok := iVal.([]byte) if !ok { return nil, fmt.Errorf("datastore had non byte-slice value for %v", dskey) } rec := new(pb.Record) err = proto.Unmarshal(byts, rec) if err != nil { log.Debug("Failed to unmarshal dht record from datastore") return nil, err } // if its our record, dont bother checking the times on it if peer.ID(rec.GetAuthor()) == dht.self { return rec, nil } var recordIsBad bool recvtime, err := u.ParseRFC3339(rec.GetTimeReceived()) if err != nil { log.Info("either no receive time set on record, or it was invalid: ", err) recordIsBad = true } if time.Now().Sub(recvtime) > MaxRecordAge { log.Debug("old record found, tossing.") recordIsBad = true } // NOTE: we do not verify the record here beyond checking these timestamps. // we put the burden of checking the records on the requester as checking a record // may be computationally expensive if recordIsBad { err := dht.datastore.Delete(dskey) if err != nil { log.Error("Failed to delete bad record from datastore: ", err) } return nil, nil // can treat this as not having the record at all } return rec, nil }