node rpc PING & PONG methods and calls

This commit is contained in:
arnaucube
2019-12-08 13:21:12 +01:00
parent 0e39e2facb
commit 229a9003bb
11 changed files with 138 additions and 30 deletions

View File

@@ -2,6 +2,7 @@ package kademlia
import (
"math/bits"
"net/rpc"
"strconv"
log "github.com/sirupsen/logrus"
@@ -20,18 +21,23 @@ type ListedNode struct {
}
type Kademlia struct {
ID ID
// N is this node data
N ListedNode
KBuckets [B * 8][]ListedNode
}
func NewKademliaTable(id ID) *Kademlia {
func NewKademliaTable(id ID, addr, port string) *Kademlia {
return &Kademlia{
ID: id,
N: ListedNode{
ID: id,
Addr: addr,
Port: port,
},
}
}
func (kad Kademlia) String() string {
r := "Node ID: " + kad.ID.String() + ", KBuckets:\n"
r := "Node ID: " + kad.N.ID.String() + ", KBuckets:\n"
for i, kb := range kad.KBuckets {
if len(kb) > 0 {
r += " KBucket " + strconv.Itoa(i) + "\n"
@@ -44,7 +50,7 @@ func (kad Kademlia) String() string {
}
func (kad Kademlia) KBucket(o ID) int {
d := kad.ID.Distance(o)
d := kad.N.ID.Distance(o)
return kBucketByDistance(d[:])
}
@@ -63,8 +69,8 @@ func (kad *Kademlia) Update(o ListedNode) {
kb := kad.KBuckets[k]
if len(kb) >= KBucketSize {
// if n.KBuckets[k] is alrady full, perform ping of the first element
log.Debug("node.KBuckets[k] already full, performing ping to node.KBuckets[0]")
kad.Ping(k, o)
log.Info("node.KBuckets[k] already full, performing ping to node.KBuckets[0]")
kad.PingOldNode(k, o)
return
}
// check that is not already in the list
@@ -72,22 +78,59 @@ func (kad *Kademlia) Update(o ListedNode) {
if exist {
// update position of o to the bottom
kad.KBuckets[k] = moveToBottom(kad.KBuckets[k], pos)
log.Debug("ListedNode already exists, moved to bottom")
log.Info("ListedNode already exists, moved to bottom")
return
}
// not exists, add it to the kBucket
kad.KBuckets[k] = append(kad.KBuckets[k], o)
log.Debug("ListedNode not exists, added to the bottom")
log.Info("ListedNode not exists, added to the bottom")
return
}
func (kad *Kademlia) Ping(k int, o ListedNode) {
func (kad *Kademlia) PingOldNode(k int, o ListedNode) {
// TODO when rpc layer is done
// ping the n.KBuckets[k][0] (using goroutine)
// if no response (timeout), delete it and add 'o'
// n.KBuckets[k][0] = o
}
func (kad *Kademlia) CallPing(o ListedNode) error {
client, err := rpc.DialHTTP("tcp", o.Addr+":"+o.Port)
if err != nil {
return err
}
ln := ListedNode{
ID: kad.N.ID,
Addr: kad.N.Addr,
Port: kad.N.Port,
}
var reply ListedNode
err = client.Call("Node.Ping", ln, &reply)
if err != nil {
return err
}
return nil
}
func (kad *Kademlia) CallPong(o ListedNode) error {
client, err := rpc.DialHTTP("tcp", o.Addr+":"+o.Port)
if err != nil {
return err
}
ln := ListedNode{
ID: kad.N.ID,
Addr: kad.N.Addr,
Port: kad.N.Port,
}
var reply bool
err = client.Call("Node.Pong", ln, &reply)
if err != nil {
return err
}
return nil
}
func existsInListedNodes(lns []ListedNode, ln ListedNode) (bool, int) {
for i, v := range lns {
if v.ID.Equal(ln.ID) {

View File

@@ -40,9 +40,9 @@ func TestCountZeros(t *testing.T) {
func TestKBucket(t *testing.T) {
idA, err := IDFromString("0fd85ddddf15aeec2d5d8b01b013dbca030a18d7")
assert.Nil(t, err)
kademlia := NewKademliaTable(idA)
kademlia := NewKademliaTable(idA, "127.0.0.1", "5000")
d := kademlia.KBucket(kademlia.ID)
d := kademlia.KBucket(kademlia.N.ID)
assert.Equal(t, 0, d) // same node should have distance 0
idB, err := IDFromString("c48d8b53dbefb609ed4e94d386dd5b22efcb2c5b")
@@ -100,7 +100,7 @@ func TestMoveToBottom(t *testing.T) {
func TestUpdate(t *testing.T) {
idA, err := IDFromString("0fd85ddddf15aeec2d5d8b01b013dbca030a18d7")
assert.Nil(t, err)
kademlia := NewKademliaTable(idA)
kademlia := NewKademliaTable(idA, "127.0.0.1", "5000")
lns := prepareTestListedNodes()
for _, lnI := range lns {