// getValueOrPeers queries a particular peer p for the value for // key. It returns either the value or a list of closer peers. // NOTE: it will update the dht's peerstore with any new addresses // it finds for the given peer. func (dht *IpfsDHT) getValueOrPeers(ctx context.Context, p peer.ID, key key.Key) ([]byte, []peer.PeerInfo, error) { pmes, err := dht.getValueSingle(ctx, p, key) if err != nil { return nil, nil, err } if record := pmes.GetRecord(); record != nil { // Success! We were given the value log.Debug("getValueOrPeers: got value") // make sure record is valid. err = dht.verifyRecordOnline(ctx, record) if err != nil { log.Info("Received invalid record! (discarded)") return nil, nil, err } return record.GetValue(), nil, nil } // Perhaps we were given closer peers peers := pb.PBPeersToPeerInfos(pmes.GetCloserPeers()) if len(peers) > 0 { log.Debug("getValueOrPeers: peers") return nil, peers, nil } log.Warning("getValueOrPeers: routing.ErrNotFound") return nil, nil, routing.ErrNotFound }
func (dht *IpfsDHT) getPublicKeyFromNode(ctx context.Context, p peer.ID) (ci.PubKey, error) { // check locally, just in case... pk := dht.peerstore.PubKey(p) if pk != nil { return pk, nil } pkkey := routing.KeyForPublicKey(p) pmes, err := dht.getValueSingle(ctx, p, pkkey) if err != nil { return nil, err } // node doesn't have key :( record := pmes.GetRecord() if record == nil { return nil, fmt.Errorf("Node not responding with its public key: %s", p) } // Success! We were given the value. we don't need to check // validity because a) we can't. b) we know the hash of the // key we're looking for. val := record.GetValue() log.Debug("DHT got a value from other peer") pk, err = ci.UnmarshalPublicKey(val) if err != nil { return nil, err } id, err := peer.IDFromPublicKey(pk) if err != nil { return nil, err } if id != p { return nil, fmt.Errorf("public key does not match id: %s", p) } // ok! it's valid. we got it! log.Debugf("DHT got public key from node itself.") return pk, nil }