|
|
@ -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 |
|
|
|
} |