mirror of
https://github.com/ChronosX88/KademliaDHT.git
synced 2024-11-24 19:22:18 +00:00
Finished NodeLookupOperation functionality! Finally found the bug
This commit is contained in:
parent
9eca0614f2
commit
3344511603
@ -16,7 +16,7 @@ public class Configuration
|
||||
* If no reply received from a node in this period (in milliseconds)
|
||||
* consider the node unresponsive.
|
||||
* */
|
||||
public static long RESPONSE_TIMEOUT = 3000;
|
||||
public static long RESPONSE_TIMEOUT = 1500;
|
||||
|
||||
/**
|
||||
* Maximum number of milliseconds for performing an operation.
|
||||
@ -36,7 +36,7 @@ public class Configuration
|
||||
/**
|
||||
* Bucket size.
|
||||
* */
|
||||
public static int K = 3;
|
||||
public static int K = 5;
|
||||
|
||||
/**
|
||||
* Size of replacement cache.
|
||||
|
@ -35,6 +35,8 @@ public class KadServer
|
||||
private final HashMap<Integer, Receiver> receivers;
|
||||
private final Timer timer; // Schedule future tasks
|
||||
private final HashMap<Integer, TimerTask> tasks; // Keep track of scheduled tasks
|
||||
|
||||
private final Node localNode;
|
||||
|
||||
/* Factories */
|
||||
private final MessageFactory messageFactory;
|
||||
@ -47,10 +49,12 @@ public class KadServer
|
||||
this.timer = new Timer(true);
|
||||
}
|
||||
|
||||
public KadServer(int udpPort, MessageFactory mFactory) throws SocketException
|
||||
public KadServer(int udpPort, MessageFactory mFactory, Node localNode) throws SocketException
|
||||
{
|
||||
this.udpPort = udpPort;
|
||||
this.socket = new DatagramSocket(udpPort);
|
||||
|
||||
this.localNode = localNode;
|
||||
|
||||
this.messageFactory = mFactory;
|
||||
|
||||
@ -128,7 +132,7 @@ public class KadServer
|
||||
|
||||
if (data.length > DATAGRAM_BUFFER_SIZE)
|
||||
{
|
||||
throw new IOException("MEssage is too big");
|
||||
throw new IOException("Message is too big");
|
||||
}
|
||||
|
||||
/* Everything is good, now create the packet and send it */
|
||||
@ -163,9 +167,7 @@ public class KadServer
|
||||
|
||||
Message msg = messageFactory.createMessage(messCode, din);
|
||||
din.close();
|
||||
System.out.println("Message Received: " + msg);
|
||||
|
||||
System.out.println("Receivers: " + receivers);
|
||||
System.out.println(this.localNode.getNodeId() + " Message Received: " + msg);
|
||||
|
||||
/* Get a receiver for this message */
|
||||
Receiver receiver;
|
||||
|
@ -49,7 +49,7 @@ public class Kademlia
|
||||
this.name = name;
|
||||
this.localNode = new Node(defaultId, InetAddress.getLocalHost(), udpPort);
|
||||
this.messageFactory = new MessageFactory(localNode);
|
||||
this.server = new KadServer(udpPort, this.messageFactory);
|
||||
this.server = new KadServer(udpPort, this.messageFactory, this.localNode);
|
||||
this.timer = new Timer(true);
|
||||
|
||||
/* Schedule Recurring RestoreOperation */
|
||||
|
@ -39,7 +39,7 @@ public class NodeLookupReceiver implements Receiver
|
||||
|
||||
Node origin = msg.getOrigin();
|
||||
|
||||
System.out.println(this.localNode.getNodeId() + ": Received incoming NodeLookupMessage, sending NodeReplyMessage to: " + origin.getNodeId());
|
||||
System.out.println(this.localNode.getNodeId() + ": Received NodeLookupMessage, sending NodeReplyMessage to: " + origin.getNodeId());
|
||||
|
||||
/* Update the local space by inserting the origin node. */
|
||||
this.localNode.getRoutingTable().insert(origin);
|
||||
|
@ -117,6 +117,28 @@ public class Node implements Streamable
|
||||
return this.routingTable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (o instanceof Node)
|
||||
{
|
||||
return this.getNodeId().equals(((Node) o).getNodeId());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return this.getNodeId().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return this.getNodeId().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* A DistanceComparator is used to compare Node objects based on their closeness
|
||||
* */
|
||||
@ -145,23 +167,36 @@ public class Node implements Streamable
|
||||
{
|
||||
Node n1 = (Node) o1;
|
||||
Node n2 = (Node) o2;
|
||||
|
||||
int index1 = nodeId.xor(n1.getNodeId()).getFirstSetBitIndex();
|
||||
int index2 = nodeId.xor(n2.getNodeId()).getFirstSetBitIndex();
|
||||
|
||||
/* If the first node is closer to the given node, return 1 */
|
||||
if (index1 < index2)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if (index1 > index2)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
if(n1.getNodeId().equals(n2.getNodeId()))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//System.out.println("\n **************** Compare Starting **************** ");
|
||||
//System.out.println("Comparing to: " + this.nodeId);
|
||||
int index1 = nodeId.xor(n1.getNodeId()).getFirstSetBitIndex();
|
||||
//System.out.println("Node " + n1.getNodeId() + " distance: " + index1);
|
||||
int index2 = nodeId.xor(n2.getNodeId()).getFirstSetBitIndex();
|
||||
//System.out.println("Node " + n2.getNodeId() + " distance: " + index2);
|
||||
|
||||
/* If the first node is closer to the given node, return 1 */
|
||||
int retval;
|
||||
if (index1 < index2)
|
||||
{
|
||||
retval = 1;
|
||||
}
|
||||
else if (index1 > index2)
|
||||
{
|
||||
retval = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
retval = -1;
|
||||
}
|
||||
|
||||
//System.out.println("Returned: " + retval);
|
||||
//System.out.println("**************** Compare Ended ***************** \n");
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,13 +8,14 @@ package kademlia.node;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
import kademlia.message.Streamable;
|
||||
|
||||
public class NodeId implements Streamable
|
||||
{
|
||||
|
||||
|
||||
public final static int ID_LENGTH = 160;
|
||||
private byte[] keyBytes;
|
||||
|
||||
@ -38,7 +39,7 @@ public class NodeId implements Streamable
|
||||
keyBytes = new byte[ID_LENGTH / 8];
|
||||
new Random().nextBytes(keyBytes);
|
||||
}
|
||||
|
||||
|
||||
public NodeId(byte[] bytes)
|
||||
{
|
||||
this.keyBytes = bytes;
|
||||
@ -55,7 +56,7 @@ public class NodeId implements Streamable
|
||||
{
|
||||
this.fromStream(in);
|
||||
}
|
||||
|
||||
|
||||
public byte[] getBytes()
|
||||
{
|
||||
return this.keyBytes;
|
||||
@ -71,7 +72,7 @@ public class NodeId implements Streamable
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
|
||||
|
||||
if (o instanceof NodeId)
|
||||
{
|
||||
NodeId nid = (NodeId) o;
|
||||
@ -79,11 +80,13 @@ public class NodeId implements Streamable
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Arrays.hashCode(this.getBytes());
|
||||
int hash = 7;
|
||||
hash = 83 * hash + Arrays.hashCode(this.keyBytes);
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -119,12 +122,17 @@ public class NodeId implements Streamable
|
||||
{
|
||||
byte[] result = new byte[ID_LENGTH / 8];
|
||||
byte[] nidBytes = nid.getBytes();
|
||||
|
||||
for (int i = 0; i < ID_LENGTH / 8; i++)
|
||||
{
|
||||
result[i] = (byte) (this.keyBytes[i] ^ nidBytes[i]);
|
||||
//System.out.println("XOR Result: " + result[i]);
|
||||
}
|
||||
|
||||
return new NodeId(result);
|
||||
|
||||
NodeId resNid = new NodeId(result);
|
||||
|
||||
//System.out.println("Resulting Nid: " + resNid + " First set bit: " + resNid.getFirstSetBitIndex());
|
||||
return resNid;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -135,7 +143,7 @@ public class NodeId implements Streamable
|
||||
public int getFirstSetBitIndex()
|
||||
{
|
||||
int prefixLength = 0;
|
||||
|
||||
|
||||
for (byte b : this.keyBytes)
|
||||
{
|
||||
if (b == 0)
|
||||
@ -168,14 +176,14 @@ public class NodeId implements Streamable
|
||||
}
|
||||
return ID_LENGTH - prefixLength;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void toStream(DataOutput out) throws IOException
|
||||
{
|
||||
/* Add the NodeId to the stream */
|
||||
out.write(this.getBytes());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void fromStream(DataInput in) throws IOException
|
||||
{
|
||||
@ -183,14 +191,16 @@ public class NodeId implements Streamable
|
||||
in.readFully(input);
|
||||
this.keyBytes = input;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder("NodeId: ");
|
||||
sb.append(new String(this.keyBytes));
|
||||
|
||||
return sb.toString();
|
||||
// StringBuilder sb = new StringBuilder("NodeId: ");
|
||||
BigInteger bi = new BigInteger(1, this.keyBytes);
|
||||
return String.format("%0" + (this.keyBytes.length << 1) + "X", bi);
|
||||
//sb.append(Hex.encodeBase64URLSafeString(this.keyBytes));
|
||||
|
||||
//return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -125,11 +125,20 @@ public class NodeLookupOperation implements Operation, Receiver
|
||||
for (Node o : list)
|
||||
{
|
||||
/* If this node is not in the list, add the node */
|
||||
System.out.println("Trying to add node " + o.getNodeId() + " hash: " + o.hashCode());
|
||||
System.out.println("Contains Key for this node: " + nodes.containsKey(o));
|
||||
if (!nodes.containsKey(o))
|
||||
{
|
||||
System.out.println("Adding unasked node " + o.getNodeId());
|
||||
nodes.put(o, UNASKED);
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println(this.localNode.getNodeId() + " Nodes List: ");
|
||||
for (Node o : this.nodes.keySet())
|
||||
{
|
||||
System.out.println(o.getNodeId() + " hash: " + o.hashCode());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -153,6 +162,11 @@ public class NodeLookupOperation implements Operation, Receiver
|
||||
|
||||
/* Get unqueried nodes among the K closest seen that have not FAILED */
|
||||
ArrayList<Node> unasked = this.closestNodesNotFailed(UNASKED);
|
||||
System.out.println("Unasked nodes found: ");
|
||||
for (Node nn : unasked)
|
||||
{
|
||||
System.out.println(nn.getNodeId());
|
||||
}
|
||||
|
||||
if (unasked.isEmpty() && this.messagesTransiting.isEmpty())
|
||||
{
|
||||
@ -256,6 +270,7 @@ public class NodeLookupOperation implements Operation, Receiver
|
||||
|
||||
/* Add the origin node to our routing table */
|
||||
Node origin = msg.getOrigin();
|
||||
System.out.println(this.localNode.getNodeId() + " Lookup Operation Response From: " + origin.getNodeId());
|
||||
this.localNode.getRoutingTable().insert(origin);
|
||||
|
||||
/* Set that we've completed ASKing the origin node */
|
||||
|
@ -7,7 +7,6 @@ package kademlia.routing;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import kademlia.node.Node;
|
||||
import kademlia.node.NodeId;
|
||||
|
||||
@ -42,7 +41,9 @@ public class KadBucket implements Bucket
|
||||
}
|
||||
else
|
||||
{
|
||||
//System.out.println("Adding new node - " + n.getNodeId() + " to bucket depth: " + this.depth);
|
||||
nodes.put(n.getNodeId(), n);
|
||||
//System.out.println(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -92,7 +93,7 @@ public class KadBucket implements Bucket
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder("Printing bucket at depth: ");
|
||||
StringBuilder sb = new StringBuilder("Bucket at depth: ");
|
||||
sb.append(this.depth);
|
||||
sb.append("\n Nodes: \n");
|
||||
for (Node n : this.nodes.values())
|
||||
|
@ -12,7 +12,7 @@ import kademlia.node.NodeId;
|
||||
public class RoutingTable
|
||||
{
|
||||
|
||||
private final Node node; // The current node
|
||||
private final Node localNode; // The current node
|
||||
private final KadBucket[] buckets;
|
||||
|
||||
|
||||
@ -20,9 +20,9 @@ public class RoutingTable
|
||||
buckets = new KadBucket[NodeId.ID_LENGTH]; // 160 buckets; 1 for each level in the tree
|
||||
}
|
||||
|
||||
public RoutingTable(Node node)
|
||||
public RoutingTable(Node localNode)
|
||||
{
|
||||
this.node = node;
|
||||
this.localNode = localNode;
|
||||
|
||||
/* Initialize all of the buckets to a specific depth */
|
||||
for (int i = 0; i < NodeId.ID_LENGTH; i++)
|
||||
@ -39,7 +39,11 @@ public class RoutingTable
|
||||
public void insert(Node n)
|
||||
{
|
||||
/* Find the first set bit: how far this node is away from the contact node */
|
||||
int bucketId = this.node.getNodeId().xor(n.getNodeId()).getFirstSetBitIndex();
|
||||
NodeId id = this.localNode.getNodeId().xor(n.getNodeId());
|
||||
//System.out.println(" First Bit Set: " + id.getFirstSetBitIndex());
|
||||
int bucketId = id.getFirstSetBitIndex();
|
||||
|
||||
System.out.println(this.localNode.getNodeId() + " Adding Node " + n.getNodeId() + " to bucket at depth: " + bucketId);
|
||||
|
||||
/* Put this contact to the bucket that stores contacts prefixLength distance away */
|
||||
this.buckets[bucketId].insert(n);
|
||||
@ -53,7 +57,7 @@ public class RoutingTable
|
||||
public void remove(Node n)
|
||||
{
|
||||
/* Find the first set bit: how far this node is away from the contact node */
|
||||
int bucketId = this.node.getNodeId().xor(n.getNodeId()).getFirstSetBitIndex();
|
||||
int bucketId = this.localNode.getNodeId().xor(n.getNodeId()).getFirstSetBitIndex();
|
||||
|
||||
/* If the bucket has the contact, remove it */
|
||||
if (this.buckets[bucketId].containNode(n))
|
||||
@ -75,7 +79,7 @@ public class RoutingTable
|
||||
ArrayList<Node> closest = new ArrayList<>(num);
|
||||
|
||||
/* Get the bucket number to search for closest from */
|
||||
int bucketNumber = this.node.getNodeId().xor(target).getFirstSetBitIndex();
|
||||
int bucketNumber = this.localNode.getNodeId().xor(target).getFirstSetBitIndex();
|
||||
|
||||
/* Add the contacts from this bucket to the return contacts */
|
||||
for (Node c : this.buckets[bucketNumber].getNodes())
|
||||
@ -158,12 +162,14 @@ public class RoutingTable
|
||||
StringBuilder sb = new StringBuilder("\nPrinting Routing Table Started ***************** \n");
|
||||
for (KadBucket b : this.buckets)
|
||||
{
|
||||
// System.out.println("Bucket: " + b);
|
||||
if (b.numNodes() > 0)
|
||||
{
|
||||
sb.append("# nodes in Bucket with depth ");
|
||||
sb.append(b.getDepth());
|
||||
sb.append(": ");
|
||||
sb.append(b.numNodes());
|
||||
sb.append("\n");
|
||||
sb.append(b.toString());
|
||||
sb.append("\n");
|
||||
}
|
||||
|
@ -17,22 +17,49 @@ public class NodeConnectionTest
|
||||
try
|
||||
{
|
||||
/* Setting up 2 Kad networks */
|
||||
Kademlia kad1 = new Kademlia("Joshua", new NodeId("12345678947584567467"), 7574);
|
||||
Kademlia kad2 = new Kademlia("Crystal", new NodeId("12345678999324567838"), 7572);
|
||||
Kademlia kad1 = new Kademlia("JoshuaK", new NodeId("ASF45678947584567467"), 7574);
|
||||
System.out.println("Created Node Kad 1: " + kad1.getNode().getNodeId());
|
||||
|
||||
Kademlia kad2 = new Kademlia("Crystal", new NodeId("ASERTKJDHGVHERJHGFLK"), 7572);
|
||||
//NodeId diff12 = kad1.getNode().getNodeId().xor(kad2.getNode().getNodeId());
|
||||
System.out.println("Created Node Kad 2: " + kad2.getNode().getNodeId());
|
||||
// System.out.println(kad1.getNode().getNodeId() + " ^ " + kad2.getNode().getNodeId() + " = " + diff12);
|
||||
// System.out.println("Kad 1 - Kad 2 distance: " + diff12.getFirstSetBitIndex());
|
||||
|
||||
/* Connecting 2 to 1 */
|
||||
System.out.println("Connecting Kad 1 and Kad 2");
|
||||
kad1.connect(kad2.getNode());
|
||||
|
||||
System.out.println("Kad 1: ");
|
||||
System.out.println(kad1.getNode().getRoutingTable());
|
||||
System.out.println("Kad 2: ");
|
||||
System.out.println(kad2.getNode().getRoutingTable());
|
||||
// System.out.println("Kad 1: ");
|
||||
// System.out.println(kad1.getNode().getRoutingTable());
|
||||
// System.out.println("Kad 2: ");
|
||||
// System.out.println(kad2.getNode().getRoutingTable());
|
||||
|
||||
/* Creating a new node 3 and connecting it to 1, hoping it'll get onto 2 also */
|
||||
Kademlia kad3 = new Kademlia("Jessica", new NodeId("88888736882323647625"), 7783);
|
||||
kad3.connect(kad1.getNode());
|
||||
System.out.println("Kad 3: ");
|
||||
Kademlia kad3 = new Kademlia("Jessica", new NodeId("ASERTKJDOLKMNBVFR45G"), 7783);
|
||||
System.out.println("\n\n\n\n\n\nCreated Node Kad 3: " + kad3.getNode().getNodeId());
|
||||
|
||||
System.out.println("Connecting Kad 3 and Kad 2");
|
||||
kad3.connect(kad2.getNode());
|
||||
|
||||
// NodeId diff32 = kad3.getNode().getNodeId().xor(kad2.getNode().getNodeId());
|
||||
// NodeId diff31 = kad1.getNode().getNodeId().xor(kad3.getNode().getNodeId());
|
||||
// System.out.println("Kad 3 - Kad 1 distance: " + diff31.getFirstSetBitIndex());
|
||||
// System.out.println("Kad 3 - Kad 2 distance: " + diff32.getFirstSetBitIndex());
|
||||
Kademlia kad4 = new Kademlia("Sandy", new NodeId("ASERTK85OLKMN85FR4SS"), 7789);
|
||||
System.out.println("\n\n\n\n\n\nCreated Node Kad 4: " + kad4.getNode().getNodeId());
|
||||
|
||||
System.out.println("Connecting Kad 4 and Kad 2");
|
||||
kad4.connect(kad2.getNode());
|
||||
|
||||
System.out.println("\n\nKad 1: " + kad1.getNode().getNodeId() + " Routing Table: ");
|
||||
System.out.println(kad1.getNode().getRoutingTable());
|
||||
System.out.println("\n\nKad 2: " + kad2.getNode().getNodeId() + " Routing Table: ");
|
||||
System.out.println(kad2.getNode().getRoutingTable());
|
||||
System.out.println("\n\nKad 3: " + kad3.getNode().getNodeId() + " Routing Table: ");
|
||||
System.out.println(kad3.getNode().getRoutingTable());
|
||||
System.out.println("\n\nKad 4: " + kad4.getNode().getNodeId() + " Routing Table: ");
|
||||
System.out.println(kad4.getNode().getRoutingTable());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user