Some major major changes to the entire Kademlia System.

Kademlia Node
- The Kademlia class is renamed to KademliaNode - this will now serve as the main node on the network
- The RoutingTable will be a part of this node
Node
- The node class is now a basic class containing information about a node to be used by peers on the network

RoutingTable
- Working on Evicting contacts from the routing table
- Working on Replacement Cache
- Written another simulation to test these new RoutingTable features
This commit is contained in:
Joshua Kissoon 2014-04-28 15:25:07 +05:30
parent a2f48d2241
commit 54ac3fe740
29 changed files with 363 additions and 186 deletions

View File

@ -34,7 +34,7 @@ import kademlia.util.serializer.JsonRoutingTableSerializer;
import kademlia.util.serializer.JsonSerializer; import kademlia.util.serializer.JsonSerializer;
/** /**
* The main Kademlia network management class * The main Kademlia Node on the network, this node manages everything for this local system.
* *
* @author Joshua Kissoon * @author Joshua Kissoon
* @since 20140215 * @since 20140215
@ -43,7 +43,7 @@ import kademlia.util.serializer.JsonSerializer;
* @todo Handle IPv6 Addresses * @todo Handle IPv6 Addresses
* *
*/ */
public class Kademlia public class KademliaNode
{ {
/* Kademlia Attributes */ /* Kademlia Attributes */
@ -53,6 +53,7 @@ public class Kademlia
private final transient Node localNode; private final transient Node localNode;
private final transient KadServer server; private final transient KadServer server;
private final transient DHT dht; private final transient DHT dht;
private transient RoutingTable routingTable;
private final transient Timer timer; private final transient Timer timer;
private final int udpPort; private final int udpPort;
private transient KadConfiguration config; private transient KadConfiguration config;
@ -66,24 +67,26 @@ public class Kademlia
* The instance is bootstraped to an existing network by specifying the * The instance is bootstraped to an existing network by specifying the
* address of a bootstrap node in the network. * address of a bootstrap node in the network.
* *
* @param ownerId The Name of this node used for storage * @param ownerId The Name of this node used for storage
* @param localNode The Local Node for this Kad instance * @param localNode The Local Node for this Kad instance
* @param udpPort The UDP port to use for routing messages * @param udpPort The UDP port to use for routing messages
* @param dht The DHT for this instance * @param dht The DHT for this instance
* @param config * @param config
* @param routingTable
* *
* @throws IOException If an error occurred while reading id or local map * @throws IOException If an error occurred while reading id or local map
* from disk <i>or</i> a network error occurred while * from disk <i>or</i> a network error occurred while
* attempting to bootstrap to the network * attempting to bootstrap to the network
* */ * */
public Kademlia(String ownerId, Node localNode, int udpPort, DHT dht, KadConfiguration config) throws IOException public KademliaNode(String ownerId, Node localNode, int udpPort, DHT dht, RoutingTable routingTable, KadConfiguration config) throws IOException
{ {
this.ownerId = ownerId; this.ownerId = ownerId;
this.udpPort = udpPort; this.udpPort = udpPort;
this.localNode = localNode; this.localNode = localNode;
this.dht = dht; this.dht = dht;
this.config = config; this.config = config;
this.messageFactory = new MessageFactory(localNode, this.dht, this.config); this.routingTable = routingTable;
this.messageFactory = new MessageFactory(this, this.dht, this.config);
this.server = new KadServer(udpPort, this.messageFactory, this.localNode, this.config); this.server = new KadServer(udpPort, this.messageFactory, this.localNode, this.config);
this.timer = new Timer(true); this.timer = new Timer(true);
@ -97,7 +100,7 @@ public class Kademlia
try try
{ {
/* Runs a DHT RefreshOperation */ /* Runs a DHT RefreshOperation */
Kademlia.this.refresh(); KademliaNode.this.refresh();
} }
catch (IOException e) catch (IOException e)
{ {
@ -110,15 +113,35 @@ public class Kademlia
); );
} }
public Kademlia(String ownerId, NodeId defaultId, int udpPort, KadConfiguration config) throws IOException public KademliaNode(String ownerId, NodeId defaultId, int udpPort, RoutingTable routingTable, KadConfiguration config) throws IOException
{ {
this(ownerId, new Node(defaultId, InetAddress.getLocalHost(), udpPort), udpPort, new DHT(ownerId, config), config); this(ownerId,
new Node(defaultId, InetAddress.getLocalHost(), udpPort, config),
udpPort,
routingTable,
new DHT(ownerId, config), config);
} }
public Kademlia(String ownerId, NodeId defaultId, int udpPort) throws IOException public KademliaNode(String ownerId, Node node, int udpPort, KadConfiguration config) throws IOException
{ {
this(ownerId, new Node(defaultId, InetAddress.getLocalHost(), udpPort), udpPort, this(
new DHT(ownerId, new DefaultConfiguration()), new DefaultConfiguration()); ownerId,
node,
udpPort,
new DHT(ownerId, config),
new RoutingTable(node, config),
config
);
}
public KademliaNode(String ownerId, NodeId defaultId, int udpPort) throws IOException
{
this(
ownerId,
new Node(defaultId, InetAddress.getLocalHost(), udpPort),
udpPort,
new DefaultConfiguration()
);
} }
/** /**
@ -131,9 +154,9 @@ public class Kademlia
* @throws java.io.FileNotFoundException * @throws java.io.FileNotFoundException
* @throws java.lang.ClassNotFoundException * @throws java.lang.ClassNotFoundException
*/ */
public static Kademlia loadFromFile(String ownerId) throws FileNotFoundException, IOException, ClassNotFoundException public static KademliaNode loadFromFile(String ownerId) throws FileNotFoundException, IOException, ClassNotFoundException
{ {
return Kademlia.loadFromFile(ownerId, new DefaultConfiguration()); return KademliaNode.loadFromFile(ownerId, new DefaultConfiguration());
} }
/** /**
@ -147,7 +170,7 @@ public class Kademlia
* @throws java.io.FileNotFoundException * @throws java.io.FileNotFoundException
* @throws java.lang.ClassNotFoundException * @throws java.lang.ClassNotFoundException
*/ */
public static Kademlia loadFromFile(String ownerId, KadConfiguration iconfig) throws FileNotFoundException, IOException, ClassNotFoundException public static KademliaNode loadFromFile(String ownerId, KadConfiguration iconfig) throws FileNotFoundException, IOException, ClassNotFoundException
{ {
DataInputStream din; DataInputStream din;
@ -155,7 +178,7 @@ public class Kademlia
* @section Read Basic Kad data * @section Read Basic Kad data
*/ */
din = new DataInputStream(new FileInputStream(getStateStorageFolderName(ownerId, iconfig) + File.separator + "kad.kns")); din = new DataInputStream(new FileInputStream(getStateStorageFolderName(ownerId, iconfig) + File.separator + "kad.kns"));
Kademlia ikad = new JsonSerializer<Kademlia>().read(din); KademliaNode ikad = new JsonSerializer<KademliaNode>().read(din);
/** /**
* @section Read the routing table * @section Read the routing table
@ -168,7 +191,6 @@ public class Kademlia
*/ */
din = new DataInputStream(new FileInputStream(getStateStorageFolderName(ownerId, iconfig) + File.separator + "node.kns")); din = new DataInputStream(new FileInputStream(getStateStorageFolderName(ownerId, iconfig) + File.separator + "node.kns"));
Node inode = new JsonSerializer<Node>().read(din); Node inode = new JsonSerializer<Node>().read(din);
inode.setRoutingTable(irtbl);
/** /**
* @section Read the DHT * @section Read the DHT
@ -177,7 +199,7 @@ public class Kademlia
DHT idht = new JsonDHTSerializer().read(din); DHT idht = new JsonDHTSerializer().read(din);
idht.setConfiguration(iconfig); idht.setConfiguration(iconfig);
return new Kademlia(ownerId, inode, ikad.getPort(), idht, iconfig); return new KademliaNode(ownerId, inode, ikad.getPort(), idht, irtbl, iconfig);
} }
/** /**
@ -223,7 +245,7 @@ public class Kademlia
* */ * */
public synchronized final void bootstrap(Node n) throws IOException, RoutingException public synchronized final void bootstrap(Node n) throws IOException, RoutingException
{ {
Operation op = new ConnectOperation(this.server, this.localNode, n, this.config); Operation op = new ConnectOperation(this.server, this, n, this.config);
op.execute(); op.execute();
} }
@ -240,7 +262,7 @@ public class Kademlia
*/ */
public synchronized int put(KadContent content) throws IOException public synchronized int put(KadContent content) throws IOException
{ {
StoreOperation sop = new StoreOperation(this.server, this.localNode, content, this.dht, this.config); StoreOperation sop = new StoreOperation(this.server, this, content, this.dht, this.config);
sop.execute(); sop.execute();
/* Return how many nodes the content was stored on */ /* Return how many nodes the content was stored on */
@ -279,7 +301,7 @@ public class Kademlia
} }
/* Seems like it doesn't exist in our DHT, get it from other Nodes */ /* Seems like it doesn't exist in our DHT, get it from other Nodes */
ContentLookupOperation clo = new ContentLookupOperation(server, localNode, param, this.config); ContentLookupOperation clo = new ContentLookupOperation(server, this, param, this.config);
clo.execute(); clo.execute();
return clo.getContentFound(); return clo.getContentFound();
} }
@ -291,7 +313,7 @@ public class Kademlia
*/ */
public void refresh() throws IOException public void refresh() throws IOException
{ {
new KadRefreshOperation(this.server, this.localNode, this.dht, this.config).execute(); new KadRefreshOperation(this.server, this, this.dht, this.config).execute();
} }
/** /**
@ -343,7 +365,7 @@ public class Kademlia
* @section Store Basic Kad data * @section Store Basic Kad data
*/ */
dout = new DataOutputStream(new FileOutputStream(getStateStorageFolderName(this.ownerId, this.config) + File.separator + "kad.kns")); dout = new DataOutputStream(new FileOutputStream(getStateStorageFolderName(this.ownerId, this.config) + File.separator + "kad.kns"));
new JsonSerializer<Kademlia>().write(this, dout); new JsonSerializer<KademliaNode>().write(this, dout);
/** /**
* @section Save the node state * @section Save the node state
@ -357,7 +379,7 @@ public class Kademlia
* This will cause a serialization recursion, and in turn a Stack Overflow * This will cause a serialization recursion, and in turn a Stack Overflow
*/ */
dout = new DataOutputStream(new FileOutputStream(getStateStorageFolderName(this.ownerId, this.config) + File.separator + "routingtable.kns")); dout = new DataOutputStream(new FileOutputStream(getStateStorageFolderName(this.ownerId, this.config) + File.separator + "routingtable.kns"));
new JsonRoutingTableSerializer().write(this.localNode.getRoutingTable(), dout); new JsonRoutingTableSerializer().write(this.getRoutingTable(), dout);
/** /**
* @section Save the DHT * @section Save the DHT
@ -384,6 +406,11 @@ public class Kademlia
return nodeStateFolder.toString(); return nodeStateFolder.toString();
} }
public RoutingTable getRoutingTable()
{
return this.routingTable;
}
/** /**
* Creates a string containing all data about this Kademlia instance * Creates a string containing all data about this Kademlia instance
* *
@ -403,7 +430,7 @@ public class Kademlia
sb.append("\n"); sb.append("\n");
sb.append("Routing Table: "); sb.append("Routing Table: ");
sb.append(this.localNode.getRoutingTable()); sb.append(this.getRoutingTable());
sb.append("\n"); sb.append("\n");
sb.append("\n"); sb.append("\n");

View File

@ -14,7 +14,7 @@ public class DefaultConfiguration implements KadConfiguration
private final static long RESPONSE_TIMEOUT = 1500; private final static long RESPONSE_TIMEOUT = 1500;
private final static long OPERATION_TIMEOUT = 3000; private final static long OPERATION_TIMEOUT = 3000;
private final static int CONCURRENCY = 10; private final static int CONCURRENCY = 10;
private final static int K = 10; private final static int K = 3;
private final static int RCSIZE = 3; private final static int RCSIZE = 3;
private final static int STALE = 1; private final static int STALE = 1;
private final static String LOCAL_FOLDER = "kademlia"; private final static String LOCAL_FOLDER = "kademlia";

View File

@ -1,8 +1,8 @@
package kademlia.message; package kademlia.message;
import java.io.IOException; import java.io.IOException;
import kademlia.KademliaNode;
import kademlia.core.KadServer; import kademlia.core.KadServer;
import kademlia.node.Node;
/** /**
* Receives a ConnectMessage and sends an AcknowledgeMessage as reply. * Receives a ConnectMessage and sends an AcknowledgeMessage as reply.
@ -14,9 +14,9 @@ public class ConnectReceiver implements Receiver
{ {
private final KadServer server; private final KadServer server;
private final Node localNode; private final KademliaNode localNode;
public ConnectReceiver(KadServer server, Node local) public ConnectReceiver(KadServer server, KademliaNode local)
{ {
this.server = server; this.server = server;
this.localNode = local; this.localNode = local;
@ -38,7 +38,7 @@ public class ConnectReceiver implements Receiver
this.localNode.getRoutingTable().insert(mess.getOrigin()); this.localNode.getRoutingTable().insert(mess.getOrigin());
/* Respond to the connect request */ /* Respond to the connect request */
AcknowledgeMessage msg = new AcknowledgeMessage(this.localNode); AcknowledgeMessage msg = new AcknowledgeMessage(this.localNode.getNode());
/* Reply to the connect message with an Acknowledgement */ /* Reply to the connect message with an Acknowledgement */
this.server.reply(mess.getOrigin(), msg, comm); this.server.reply(mess.getOrigin(), msg, comm);

View File

@ -1,10 +1,10 @@
package kademlia.message; package kademlia.message;
import java.io.IOException; import java.io.IOException;
import kademlia.KademliaNode;
import kademlia.core.KadConfiguration; import kademlia.core.KadConfiguration;
import kademlia.core.KadServer; import kademlia.core.KadServer;
import kademlia.dht.DHT; import kademlia.dht.DHT;
import kademlia.node.Node;
/** /**
* Responds to a ContentLookupMessage by sending a ContentMessage containing the requested content; * Responds to a ContentLookupMessage by sending a ContentMessage containing the requested content;
@ -17,11 +17,11 @@ public class ContentLookupReceiver implements Receiver
{ {
private final KadServer server; private final KadServer server;
private final Node localNode; private final KademliaNode localNode;
private final DHT dht; private final DHT dht;
private final KadConfiguration config; private final KadConfiguration config;
public ContentLookupReceiver(KadServer server, Node localNode, DHT dht, KadConfiguration config) public ContentLookupReceiver(KadServer server, KademliaNode localNode, DHT dht, KadConfiguration config)
{ {
this.server = server; this.server = server;
this.localNode = localNode; this.localNode = localNode;
@ -42,7 +42,7 @@ public class ContentLookupReceiver implements Receiver
if (this.dht.contains(msg.getParameters())) if (this.dht.contains(msg.getParameters()))
{ {
/* Return a ContentMessage with the required data */ /* Return a ContentMessage with the required data */
ContentMessage cMsg = new ContentMessage(localNode, this.dht.get(msg.getParameters())); ContentMessage cMsg = new ContentMessage(localNode.getNode(), this.dht.get(msg.getParameters()));
server.reply(msg.getOrigin(), cMsg, comm); server.reply(msg.getOrigin(), cMsg, comm);
} }
else else

View File

@ -2,10 +2,10 @@ package kademlia.message;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.IOException; import java.io.IOException;
import kademlia.KademliaNode;
import kademlia.core.KadConfiguration; import kademlia.core.KadConfiguration;
import kademlia.core.KadServer; import kademlia.core.KadServer;
import kademlia.dht.DHT; import kademlia.dht.DHT;
import kademlia.node.Node;
/** /**
* Handles creating messages and receivers * Handles creating messages and receivers
@ -16,11 +16,11 @@ import kademlia.node.Node;
public class MessageFactory public class MessageFactory
{ {
private final Node localNode; private final KademliaNode localNode;
private final DHT dht; private final DHT dht;
private final KadConfiguration config; private final KadConfiguration config;
public MessageFactory(Node local, DHT dht, KadConfiguration config) public MessageFactory(KademliaNode local, DHT dht, KadConfiguration config)
{ {
this.localNode = local; this.localNode = local;
this.dht = dht; this.dht = dht;
@ -64,12 +64,10 @@ public class MessageFactory
return new ContentLookupReceiver(server, this.localNode, this.dht, this.config); return new ContentLookupReceiver(server, this.localNode, this.dht, this.config);
case NodeLookupMessage.CODE: case NodeLookupMessage.CODE:
return new NodeLookupReceiver(server, this.localNode, this.config); return new NodeLookupReceiver(server, this.localNode, this.config);
case SimpleMessage.CODE:
return new SimpleReceiver();
case StoreContentMessage.CODE: case StoreContentMessage.CODE:
return new StoreContentReceiver(server, this.localNode, this.dht); return new StoreContentReceiver(server, this.localNode, this.dht);
default: default:
System.out.println("No reveiver found for message. Code: " + code); System.out.println("No receiver found for message. Code: " + code);
return new SimpleReceiver(); return new SimpleReceiver();
} }
} }

View File

@ -2,6 +2,7 @@ package kademlia.message;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import kademlia.KademliaNode;
import kademlia.core.KadConfiguration; import kademlia.core.KadConfiguration;
import kademlia.core.KadServer; import kademlia.core.KadServer;
import kademlia.node.Node; import kademlia.node.Node;
@ -16,10 +17,10 @@ public class NodeLookupReceiver implements Receiver
{ {
private final KadServer server; private final KadServer server;
private final Node localNode; private final KademliaNode localNode;
private final KadConfiguration config; private final KadConfiguration config;
public NodeLookupReceiver(KadServer server, Node local, KadConfiguration config) public NodeLookupReceiver(KadServer server, KademliaNode local, KadConfiguration config)
{ {
this.server = server; this.server = server;
this.localNode = local; this.localNode = local;
@ -48,7 +49,7 @@ public class NodeLookupReceiver implements Receiver
List<Node> nodes = this.localNode.getRoutingTable().findClosest(msg.getLookupId(), this.config.k()); List<Node> nodes = this.localNode.getRoutingTable().findClosest(msg.getLookupId(), this.config.k());
/* Respond to the NodeLookupMessage */ /* Respond to the NodeLookupMessage */
Message reply = new NodeReplyMessage(this.localNode, nodes); Message reply = new NodeReplyMessage(this.localNode.getNode(), nodes);
/* Let the Server send the reply */ /* Let the Server send the reply */
this.server.reply(origin, reply, comm); this.server.reply(origin, reply, comm);

View File

@ -89,6 +89,6 @@ public class NodeReplyMessage implements Message
@Override @Override
public String toString() public String toString()
{ {
return "ConnectMessage[origin NodeId=" + origin.getNodeId() + "]"; return "NodeReplyMessage[origin NodeId=" + origin.getNodeId() + "]";
} }
} }

View File

@ -1,9 +1,9 @@
package kademlia.message; package kademlia.message;
import java.io.IOException; import java.io.IOException;
import kademlia.KademliaNode;
import kademlia.core.KadServer; import kademlia.core.KadServer;
import kademlia.dht.DHT; import kademlia.dht.DHT;
import kademlia.node.Node;
/** /**
* Receiver for incoming StoreContentMessage * Receiver for incoming StoreContentMessage
@ -15,10 +15,10 @@ public class StoreContentReceiver implements Receiver
{ {
private final KadServer server; private final KadServer server;
private final Node localNode; private final KademliaNode localNode;
private final DHT dht; private final DHT dht;
public StoreContentReceiver(KadServer server, Node localNode, DHT dht) public StoreContentReceiver(KadServer server, KademliaNode localNode, DHT dht)
{ {
this.server = server; this.server = server;
this.localNode = localNode; this.localNode = localNode;

View File

@ -7,10 +7,9 @@ import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
import kademlia.message.Streamable; import kademlia.message.Streamable;
import kademlia.routing.RoutingTable;
/** /**
* A Node in the Kademlia network * A Node in the Kademlia network - Contains basic node network information.
* *
* @author Joshua Kissoon * @author Joshua Kissoon
* @since 20140202 * @since 20140202
@ -24,15 +23,12 @@ public class Node implements Streamable
private int port; private int port;
private final String strRep; private final String strRep;
private transient RoutingTable routingTable;
public Node(NodeId nid, InetAddress ip, int port) public Node(NodeId nid, InetAddress ip, int port)
{ {
this.nodeId = nid; this.nodeId = nid;
this.inetAddress = ip; this.inetAddress = ip;
this.port = port; this.port = port;
this.strRep = this.nodeId.toString(); this.strRep = this.nodeId.toString();
this.routingTable = new RoutingTable(this);
} }
/** /**
@ -109,24 +105,6 @@ public class Node implements Streamable
this.port = in.readInt(); this.port = in.readInt();
} }
/**
* @return The RoutingTable of this Node
*/
public RoutingTable getRoutingTable()
{
return this.routingTable;
}
/**
* Sets a new routing table to this node, mainly used when we retrieve the node from a saved state
*
* @param tbl The routing table to use
*/
public void setRoutingTable(RoutingTable tbl)
{
this.routingTable = tbl;
}
@Override @Override
public boolean equals(Object o) public boolean equals(Object o)
{ {

View File

@ -1,9 +1,9 @@
package kademlia.operation; package kademlia.operation;
import java.io.IOException; import java.io.IOException;
import kademlia.KademliaNode;
import kademlia.core.KadConfiguration; import kademlia.core.KadConfiguration;
import kademlia.core.KadServer; import kademlia.core.KadServer;
import kademlia.node.Node;
import kademlia.node.NodeId; import kademlia.node.NodeId;
/** /**
@ -17,10 +17,10 @@ public class BucketRefreshOperation implements Operation
{ {
private final KadServer server; private final KadServer server;
private final Node localNode; private final KademliaNode localNode;
private final KadConfiguration config; private final KadConfiguration config;
public BucketRefreshOperation(KadServer server, Node localNode, KadConfiguration config) public BucketRefreshOperation(KadServer server, KademliaNode localNode, KadConfiguration config)
{ {
this.server = server; this.server = server;
this.localNode = localNode; this.localNode = localNode;
@ -43,7 +43,7 @@ public class BucketRefreshOperation implements Operation
for (int i = 1; i < NodeId.ID_LENGTH; i++) for (int i = 1; i < NodeId.ID_LENGTH; i++)
{ {
/* Construct a NodeId that is i bits away from the current node Id */ /* Construct a NodeId that is i bits away from the current node Id */
final NodeId current = this.localNode.getNodeId().generateNodeIdByDistance(i); final NodeId current = this.localNode.getNode().getNodeId().generateNodeIdByDistance(i);
/* Run the Node Lookup Operation, each in a different thread to speed up things */ /* Run the Node Lookup Operation, each in a different thread to speed up things */
new Thread() new Thread()
@ -53,7 +53,7 @@ public class BucketRefreshOperation implements Operation
{ {
try try
{ {
new NodeLookupOperation(server, localNode, localNode.getNodeId(), BucketRefreshOperation.this.config).execute(); new NodeLookupOperation(server, localNode, localNode.getNode().getNodeId(), BucketRefreshOperation.this.config).execute();
} }
catch (IOException e) catch (IOException e)
{ {

View File

@ -7,6 +7,7 @@ package kademlia.operation;
import kademlia.message.Receiver; import kademlia.message.Receiver;
import java.io.IOException; import java.io.IOException;
import kademlia.KademliaNode;
import kademlia.core.KadConfiguration; import kademlia.core.KadConfiguration;
import kademlia.core.KadServer; import kademlia.core.KadServer;
import kademlia.exceptions.RoutingException; import kademlia.exceptions.RoutingException;
@ -21,7 +22,7 @@ public class ConnectOperation implements Operation, Receiver
public static final int MAX_CONNECT_ATTEMPTS = 5; // Try 5 times to connect to a node public static final int MAX_CONNECT_ATTEMPTS = 5; // Try 5 times to connect to a node
private final KadServer server; private final KadServer server;
private final Node localNode; private final KademliaNode localNode;
private final Node bootstrapNode; private final Node bootstrapNode;
private final KadConfiguration config; private final KadConfiguration config;
@ -34,7 +35,7 @@ public class ConnectOperation implements Operation, Receiver
* @param bootstrap Node to use to bootstrap the local node onto the network * @param bootstrap Node to use to bootstrap the local node onto the network
* @param config * @param config
*/ */
public ConnectOperation(KadServer server, Node local, Node bootstrap, KadConfiguration config) public ConnectOperation(KadServer server, KademliaNode local, Node bootstrap, KadConfiguration config)
{ {
this.server = server; this.server = server;
this.localNode = local; this.localNode = local;
@ -50,7 +51,7 @@ public class ConnectOperation implements Operation, Receiver
/* Contact the bootstrap node */ /* Contact the bootstrap node */
this.error = true; this.error = true;
this.attempts = 0; this.attempts = 0;
Message m = new ConnectMessage(this.localNode); Message m = new ConnectMessage(this.localNode.getNode());
/* Send a connect message to the bootstrap node */ /* Send a connect message to the bootstrap node */
server.sendMessage(this.bootstrapNode, m, this); server.sendMessage(this.bootstrapNode, m, this);
@ -77,7 +78,7 @@ public class ConnectOperation implements Operation, Receiver
} }
/* Perform lookup for our own ID to get nodes close to us */ /* Perform lookup for our own ID to get nodes close to us */
Operation lookup = new NodeLookupOperation(this.server, this.localNode, this.localNode.getNodeId(), this.config); Operation lookup = new NodeLookupOperation(this.server, this.localNode, this.localNode.getNode().getNodeId(), this.config);
lookup.execute(); lookup.execute();
/** /**
@ -127,7 +128,7 @@ public class ConnectOperation implements Operation, Receiver
{ {
if (++this.attempts < MAX_CONNECT_ATTEMPTS) if (++this.attempts < MAX_CONNECT_ATTEMPTS)
{ {
this.server.sendMessage(this.bootstrapNode, new ConnectMessage(this.localNode), this); this.server.sendMessage(this.bootstrapNode, new ConnectMessage(this.localNode.getNode()), this);
} }
else else
{ {

View File

@ -10,6 +10,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.SortedMap; import java.util.SortedMap;
import java.util.TreeMap; import java.util.TreeMap;
import kademlia.KademliaNode;
import kademlia.dht.GetParameter; import kademlia.dht.GetParameter;
import kademlia.core.KadConfiguration; import kademlia.core.KadConfiguration;
import kademlia.core.KadServer; import kademlia.core.KadServer;
@ -40,7 +41,7 @@ public class ContentLookupOperation implements Operation, Receiver
private static final Byte FAILED = (byte) 0x03; private static final Byte FAILED = (byte) 0x03;
private final KadServer server; private final KadServer server;
private final Node localNode; private final KademliaNode localNode;
private StorageEntry contentFound = null; private StorageEntry contentFound = null;
private final KadConfiguration config; private final KadConfiguration config;
@ -67,10 +68,10 @@ public class ContentLookupOperation implements Operation, Receiver
* @param params The parameters to search for the content which we need to find * @param params The parameters to search for the content which we need to find
* @param config * @param config
*/ */
public ContentLookupOperation(KadServer server, Node localNode, GetParameter params, KadConfiguration config) public ContentLookupOperation(KadServer server, KademliaNode localNode, GetParameter params, KadConfiguration config)
{ {
/* Construct our lookup message */ /* Construct our lookup message */
this.lookupMessage = new ContentLookupMessage(localNode, params); this.lookupMessage = new ContentLookupMessage(localNode.getNode(), params);
this.server = server; this.server = server;
this.localNode = localNode; this.localNode = localNode;
@ -94,7 +95,7 @@ public class ContentLookupOperation implements Operation, Receiver
try try
{ {
/* Set the local node as already asked */ /* Set the local node as already asked */
nodes.put(this.localNode, ASKED); nodes.put(this.localNode.getNode(), ASKED);
this.addNodes(this.localNode.getRoutingTable().getAllNodes()); this.addNodes(this.localNode.getRoutingTable().getAllNodes());

View File

@ -2,6 +2,7 @@ package kademlia.operation;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import kademlia.KademliaNode;
import kademlia.core.KadConfiguration; import kademlia.core.KadConfiguration;
import kademlia.core.KadServer; import kademlia.core.KadServer;
import kademlia.dht.DHT; import kademlia.dht.DHT;
@ -21,11 +22,11 @@ public class ContentRefreshOperation implements Operation
{ {
private final KadServer server; private final KadServer server;
private final Node localNode; private final KademliaNode localNode;
private final DHT dht; private final DHT dht;
private final KadConfiguration config; private final KadConfiguration config;
public ContentRefreshOperation(KadServer server, Node localNode, DHT dht, KadConfiguration config) public ContentRefreshOperation(KadServer server, KademliaNode localNode, DHT dht, KadConfiguration config)
{ {
this.server = server; this.server = server;
this.localNode = localNode; this.localNode = localNode;
@ -66,7 +67,7 @@ public class ContentRefreshOperation implements Operation
List<Node> closestNodes = this.localNode.getRoutingTable().findClosest(e.getKey(), this.config.k()); List<Node> closestNodes = this.localNode.getRoutingTable().findClosest(e.getKey(), this.config.k());
/* Create the message */ /* Create the message */
Message msg = new StoreContentMessage(this.localNode, dht.get(e)); Message msg = new StoreContentMessage(this.localNode.getNode(), dht.get(e));
/*Store the message on all of the K-Nodes*/ /*Store the message on all of the K-Nodes*/
for (Node n : closestNodes) for (Node n : closestNodes)

View File

@ -1,10 +1,10 @@
package kademlia.operation; package kademlia.operation;
import java.io.IOException; import java.io.IOException;
import kademlia.KademliaNode;
import kademlia.core.KadConfiguration; import kademlia.core.KadConfiguration;
import kademlia.core.KadServer; import kademlia.core.KadServer;
import kademlia.dht.DHT; import kademlia.dht.DHT;
import kademlia.node.Node;
/** /**
* An operation that handles refreshing the entire Kademlia Systems including buckets and content * An operation that handles refreshing the entire Kademlia Systems including buckets and content
@ -16,11 +16,11 @@ public class KadRefreshOperation implements Operation
{ {
private final KadServer server; private final KadServer server;
private final Node localNode; private final KademliaNode localNode;
private final DHT dht; private final DHT dht;
private final KadConfiguration config; private final KadConfiguration config;
public KadRefreshOperation(KadServer server, Node localNode, DHT dht, KadConfiguration config) public KadRefreshOperation(KadServer server, KademliaNode localNode, DHT dht, KadConfiguration config)
{ {
this.server = server; this.server = server;
this.localNode = localNode; this.localNode = localNode;

View File

@ -8,6 +8,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
import kademlia.KademliaNode;
import kademlia.core.KadConfiguration; import kademlia.core.KadConfiguration;
import kademlia.core.KadServer; import kademlia.core.KadServer;
import kademlia.exceptions.RoutingException; import kademlia.exceptions.RoutingException;
@ -37,7 +38,7 @@ public class NodeLookupOperation implements Operation, Receiver
private static final String FAILED = "Failed"; private static final String FAILED = "Failed";
private final KadServer server; private final KadServer server;
private final Node localNode; private final KademliaNode localNode;
private final NodeId lookupId; private final NodeId lookupId;
private final KadConfiguration config; private final KadConfiguration config;
@ -63,14 +64,14 @@ public class NodeLookupOperation implements Operation, Receiver
* @param lookupId The ID for which to find nodes close to * @param lookupId The ID for which to find nodes close to
* @param config * @param config
*/ */
public NodeLookupOperation(KadServer server, Node localNode, NodeId lookupId, KadConfiguration config) public NodeLookupOperation(KadServer server, KademliaNode localNode, NodeId lookupId, KadConfiguration config)
{ {
this.server = server; this.server = server;
this.localNode = localNode; this.localNode = localNode;
this.lookupId = lookupId; this.lookupId = lookupId;
this.config = config; this.config = config;
this.lookupMessage = new NodeLookupMessage(localNode, lookupId); this.lookupMessage = new NodeLookupMessage(localNode.getNode(), lookupId);
/** /**
* We initialize a TreeMap to store nodes. * We initialize a TreeMap to store nodes.
@ -93,9 +94,9 @@ public class NodeLookupOperation implements Operation, Receiver
error = true; error = true;
/* Set the local node as already asked */ /* Set the local node as already asked */
nodes.put(this.localNode, ASKED); nodes.put(this.localNode.getNode(), ASKED);
this.addNodes(this.localNode.getRoutingTable().getAllNodes()); this.addNodes(this.localNode.getRoutingTable().findClosest(this.lookupId, this.config.k()));
/* If we haven't finished as yet, wait for a maximum of config.operationTimeout() time */ /* If we haven't finished as yet, wait for a maximum of config.operationTimeout() time */
int totalTimeWaited = 0; int totalTimeWaited = 0;
@ -118,21 +119,9 @@ public class NodeLookupOperation implements Operation, Receiver
throw new RoutingException("Lookup Timeout."); throw new RoutingException("Lookup Timeout.");
} }
/** /* Now after we've finished, we would have an idea of offline nodes, lets update our routing table */
* @deprecated - replaced by the above code this.localNode.getRoutingTable().setUnresponsiveContacts(this.getFailedNodes());
* We just keep this code in case any problems are encountered later
*/
// if (!this.askNodesorFinish())
// {
// /* If we haven't finished as yet, wait for a maximum of OPERATION_TIMEOUT time */
// wait(this.config.operationTimeout());
//
// /* If we still haven't received any responses by then, do a routing timeout */
// if (error)
// {
// throw new RoutingException("Lookup Timeout.");
// }
// }
} }
catch (InterruptedException e) catch (InterruptedException e)
{ {
@ -321,4 +310,19 @@ public class NodeLookupOperation implements Operation, Receiver
this.askNodesorFinish(); this.askNodesorFinish();
} }
public List<Node> getFailedNodes()
{
List<Node> failedNodes = new ArrayList<>();
for (Map.Entry<Node, String> e : this.nodes.entrySet())
{
if (e.getValue().equals(FAILED))
{
failedNodes.add(e.getKey());
}
}
return failedNodes;
}
} }

View File

@ -2,6 +2,7 @@ package kademlia.operation;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import kademlia.KademliaNode;
import kademlia.core.KadConfiguration; import kademlia.core.KadConfiguration;
import kademlia.core.KadServer; import kademlia.core.KadServer;
import kademlia.dht.DHT; import kademlia.dht.DHT;
@ -21,7 +22,7 @@ public class StoreOperation implements Operation
{ {
private final KadServer server; private final KadServer server;
private final Node localNode; private final KademliaNode localNode;
private final KadContent content; private final KadContent content;
private final DHT localDht; private final DHT localDht;
private final KadConfiguration config; private final KadConfiguration config;
@ -33,7 +34,7 @@ public class StoreOperation implements Operation
* @param localDht The local DHT * @param localDht The local DHT
* @param config * @param config
*/ */
public StoreOperation(KadServer server, Node localNode, KadContent content, DHT localDht, KadConfiguration config) public StoreOperation(KadServer server, KademliaNode localNode, KadContent content, DHT localDht, KadConfiguration config)
{ {
this.server = server; this.server = server;
this.localNode = localNode; this.localNode = localNode;
@ -51,7 +52,7 @@ public class StoreOperation implements Operation
List<Node> nodes = ndlo.getClosestNodes(); List<Node> nodes = ndlo.getClosestNodes();
/* Create the message */ /* Create the message */
Message msg = new StoreContentMessage(this.localNode, new StorageEntry(this.content)); Message msg = new StoreContentMessage(this.localNode.getNode(), new StorageEntry(this.content));
/*Store the message on all of the K-Nodes*/ /*Store the message on all of the K-Nodes*/
for (Node n : nodes) for (Node n : nodes)

View File

@ -15,12 +15,19 @@ import kademlia.node.Node;
public class KadBucket implements Bucket public class KadBucket implements Bucket
{ {
/* How deep is this bucket in the Routing Table */
private final int depth; private final int depth;
/* Contacts stored in this routing table */
private final Map<Contact, Contact> contacts; private final Map<Contact, Contact> contacts;
/* A set of last seen contacts that can replace any current contact that is unresponsive */
private final Map<Contact, Contact> replacementCache;
{ {
contacts = new TreeMap<>(new ContactLastSeenComparator()); contacts = new TreeMap<>(new ContactLastSeenComparator());
replacementCache = new TreeMap<>(new ContactLastSeenComparator());
} }
/** /**
@ -94,9 +101,9 @@ public class KadBucket implements Bucket
} }
@Override @Override
public List<Contact> getContacts() public synchronized List<Contact> getContacts()
{ {
return new ArrayList<>(this.contacts.values()); return (this.contacts.isEmpty()) ? new ArrayList<>() : new ArrayList<>(this.contacts.values());
} }
@Override @Override

View File

@ -2,6 +2,7 @@ package kademlia.routing;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import kademlia.core.KadConfiguration;
import kademlia.node.Node; import kademlia.node.Node;
import kademlia.node.NodeId; import kademlia.node.NodeId;
@ -17,9 +18,12 @@ public class RoutingTable
private final Node localNode; // The current node private final Node localNode; // The current node
private transient Bucket[] buckets; private transient Bucket[] buckets;
public RoutingTable(Node localNode) private final KadConfiguration config;
public RoutingTable(Node localNode, KadConfiguration config)
{ {
this.localNode = localNode; this.localNode = localNode;
this.config = config;
/* Initialize all of the buckets to a specific depth */ /* Initialize all of the buckets to a specific depth */
this.initialize(); this.initialize();
@ -99,7 +103,7 @@ public class RoutingTable
* *
* @return List A List of contacts closest to target * @return List A List of contacts closest to target
*/ */
public final List<Node> findClosest(NodeId target, int numNodesRequired) public synchronized final List<Node> findClosest(NodeId target, int numNodesRequired)
{ {
List<Node> closest = new ArrayList<>(numNodesRequired); List<Node> closest = new ArrayList<>(numNodesRequired);
@ -232,14 +236,35 @@ public class RoutingTable
this.buckets = buckets; this.buckets = buckets;
} }
/**
* Method used by operations to notify the routing table of any contacts that have been unresponsive.
*
* @param contacts The set of unresponsive contacts
*/
public void setUnresponsiveContacts(List<Node> contacts)
{
if (contacts.isEmpty())
{
return;
}
System.out.println("Unresponsive contacts: ");
for (Node n : contacts)
{
System.out.println(n);
}
}
@Override @Override
public final String toString() public synchronized final String toString()
{ {
StringBuilder sb = new StringBuilder("\nPrinting Routing Table Started ***************** \n"); StringBuilder sb = new StringBuilder("\nPrinting Routing Table Started ***************** \n");
int totalContacts = 0;
for (Bucket b : this.buckets) for (Bucket b : this.buckets)
{ {
if (b.numContacts() > 0) if (b.numContacts() > 0)
{ {
totalContacts += b.numContacts();
sb.append("# nodes in Bucket with depth "); sb.append("# nodes in Bucket with depth ");
sb.append(b.getDepth()); sb.append(b.getDepth());
sb.append(": "); sb.append(": ");
@ -249,6 +274,11 @@ public class RoutingTable
sb.append("\n"); sb.append("\n");
} }
} }
sb.append("\nTotal Contacts: ");
sb.append(totalContacts);
sb.append("\n\n");
sb.append("Printing Routing Table Ended ******************** "); sb.append("Printing Routing Table Ended ******************** ");
return sb.toString(); return sb.toString();

View File

@ -3,7 +3,7 @@ package kademlia.tests;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
import kademlia.core.DefaultConfiguration; import kademlia.core.DefaultConfiguration;
import kademlia.Kademlia; import kademlia.KademliaNode;
import kademlia.core.KadConfiguration; import kademlia.core.KadConfiguration;
import kademlia.node.NodeId; import kademlia.node.NodeId;
@ -21,11 +21,11 @@ public class AutoRefreshOperationTest
try try
{ {
/* Setting up 2 Kad networks */ /* Setting up 2 Kad networks */
final Kademlia kad1 = new Kademlia("JoshuaK", new NodeId("ASF456789djem45674DH"), 12049); final KademliaNode kad1 = new KademliaNode("JoshuaK", new NodeId("ASF456789djem45674DH"), 12049);
final Kademlia kad2 = new Kademlia("Crystal", new NodeId("AJDHR678947584567464"), 4585); final KademliaNode kad2 = new KademliaNode("Crystal", new NodeId("AJDHR678947584567464"), 4585);
final Kademlia kad3 = new Kademlia("Shameer", new NodeId("AS84k6789KRNS45KFJ8W"), 8104); final KademliaNode kad3 = new KademliaNode("Shameer", new NodeId("AS84k6789KRNS45KFJ8W"), 8104);
final Kademlia kad4 = new Kademlia("Lokesh.", new NodeId("ASF45678947A845674GG"), 8335); final KademliaNode kad4 = new KademliaNode("Lokesh.", new NodeId("ASF45678947A845674GG"), 8335);
final Kademlia kad5 = new Kademlia("Chandu.", new NodeId("AS84kUD894758456dyrj"), 13345); final KademliaNode kad5 = new KademliaNode("Chandu.", new NodeId("AS84kUD894758456dyrj"), 13345);
/* Connecting nodes */ /* Connecting nodes */
System.out.println("Connecting Nodes"); System.out.println("Connecting Nodes");

View File

@ -3,7 +3,7 @@ package kademlia.tests;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
import kademlia.core.DefaultConfiguration; import kademlia.core.DefaultConfiguration;
import kademlia.Kademlia; import kademlia.KademliaNode;
import kademlia.core.KadConfiguration; import kademlia.core.KadConfiguration;
import kademlia.node.NodeId; import kademlia.node.NodeId;
@ -21,9 +21,9 @@ public class AutoRefreshOperationTest2
try try
{ {
/* Setting up 2 Kad networks */ /* Setting up 2 Kad networks */
final Kademlia kad1 = new Kademlia("JoshuaK", new NodeId("ASF456789djem4567463"), 12049); final KademliaNode kad1 = new KademliaNode("JoshuaK", new NodeId("ASF456789djem4567463"), 12049);
final Kademlia kad2 = new Kademlia("Crystal", new NodeId("AS84k678DJRW84567465"), 4585); final KademliaNode kad2 = new KademliaNode("Crystal", new NodeId("AS84k678DJRW84567465"), 4585);
final Kademlia kad3 = new Kademlia("Shameer", new NodeId("AS84k67894758456746A"), 8104); final KademliaNode kad3 = new KademliaNode("Shameer", new NodeId("AS84k67894758456746A"), 8104);
/* Connecting nodes */ /* Connecting nodes */
System.out.println("Connecting Nodes"); System.out.println("Connecting Nodes");

View File

@ -2,7 +2,7 @@ package kademlia.tests;
import java.io.IOException; import java.io.IOException;
import kademlia.dht.GetParameter; import kademlia.dht.GetParameter;
import kademlia.Kademlia; import kademlia.KademliaNode;
import kademlia.dht.StorageEntry; import kademlia.dht.StorageEntry;
import kademlia.exceptions.ContentNotFoundException; import kademlia.exceptions.ContentNotFoundException;
import kademlia.node.NodeId; import kademlia.node.NodeId;
@ -21,9 +21,9 @@ public class ContentSendingTest
try try
{ {
/* Setting up 2 Kad networks */ /* Setting up 2 Kad networks */
Kademlia kad1 = new Kademlia("JoshuaK", new NodeId("ASF45678947584567467"), 7574); KademliaNode kad1 = new KademliaNode("JoshuaK", new NodeId("ASF45678947584567467"), 7574);
System.out.println("Created Node Kad 1: " + kad1.getNode().getNodeId()); System.out.println("Created Node Kad 1: " + kad1.getNode().getNodeId());
Kademlia kad2 = new Kademlia("Crystal", new NodeId("ASERTKJDHGVHERJHGFLK"), 7572); KademliaNode kad2 = new KademliaNode("Crystal", new NodeId("ASERTKJDHGVHERJHGFLK"), 7572);
System.out.println("Created Node Kad 2: " + kad2.getNode().getNodeId()); System.out.println("Created Node Kad 2: " + kad2.getNode().getNodeId());
kad2.bootstrap(kad1.getNode()); kad2.bootstrap(kad1.getNode());

View File

@ -2,7 +2,7 @@ package kademlia.tests;
import java.io.IOException; import java.io.IOException;
import kademlia.dht.GetParameter; import kademlia.dht.GetParameter;
import kademlia.Kademlia; import kademlia.KademliaNode;
import kademlia.dht.StorageEntry; import kademlia.dht.StorageEntry;
import kademlia.exceptions.ContentNotFoundException; import kademlia.exceptions.ContentNotFoundException;
import kademlia.node.NodeId; import kademlia.node.NodeId;
@ -21,9 +21,9 @@ public class ContentUpdatingTest
try try
{ {
/* Setting up 2 Kad networks */ /* Setting up 2 Kad networks */
Kademlia kad1 = new Kademlia("JoshuaK", new NodeId("ASF45678947584567467"), 7574); KademliaNode kad1 = new KademliaNode("JoshuaK", new NodeId("ASF45678947584567467"), 7574);
System.out.println("Created Node Kad 1: " + kad1.getNode().getNodeId()); System.out.println("Created Node Kad 1: " + kad1.getNode().getNodeId());
Kademlia kad2 = new Kademlia("Crystal", new NodeId("ASERTKJDHGVHERJHGFLK"), 7572); KademliaNode kad2 = new KademliaNode("Crystal", new NodeId("ASERTKJDHGVHERJHGFLK"), 7572);
System.out.println("Created Node Kad 2: " + kad2.getNode().getNodeId()); System.out.println("Created Node Kad 2: " + kad2.getNode().getNodeId());
kad2.bootstrap(kad1.getNode()); kad2.bootstrap(kad1.getNode());

View File

@ -1,7 +1,7 @@
package kademlia.tests; package kademlia.tests;
import java.io.IOException; import java.io.IOException;
import kademlia.Kademlia; import kademlia.KademliaNode;
import kademlia.node.NodeId; import kademlia.node.NodeId;
/** /**
@ -18,10 +18,10 @@ public class NodeConnectionTest
try try
{ {
/* Setting up 2 Kad networks */ /* Setting up 2 Kad networks */
Kademlia kad1 = new Kademlia("JoshuaK", new NodeId("ASF45678947584567467"), 7574); KademliaNode kad1 = new KademliaNode("JoshuaK", new NodeId("ASF45678947584567467"), 7574);
System.out.println("Created Node Kad 1: " + kad1.getNode().getNodeId()); System.out.println("Created Node Kad 1: " + kad1.getNode().getNodeId());
Kademlia kad2 = new Kademlia("Crystal", new NodeId("ASERTKJDHGVHERJHGFLK"), 7572); KademliaNode kad2 = new KademliaNode("Crystal", new NodeId("ASERTKJDHGVHERJHGFLK"), 7572);
//NodeId diff12 = kad1.getNode().getNodeId().xor(kad2.getNode().getNodeId()); //NodeId diff12 = kad1.getNode().getNodeId().xor(kad2.getNode().getNodeId());
System.out.println("Created Node Kad 2: " + 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(kad1.getNode().getNodeId() + " ^ " + kad2.getNode().getNodeId() + " = " + diff12);
@ -37,7 +37,7 @@ public class NodeConnectionTest
// System.out.println(kad2.getNode().getRoutingTable()); // System.out.println(kad2.getNode().getRoutingTable());
/* Creating a new node 3 and connecting it to 1, hoping it'll get onto 2 also */ /* Creating a new node 3 and connecting it to 1, hoping it'll get onto 2 also */
Kademlia kad3 = new Kademlia("Jessica", new NodeId("ASERTKJDOLKMNBVFR45G"), 7783); KademliaNode kad3 = new KademliaNode("Jessica", new NodeId("ASERTKJDOLKMNBVFR45G"), 7783);
System.out.println("\n\n\n\n\n\nCreated Node Kad 3: " + kad3.getNode().getNodeId()); System.out.println("\n\n\n\n\n\nCreated Node Kad 3: " + kad3.getNode().getNodeId());
System.out.println("Connecting Kad 3 and Kad 2"); System.out.println("Connecting Kad 3 and Kad 2");
@ -47,20 +47,20 @@ public class NodeConnectionTest
// NodeId diff31 = kad1.getNode().getNodeId().xor(kad3.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 1 distance: " + diff31.getFirstSetBitIndex());
// System.out.println("Kad 3 - Kad 2 distance: " + diff32.getFirstSetBitIndex()); // System.out.println("Kad 3 - Kad 2 distance: " + diff32.getFirstSetBitIndex());
Kademlia kad4 = new Kademlia("Sandy", new NodeId("ASERTK85OLKMN85FR4SS"), 7789); KademliaNode kad4 = new KademliaNode("Sandy", new NodeId("ASERTK85OLKMN85FR4SS"), 7789);
System.out.println("\n\n\n\n\n\nCreated Node Kad 4: " + kad4.getNode().getNodeId()); System.out.println("\n\n\n\n\n\nCreated Node Kad 4: " + kad4.getNode().getNodeId());
System.out.println("Connecting Kad 4 and Kad 2"); System.out.println("Connecting Kad 4 and Kad 2");
kad4.bootstrap(kad2.getNode()); kad4.bootstrap(kad2.getNode());
System.out.println("\n\nKad 1: " + kad1.getNode().getNodeId() + " Routing Table: "); System.out.println("\n\nKad 1: " + kad1.getNode().getNodeId() + " Routing Table: ");
System.out.println(kad1.getNode().getRoutingTable()); System.out.println(kad1.getRoutingTable());
System.out.println("\n\nKad 2: " + kad2.getNode().getNodeId() + " Routing Table: "); System.out.println("\n\nKad 2: " + kad2.getNode().getNodeId() + " Routing Table: ");
System.out.println(kad2.getNode().getRoutingTable()); System.out.println(kad2.getRoutingTable());
System.out.println("\n\nKad 3: " + kad3.getNode().getNodeId() + " Routing Table: "); System.out.println("\n\nKad 3: " + kad3.getNode().getNodeId() + " Routing Table: ");
System.out.println(kad3.getNode().getRoutingTable()); System.out.println(kad3.getRoutingTable());
System.out.println("\n\nKad 4: " + kad4.getNode().getNodeId() + " Routing Table: "); System.out.println("\n\nKad 4: " + kad4.getNode().getNodeId() + " Routing Table: ");
System.out.println(kad4.getNode().getRoutingTable()); System.out.println(kad4.getRoutingTable());
} }
catch (IOException e) catch (IOException e)
{ {

View File

@ -2,7 +2,7 @@ package kademlia.tests;
import java.io.IOException; import java.io.IOException;
import kademlia.dht.GetParameter; import kademlia.dht.GetParameter;
import kademlia.Kademlia; import kademlia.KademliaNode;
import kademlia.dht.StorageEntry; import kademlia.dht.StorageEntry;
import kademlia.exceptions.ContentNotFoundException; import kademlia.exceptions.ContentNotFoundException;
import kademlia.node.NodeId; import kademlia.node.NodeId;
@ -21,8 +21,8 @@ public class RefreshOperationTest
try try
{ {
/* Setting up 2 Kad networks */ /* Setting up 2 Kad networks */
Kademlia kad1 = new Kademlia("JoshuaK", new NodeId("ASF45678947584567467"), 7574); KademliaNode kad1 = new KademliaNode("JoshuaK", new NodeId("ASF45678947584567467"), 7574);
Kademlia kad2 = new Kademlia("Crystal", new NodeId("ASERTKJDHGVHERJHGFLK"), 7572); KademliaNode kad2 = new KademliaNode("Crystal", new NodeId("ASERTKJDHGVHERJHGFLK"), 7572);
kad2.bootstrap(kad1.getNode()); kad2.bootstrap(kad1.getNode());
/* Lets create the content and share it */ /* Lets create the content and share it */

View File

@ -1,6 +1,6 @@
package kademlia.tests; package kademlia.tests;
import kademlia.Kademlia; import kademlia.KademliaNode;
import kademlia.node.NodeId; import kademlia.node.NodeId;
import kademlia.routing.RoutingTable; import kademlia.routing.RoutingTable;
@ -18,13 +18,13 @@ public class RoutingTableSimulation
try try
{ {
/* Setting up 2 Kad networks */ /* Setting up 2 Kad networks */
Kademlia kad1 = new Kademlia("JoshuaK", new NodeId("ASF45678947584567463"), 12049); KademliaNode kad1 = new KademliaNode("JoshuaK", new NodeId("ASF45678947584567463"), 12049);
Kademlia kad2 = new Kademlia("Crystal", new NodeId("ASF45678947584567464"), 4585); KademliaNode kad2 = new KademliaNode("Crystal", new NodeId("ASF45678947584567464"), 4585);
Kademlia kad3 = new Kademlia("Shameer", new NodeId("ASF45678947584567465"), 8104); KademliaNode kad3 = new KademliaNode("Shameer", new NodeId("ASF45678947584567465"), 8104);
Kademlia kad4 = new Kademlia("Lokesh", new NodeId("ASF45678947584567466"), 8335); KademliaNode kad4 = new KademliaNode("Lokesh", new NodeId("ASF45678947584567466"), 8335);
Kademlia kad5 = new Kademlia("Chandu", new NodeId("ASF45678947584567467"), 13345); KademliaNode kad5 = new KademliaNode("Chandu", new NodeId("ASF45678947584567467"), 13345);
RoutingTable rt = kad1.getNode().getRoutingTable(); RoutingTable rt = kad1.getRoutingTable();
rt.insert(kad2.getNode()); rt.insert(kad2.getNode());
rt.insert(kad3.getNode()); rt.insert(kad3.getNode());
@ -36,6 +36,9 @@ public class RoutingTableSimulation
rt.insert(kad3.getNode()); rt.insert(kad3.getNode());
System.out.println(rt); System.out.println(rt);
/* Lets shut down a node and then try putting a content on the network. We'll then see how the un-responsive contacts work */
} }
catch (IllegalStateException e) catch (IllegalStateException e)
{ {

View File

@ -0,0 +1,125 @@
package kademlia.tests;
import java.io.IOException;
import kademlia.KademliaNode;
import kademlia.dht.KadContent;
import kademlia.node.NodeId;
/**
* Testing how the routing table works and it's state after different operations
*
* @author Joshua Kissoon
* @since 20140426
*/
public class RoutingTableStateTesting
{
KademliaNode kad0, kad1, kad2, kad3, kad4, kad5, kad6, kad7, kad8, kad9;
public RoutingTableStateTesting()
{
try
{
/* Setting up 2 Kad networks */
kad0 = new KademliaNode("user0", new NodeId("HRF456789SD584567460"), 1334);
kad1 = new KademliaNode("user1", new NodeId("ASF456789475DS567461"), 1209);
kad2 = new KademliaNode("user2", new NodeId("AFG45678947584567462"), 4585);
kad3 = new KademliaNode("user3", new NodeId("FSF45J38947584567463"), 8104);
kad4 = new KademliaNode("user4", new NodeId("ASF45678947584567464"), 8335);
kad5 = new KademliaNode("user5", new NodeId("GHF4567894DR84567465"), 13345);
kad6 = new KademliaNode("user6", new NodeId("ASF45678947584567466"), 12049);
kad7 = new KademliaNode("user7", new NodeId("AE345678947584567467"), 14585);
kad8 = new KademliaNode("user8", new NodeId("ASAA5678947584567468"), 18104);
kad9 = new KademliaNode("user9", new NodeId("ASF456789475845674U9"), 18335);
kad1.bootstrap(kad0.getNode());
kad2.bootstrap(kad0.getNode());
kad3.bootstrap(kad0.getNode());
kad4.bootstrap(kad0.getNode());
kad5.bootstrap(kad0.getNode());
kad6.bootstrap(kad0.getNode());
kad7.bootstrap(kad0.getNode());
kad8.bootstrap(kad0.getNode());
kad9.bootstrap(kad0.getNode());
/* Lets shut down a node and then try putting a content on the network. We'll then see how the un-responsive contacts work */
}
catch (IllegalStateException e)
{
}
catch (Exception e)
{
e.printStackTrace();
}
}
public KadContent putContent(String content, KademliaNode owner)
{
DHTContentImpl c = null;
try
{
c = new DHTContentImpl(kad2.getOwnerId(), "Some Data");
owner.put(c);
return c;
}
catch (IOException e)
{
System.err.println("Error whiles putting content " + content + " from owner: " + owner.getOwnerId());
}
return c;
}
public void shutdownKad(KademliaNode kad)
{
try
{
kad.shutdown(false);
}
catch (IOException ex)
{
System.err.println("Error whiles shutting down node with owner: " + kad.getOwnerId());
}
}
public void printRoutingTables()
{
System.out.println(kad0.getRoutingTable());
System.out.println(kad1.getRoutingTable());
System.out.println(kad2.getRoutingTable());
System.out.println(kad3.getRoutingTable());
System.out.println(kad4.getRoutingTable());
System.out.println(kad5.getRoutingTable());
System.out.println(kad6.getRoutingTable());
System.out.println(kad7.getRoutingTable());
System.out.println(kad8.getRoutingTable());
System.out.println(kad9.getRoutingTable());
}
public void printStorage()
{
System.out.println(kad0.getDHT());
System.out.println(kad1.getDHT());
System.out.println(kad2.getDHT());
System.out.println(kad3.getDHT());
System.out.println(kad4.getDHT());
System.out.println(kad5.getDHT());
System.out.println(kad6.getDHT());
System.out.println(kad7.getDHT());
System.out.println(kad8.getDHT());
System.out.println(kad9.getDHT());
}
public static void main(String[] args)
{
RoutingTableStateTesting rtss = new RoutingTableStateTesting();
rtss.printRoutingTables();
/* Lets shut down a node to test the node removal operation */
rtss.shutdownKad(rtss.kad3);
rtss.putContent("Content owned by kad0", rtss.kad0);
rtss.printStorage();
}
}

View File

@ -1,6 +1,6 @@
package kademlia.tests; package kademlia.tests;
import kademlia.Kademlia; import kademlia.KademliaNode;
import kademlia.node.NodeId; import kademlia.node.NodeId;
/** /**
@ -17,11 +17,11 @@ public class SaveStateTest
try try
{ {
/* Setting up 2 Kad networks */ /* Setting up 2 Kad networks */
Kademlia kad1 = new Kademlia("JoshuaK", new NodeId("ASF45678947584567463"), 12049); KademliaNode kad1 = new KademliaNode("JoshuaK", new NodeId("ASF45678947584567463"), 12049);
Kademlia kad2 = new Kademlia("Crystal", new NodeId("ASF45678947584567464"), 4585); KademliaNode kad2 = new KademliaNode("Crystal", new NodeId("ASF45678947584567464"), 4585);
Kademlia kad3 = new Kademlia("Shameer", new NodeId("ASF45678947584567465"), 8104); KademliaNode kad3 = new KademliaNode("Shameer", new NodeId("ASF45678947584567465"), 8104);
Kademlia kad4 = new Kademlia("Lokesh", new NodeId("ASF45678947584567466"), 8335); KademliaNode kad4 = new KademliaNode("Lokesh", new NodeId("ASF45678947584567466"), 8335);
Kademlia kad5 = new Kademlia("Chandu", new NodeId("ASF45678947584567467"), 13345); KademliaNode kad5 = new KademliaNode("Chandu", new NodeId("ASF45678947584567467"), 13345);
/* Connecting 2 to 1 */ /* Connecting 2 to 1 */
System.out.println("Connecting Nodes 1 & 2"); System.out.println("Connecting Nodes 1 & 2");
@ -76,7 +76,7 @@ public class SaveStateTest
kad1.shutdown(true); kad1.shutdown(true);
System.out.println("\n\n\nReloading Kad instance from file"); System.out.println("\n\n\nReloading Kad instance from file");
Kademlia kadR2 = Kademlia.loadFromFile("JoshuaK"); KademliaNode kadR2 = KademliaNode.loadFromFile("JoshuaK");
System.out.println(kadR2); System.out.println(kadR2);
} }
catch (IllegalStateException e) catch (IllegalStateException e)

View File

@ -1,6 +1,6 @@
package kademlia.tests; package kademlia.tests;
import kademlia.Kademlia; import kademlia.KademliaNode;
import kademlia.dht.GetParameter; import kademlia.dht.GetParameter;
import kademlia.dht.StorageEntry; import kademlia.dht.StorageEntry;
import kademlia.node.NodeId; import kademlia.node.NodeId;
@ -20,8 +20,8 @@ public class SaveStateTest2
try try
{ {
/* Setting up 2 Kad networks */ /* Setting up 2 Kad networks */
Kademlia kad1 = new Kademlia("JoshuaK", new NodeId("ASF45678947584567463"), 12049); KademliaNode kad1 = new KademliaNode("JoshuaK", new NodeId("ASF45678947584567463"), 12049);
Kademlia kad2 = new Kademlia("Crystal", new NodeId("ASF45678947584567464"), 4585); KademliaNode kad2 = new KademliaNode("Crystal", new NodeId("ASF45678947584567464"), 4585);
/* Connecting 2 to 1 */ /* Connecting 2 to 1 */
System.out.println("Connecting Nodes 1 & 2"); System.out.println("Connecting Nodes 1 & 2");
@ -46,7 +46,7 @@ public class SaveStateTest2
kad1.shutdown(true); kad1.shutdown(true);
System.out.println("\n\n\nReloading Kad instance from file"); System.out.println("\n\n\nReloading Kad instance from file");
kad1 = Kademlia.loadFromFile("JoshuaK"); kad1 = KademliaNode.loadFromFile("JoshuaK");
kad1.bootstrap(kad2.getNode()); kad1.bootstrap(kad2.getNode());
System.out.println(kad2); System.out.println(kad2);

View File

@ -1,7 +1,7 @@
package kademlia.tests; package kademlia.tests;
import java.io.IOException; import java.io.IOException;
import kademlia.Kademlia; import kademlia.KademliaNode;
import kademlia.message.SimpleMessage; import kademlia.message.SimpleMessage;
import kademlia.node.NodeId; import kademlia.node.NodeId;
import kademlia.message.SimpleReceiver; import kademlia.message.SimpleReceiver;
@ -19,8 +19,8 @@ public class SimpleMessageTest
{ {
try try
{ {
Kademlia kad1 = new Kademlia("Joshua", new NodeId("12345678901234567890"), 7574); KademliaNode kad1 = new KademliaNode("Joshua", new NodeId("12345678901234567890"), 7574);
Kademlia kad2 = new Kademlia("Crystal", new NodeId("12345678901234567891"), 7572); KademliaNode kad2 = new KademliaNode("Crystal", new NodeId("12345678901234567891"), 7572);
kad1.getServer().sendMessage(kad2.getNode(), new SimpleMessage("Some Message"), new SimpleReceiver()); kad1.getServer().sendMessage(kad2.getNode(), new SimpleMessage("Some Message"), new SimpleReceiver());
} }