mirror of
https://github.com/ChronosX88/KademliaDHT.git
synced 2024-11-22 02:02:21 +00:00
Still working on NodeLookupRequest
Updated the NodeId equals() and hashCode() methods; fixes the bug where several same NodeIds were being added to the routing table
This commit is contained in:
parent
1de348fc72
commit
9eca0614f2
@ -51,8 +51,8 @@ public class MessageFactory
|
|||||||
return new SimpleReceiver();
|
return new SimpleReceiver();
|
||||||
case ConnectMessage.CODE:
|
case ConnectMessage.CODE:
|
||||||
return new ConnectReceiver(server, this.localNode);
|
return new ConnectReceiver(server, this.localNode);
|
||||||
case NodeLookupMessage.CODE
|
case NodeLookupMessage.CODE:
|
||||||
return new NodeLookupReceiver();
|
return new NodeLookupReceiver(server, this.localNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
75
src/kademlia/message/NodeLookupReceiver.java
Normal file
75
src/kademlia/message/NodeLookupReceiver.java
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/**
|
||||||
|
* @author Joshua Kissoon
|
||||||
|
* @created 20140219
|
||||||
|
* @desc Receives a ConnectMessage and sends an AcknowledgeMessage as reply
|
||||||
|
*/
|
||||||
|
package kademlia.message;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import kademlia.core.Configuration;
|
||||||
|
import kademlia.core.KadServer;
|
||||||
|
import kademlia.node.Node;
|
||||||
|
import kademlia.operation.Receiver;
|
||||||
|
|
||||||
|
public class NodeLookupReceiver implements Receiver
|
||||||
|
{
|
||||||
|
|
||||||
|
private final KadServer server;
|
||||||
|
private final Node localNode;
|
||||||
|
|
||||||
|
public NodeLookupReceiver(KadServer server, Node local)
|
||||||
|
{
|
||||||
|
this.server = server;
|
||||||
|
this.localNode = local;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle receiving a NodeLookupMessage
|
||||||
|
* Find the set of K nodes closest to the lookup ID and return them
|
||||||
|
*
|
||||||
|
* @param comm
|
||||||
|
*
|
||||||
|
* @throws java.io.IOException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void receive(Message incoming, int comm) throws IOException
|
||||||
|
{
|
||||||
|
NodeLookupMessage msg = (NodeLookupMessage) incoming;
|
||||||
|
|
||||||
|
Node origin = msg.getOrigin();
|
||||||
|
|
||||||
|
System.out.println(this.localNode.getNodeId() + ": Received incoming NodeLookupMessage, sending NodeReplyMessage to: " + origin.getNodeId());
|
||||||
|
|
||||||
|
/* Update the local space by inserting the origin node. */
|
||||||
|
this.localNode.getRoutingTable().insert(origin);
|
||||||
|
|
||||||
|
/* Find nodes closest to the LookupId */
|
||||||
|
ArrayList<Node> nodes = this.localNode.getRoutingTable().findClosest(msg.getLookupId(), Configuration.K);
|
||||||
|
|
||||||
|
System.out.println("\nClosest Nodes: ");
|
||||||
|
for (Node n : nodes)
|
||||||
|
{
|
||||||
|
System.out.println(n.getNodeId());
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
|
||||||
|
/* Respond to the NodeLookupMessage */
|
||||||
|
Message reply = new NodeReplyMessage(this.localNode, nodes);
|
||||||
|
|
||||||
|
/* Let the Server send the reply */
|
||||||
|
this.server.reply(origin, reply, comm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We don't need to do anything here
|
||||||
|
*
|
||||||
|
* @param comm
|
||||||
|
*
|
||||||
|
* @throws java.io.IOException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void timeout(int comm) throws IOException
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -14,7 +14,7 @@ import kademlia.message.Streamable;
|
|||||||
|
|
||||||
public class NodeId implements Streamable
|
public class NodeId implements Streamable
|
||||||
{
|
{
|
||||||
|
|
||||||
public final static int ID_LENGTH = 160;
|
public final static int ID_LENGTH = 160;
|
||||||
private byte[] keyBytes;
|
private byte[] keyBytes;
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ public class NodeId implements Streamable
|
|||||||
keyBytes = new byte[ID_LENGTH / 8];
|
keyBytes = new byte[ID_LENGTH / 8];
|
||||||
new Random().nextBytes(keyBytes);
|
new Random().nextBytes(keyBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public NodeId(byte[] bytes)
|
public NodeId(byte[] bytes)
|
||||||
{
|
{
|
||||||
this.keyBytes = bytes;
|
this.keyBytes = bytes;
|
||||||
@ -55,7 +55,7 @@ public class NodeId implements Streamable
|
|||||||
{
|
{
|
||||||
this.fromStream(in);
|
this.fromStream(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getBytes()
|
public byte[] getBytes()
|
||||||
{
|
{
|
||||||
return this.keyBytes;
|
return this.keyBytes;
|
||||||
@ -64,13 +64,26 @@ public class NodeId implements Streamable
|
|||||||
/**
|
/**
|
||||||
* Compares a NodeId to this NodeId
|
* Compares a NodeId to this NodeId
|
||||||
*
|
*
|
||||||
* @param nid The NodeId to compare to this NodeId
|
* @param o The NodeId to compare to this NodeId
|
||||||
*
|
*
|
||||||
* @return boolean Whether the 2 NodeIds are equal
|
* @return boolean Whether the 2 NodeIds are equal
|
||||||
*/
|
*/
|
||||||
public boolean equals(NodeId nid)
|
@Override
|
||||||
|
public boolean equals(Object o)
|
||||||
{
|
{
|
||||||
return Arrays.equals(keyBytes, nid.getBytes());
|
|
||||||
|
if (o instanceof NodeId)
|
||||||
|
{
|
||||||
|
NodeId nid = (NodeId) o;
|
||||||
|
return Arrays.equals(this.getBytes(), nid.getBytes());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode()
|
||||||
|
{
|
||||||
|
return Arrays.hashCode(this.getBytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -110,7 +123,7 @@ public class NodeId implements Streamable
|
|||||||
{
|
{
|
||||||
result[i] = (byte) (this.keyBytes[i] ^ nidBytes[i]);
|
result[i] = (byte) (this.keyBytes[i] ^ nidBytes[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new NodeId(result);
|
return new NodeId(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +135,7 @@ public class NodeId implements Streamable
|
|||||||
public int getFirstSetBitIndex()
|
public int getFirstSetBitIndex()
|
||||||
{
|
{
|
||||||
int prefixLength = 0;
|
int prefixLength = 0;
|
||||||
|
|
||||||
for (byte b : this.keyBytes)
|
for (byte b : this.keyBytes)
|
||||||
{
|
{
|
||||||
if (b == 0)
|
if (b == 0)
|
||||||
@ -155,14 +168,14 @@ public class NodeId implements Streamable
|
|||||||
}
|
}
|
||||||
return ID_LENGTH - prefixLength;
|
return ID_LENGTH - prefixLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void toStream(DataOutput out) throws IOException
|
public void toStream(DataOutput out) throws IOException
|
||||||
{
|
{
|
||||||
/* Add the NodeId to the stream */
|
/* Add the NodeId to the stream */
|
||||||
out.write(this.getBytes());
|
out.write(this.getBytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fromStream(DataInput in) throws IOException
|
public void fromStream(DataInput in) throws IOException
|
||||||
{
|
{
|
||||||
@ -170,14 +183,14 @@ public class NodeId implements Streamable
|
|||||||
in.readFully(input);
|
in.readFully(input);
|
||||||
this.keyBytes = input;
|
this.keyBytes = input;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
StringBuilder sb = new StringBuilder("NodeId: ");
|
StringBuilder sb = new StringBuilder("NodeId: ");
|
||||||
sb.append(new String(this.keyBytes));
|
sb.append(new String(this.keyBytes));
|
||||||
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,17 +6,20 @@
|
|||||||
package kademlia.routing;
|
package kademlia.routing;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import kademlia.node.Node;
|
import kademlia.node.Node;
|
||||||
|
import kademlia.node.NodeId;
|
||||||
|
|
||||||
public class KadBucket implements Bucket
|
public class KadBucket implements Bucket
|
||||||
{
|
{
|
||||||
|
|
||||||
private final int depth;
|
private final int depth;
|
||||||
private final ArrayList<Node> nodes;
|
private final HashMap<NodeId, Node> nodes;
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
nodes = new ArrayList<>();
|
nodes = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,14 +35,14 @@ public class KadBucket implements Bucket
|
|||||||
{
|
{
|
||||||
/*@todo Check if the bucket is filled already and handle this */
|
/*@todo Check if the bucket is filled already and handle this */
|
||||||
/* Check if the contact is already in the bucket */
|
/* Check if the contact is already in the bucket */
|
||||||
if (this.nodes.contains(n))
|
if (this.nodes.containsKey(n.getNodeId()))
|
||||||
{
|
{
|
||||||
/* @todo If it is, then move it to the front */
|
/* @todo If it is, then move it to the front */
|
||||||
/* @todo Possibly use a doubly linked list instead of an ArrayList */
|
/* @todo Possibly use a doubly linked list instead of an ArrayList */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nodes.add(n);
|
nodes.put(n.getNodeId(), n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,7 +55,7 @@ public class KadBucket implements Bucket
|
|||||||
*/
|
*/
|
||||||
public boolean containNode(Node n)
|
public boolean containNode(Node n)
|
||||||
{
|
{
|
||||||
return this.nodes.contains(n);
|
return this.nodes.containsKey(n.getNodeId());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -62,7 +65,7 @@ public class KadBucket implements Bucket
|
|||||||
*/
|
*/
|
||||||
public void removeNode(Node n)
|
public void removeNode(Node n)
|
||||||
{
|
{
|
||||||
this.nodes.remove(n);
|
this.nodes.remove(n.getNodeId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public int numNodes()
|
public int numNodes()
|
||||||
@ -78,12 +81,12 @@ public class KadBucket implements Bucket
|
|||||||
@Override
|
@Override
|
||||||
public void markDead(Node n)
|
public void markDead(Node n)
|
||||||
{
|
{
|
||||||
this.nodes.remove(n);
|
this.nodes.remove(n.getNodeId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<Node> getNodes()
|
public ArrayList<Node> getNodes()
|
||||||
{
|
{
|
||||||
return this.nodes;
|
return new ArrayList<>(this.nodes.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -92,7 +95,7 @@ public class KadBucket implements Bucket
|
|||||||
StringBuilder sb = new StringBuilder("Printing bucket at depth: ");
|
StringBuilder sb = new StringBuilder("Printing bucket at depth: ");
|
||||||
sb.append(this.depth);
|
sb.append(this.depth);
|
||||||
sb.append("\n Nodes: \n");
|
sb.append("\n Nodes: \n");
|
||||||
for (Node n : this.nodes)
|
for (Node n : this.nodes.values())
|
||||||
{
|
{
|
||||||
sb.append("Node: ");
|
sb.append("Node: ");
|
||||||
sb.append(n.getNodeId().toString());
|
sb.append(n.getNodeId().toString());
|
||||||
|
@ -164,6 +164,7 @@ public class RoutingTable
|
|||||||
sb.append(b.getDepth());
|
sb.append(b.getDepth());
|
||||||
sb.append(": ");
|
sb.append(": ");
|
||||||
sb.append(b.numNodes());
|
sb.append(b.numNodes());
|
||||||
|
sb.append(b.toString());
|
||||||
sb.append("\n");
|
sb.append("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,8 @@ public class NodeConnectionTest
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
/* Setting up 2 Kad networks */
|
/* Setting up 2 Kad networks */
|
||||||
Kademlia kad1 = new Kademlia("Joshua", new NodeId("12345678901234567890"), 7574);
|
Kademlia kad1 = new Kademlia("Joshua", new NodeId("12345678947584567467"), 7574);
|
||||||
Kademlia kad2 = new Kademlia("Crystal", new NodeId("12345678901234567891"), 7572);
|
Kademlia kad2 = new Kademlia("Crystal", new NodeId("12345678999324567838"), 7572);
|
||||||
|
|
||||||
/* Connecting 2 to 1 */
|
/* Connecting 2 to 1 */
|
||||||
kad1.connect(kad2.getNode());
|
kad1.connect(kad2.getNode());
|
||||||
|
Loading…
Reference in New Issue
Block a user