add admin RPC find call, add kademlia NodeLookup interactive

This commit is contained in:
arnaucube
2019-12-15 17:22:35 +01:00
parent d971d1503a
commit ff0ba3995a
13 changed files with 264 additions and 22 deletions

View File

@@ -2,6 +2,7 @@ package kademlia
import (
"errors"
"fmt"
"math/bits"
"net/rpc"
"strconv"
@@ -50,8 +51,12 @@ func (kad Kademlia) String() string {
return r
}
func (kad Kademlia) FindClosestKBucket(id ID) (int, error) {
func (kad Kademlia) GetClosestKBucket(id ID) (int, error) {
kb := kad.KBucket(id)
if kb == 0 {
// is this node
return kb, nil
}
if len(kad.KBuckets[kb]) != 0 {
return kb, nil
}
@@ -118,7 +123,7 @@ func (kad *Kademlia) Update(o ListedNode) {
}
func (kad *Kademlia) PingOldNode(k int, o ListedNode) {
// TODO when rpc layer is done
// TODO
// ping the n.KBuckets[k][0] (using goroutine)
// if no response (timeout), delete it and add 'o'
// n.KBuckets[k][0] = o
@@ -177,3 +182,76 @@ func moveToBottom(kb []ListedNode, k int) []ListedNode {
kb = append(kb[:], e)
return kb
}
func removeFromListedNodes(lns []ListedNode, k int) []ListedNode {
lns = append(lns[:k], lns[k+1:]...)
return lns
}
func (kad Kademlia) CallFindNode(id ID, o ListedNode) ([]ListedNode, error) {
client, err := rpc.DialHTTP("tcp", o.Addr+":"+o.Port)
if err != nil {
return nil, err
}
var lns []ListedNode
err = client.Call("Node.FindNode", id, &lns)
if err != nil {
return nil, err
}
return lns, nil
}
func (kad Kademlia) NodeLookup(id ID) ([]ListedNode, error) {
log.Debug("[NodeLookup] get closest KBucket for ", id)
// find closest kbucket for this current node
k, err := kad.GetClosestKBucket(id)
if err != nil {
return []ListedNode{}, fmt.Errorf("No KBuckets")
}
log.Debug("[NodeLookup] closest KBucket", k)
var closest ListedNode
var newClosest ListedNode
closest = kad.N
var lns []ListedNode
lns = kad.KBuckets[k]
for !closest.ID.Equal(newClosest.ID) { // TODO
// call each ListedNode from the kbucket, asking for their list of closest kbucket
var newLns []ListedNode
closest = newClosest
for k, ln := range lns {
// TODO TMP for the moment is synchronous
fmt.Println("calling node", ln)
flns, err := kad.CallFindNode(id, ln)
if err != nil {
log.Debug(err)
}
removeFromListedNodes(lns, k)
// newLns = append(newLns, flns...)
for _, fln := range flns {
exist, _ := existsInListedNodes(newLns, fln)
if !exist {
fmt.Println("ln", fln.ID, " not exists")
newLns = append(newLns, fln)
}
}
}
lns = newLns
newClosest = updateClosest(id, lns, closest)
}
return lns, nil
}
func updateClosest(id ID, lns []ListedNode, closest ListedNode) ListedNode {
d := id.Distance(closest.ID)
closestZ := countZeroes(d[:])
for _, ln := range lns {
d := id.Distance(ln.ID)
z := countZeroes(d[:])
if z < closestZ {
closest = ln
closestZ = z
}
}
return closest
}

View File

@@ -152,7 +152,7 @@ func TestFindClosestKBucket(t *testing.T) {
idB, err := IDFromString("0fd85ddddf15aeec2d5d8b01b013dbca030a18d5")
assert.Nil(t, err)
k, err := kademlia.FindClosestKBucket(idB)
k, err := kademlia.GetClosestKBucket(idB)
assert.Nil(t, err)
assert.Equal(t, 2, k)
@@ -164,7 +164,7 @@ func TestFindClosestKBucket(t *testing.T) {
assert.Equal(t, 3, k)
// while the real KBucket (as the 3 is empty), should be 2
k, err = kademlia.FindClosestKBucket(idB)
k, err = kademlia.GetClosestKBucket(idB)
assert.Nil(t, err)
assert.Equal(t, 2, k)
@@ -176,7 +176,7 @@ func TestFindClosestKBucket(t *testing.T) {
assert.Equal(t, 5, k)
// while the real KBucket (as the 3 is empty), should be 2
k, err = kademlia.FindClosestKBucket(idB)
k, err = kademlia.GetClosestKBucket(idB)
assert.Nil(t, err)
assert.Equal(t, 7, k)
}