From 69ed45c555db599591211d2003dee1533368ee29 Mon Sep 17 00:00:00 2001
From: Juan Batiz-Benet <juan@benet.ai>
Date: Tue, 16 Sep 2014 01:54:53 -0700
Subject: [PATCH] refactor peer distance search + handleGetProviders

---
 routing/dht/dht.go | 113 +++++++++++++++++++++++++--------------------
 1 file changed, 62 insertions(+), 51 deletions(-)

diff --git a/routing/dht/dht.go b/routing/dht/dht.go
index 14484144..e0553c9a 100644
--- a/routing/dht/dht.go
+++ b/routing/dht/dht.go
@@ -245,24 +245,8 @@ func (dht *IpfsDHT) handleGetValue(p *peer.Peer, pmes *Message) (*Message, error
 	}
 
 	// Find closest peer on given cluster to desired key and reply with that info
-	// TODO: this should probably be decomposed.
-
-	// stored levels are > 1, to distinguish missing levels.
-	level := pmes.GetClusterLevel()
-	u.DOut("handleGetValue searching level %d clusters\n", level)
-
-	ck := kb.ConvertKey(u.Key(pmes.GetKey()))
-	closer := dht.routingTables[level].NearestPeer(ck)
-
-	// if closer peer is self, return nil
-	if closer.ID.Equal(dht.self.ID) {
-		u.DOut("Attempted to return self! this shouldnt happen...\n")
-		resp.CloserPeers = nil
-		return resp, nil
-	}
-
-	// if self is closer than the one from the table, return nil
-	if kb.Closer(dht.self.ID, closer.ID, u.Key(pmes.GetKey())) {
+	closer := dht.betterPeerToQuery(pmes)
+	if closer == nil {
 		u.DOut("handleGetValue could not find a closer node than myself.\n")
 		resp.CloserPeers = nil
 		return resp, nil
@@ -293,12 +277,15 @@ func (dht *IpfsDHT) handlePing(p *peer.Peer, pmes *Message) (*Message, error) {
 
 func (dht *IpfsDHT) handleFindPeer(p *peer.Peer, pmes *Message) (*Message, error) {
 	resp := &Message{Type: pmes.Type}
+	var closest *peer.Peer
 
-	level := pmes.GetClusterLevel()
-	u.DOut("handleFindPeer: searching for '%s'\n", peer.ID(pmes.GetKey()).Pretty())
+	// if looking for self... special case where we send it on CloserPeers.
+	if peer.ID(pmes.GetKey()).Equal(dht.self.ID) {
+		closest = dht.self
+	} else {
+		closest = dht.betterPeerToQuery(pmes)
+	}
 
-	ck := kb.ConvertKey(u.Key(pmes.GetKey()))
-	closest := dht.routingTables[level].NearestPeer(ck)
 	if closest == nil {
 		u.PErr("handleFindPeer: could not find anything.\n")
 		return resp, nil
@@ -309,52 +296,42 @@ func (dht *IpfsDHT) handleFindPeer(p *peer.Peer, pmes *Message) (*Message, error
 		return resp, nil
 	}
 
-	// If the found peer further away than this peer...
-	if kb.Closer(dht.self.ID, closest.ID, u.Key(pmes.GetKey())) {
-		return resp, nil
-	}
-
 	u.DOut("handleFindPeer: sending back '%s'\n", closest.ID.Pretty())
 	resp.CloserPeers = peersToPBPeers([]*peer.Peer{closest})
 	return resp, nil
 }
 
-func (dht *IpfsDHT) handleGetProviders(p *peer.Peer, pmes *Message) {
-	resp := Message{
-		Type:     Message_GET_PROVIDERS,
-		Key:      pmes.GetKey(),
-		ID:       pmes.GetId(),
-		Response: true,
+func (dht *IpfsDHT) handleGetProviders(p *peer.Peer, pmes *Message) (*Message, error) {
+	resp := &Message{
+		Type: pmes.Type,
+		Key:  pmes.Key,
 	}
 
+	// check if we have this value, to add ourselves as provider.
 	has, err := dht.datastore.Has(ds.NewKey(pmes.GetKey()))
-	if err != nil {
-		dht.netChan.Errors <- err
+	if err != nil && err != ds.ErrNotFound {
+		u.PErr("unexpected datastore error: %v\n", err)
+		has = false
 	}
 
+	// setup providers
 	providers := dht.providers.GetProviders(u.Key(pmes.GetKey()))
 	if has {
 		providers = append(providers, dht.self)
 	}
-	if providers == nil || len(providers) == 0 {
-		level := 0
-		if len(pmes.GetValue()) > 0 {
-			level = int(pmes.GetValue()[0])
-		}
 
-		closer := dht.routingTables[level].NearestPeer(kb.ConvertKey(u.Key(pmes.GetKey())))
-		if kb.Closer(dht.self.ID, closer.ID, u.Key(pmes.GetKey())) {
-			resp.Peers = nil
-		} else {
-			resp.Peers = []*peer.Peer{closer}
-		}
-	} else {
-		resp.Peers = providers
-		resp.Success = true
+	// if we've got providers, send thos those.
+	if providers != nil && len(providers) > 0 {
+		resp.ProviderPeers = peersToPBPeers(providers)
 	}
 
-	mes := swarm.NewMessage(p, resp.ToProtobuf())
-	dht.netChan.Outgoing <- mes
+	// Also send closer peers.
+	closer := dht.betterPeerToQuery(pmes)
+	if closer != nil {
+		resp.CloserPeers = peersToPBPeers([]*peer.Peer{closer})
+	}
+
+	return resp, nil
 }
 
 type providerInfo struct {
@@ -671,6 +648,40 @@ func (dht *IpfsDHT) addPeerList(key u.Key, peers []*Message_PBPeer) []*peer.Peer
 	return provArr
 }
 
+// nearestPeerToQuery returns the routing tables closest peers.
+func (dht *IpfsDHT) nearestPeerToQuery(pmes *Message) *peer.Peer {
+	level := pmes.GetClusterLevel()
+	cluster := dht.routingTables[level]
+
+	key := u.Key(pmes.GetKey())
+	closer := cluster.NearestPeer(kb.ConvertKey(key))
+	return closer
+}
+
+// betterPeerToQuery returns nearestPeerToQuery, but iff closer than self.
+func (dht *IpfsDHT) betterPeerToQuery(pmes *Message) *peer.Peer {
+	closer := dht.nearestPeerToQuery(pmes)
+
+	// no node? nil
+	if closer == nil {
+		return nil
+	}
+
+	// == to self? nil
+	if closer.ID.Equal(dht.self.ID) {
+		u.DOut("Attempted to return self! this shouldnt happen...\n")
+		return nil
+	}
+
+	// self is closer? nil
+	if kb.Closer(dht.self.ID, closer.ID, key) {
+		return nil
+	}
+
+	// ok seems like a closer node.
+	return closer
+}
+
 func (dht *IpfsDHT) peerFromInfo(pbp *Message_PBPeer) (*peer.Peer, error) {
 	maddr, err := ma.NewMultiaddr(pbp.GetAddr())
 	if err != nil {
-- 
GitLab