func checkEOL(e *pb.IpnsEntry) (time.Time, bool) { if e.GetValidityType() == pb.IpnsEntry_EOL { eol, err := u.ParseRFC3339(string(e.GetValidity())) if err != nil { return time.Time{}, false } return eol, true } return time.Time{}, false }
func selectRecord(recs []*pb.IpnsEntry, vals [][]byte) (int, error) { var best_seq uint64 best_i := -1 for i, r := range recs { if r == nil || r.GetSequence() < best_seq { continue } if best_i == -1 || r.GetSequence() > best_seq { best_seq = r.GetSequence() best_i = i } else if r.GetSequence() == best_seq { rt, err := u.ParseRFC3339(string(r.GetValidity())) if err != nil { continue } bestt, err := u.ParseRFC3339(string(recs[best_i].GetValidity())) if err != nil { continue } if rt.After(bestt) { best_i = i } else if rt == bestt { if bytes.Compare(vals[i], vals[best_i]) > 0 { best_i = i } } } } if best_i == -1 { return 0, errors.New("no usable records in given set") } return best_i, 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 }
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 }