From 54ac3fe74010a08db0f8ca35b6312ec31aa820f2 Mon Sep 17 00:00:00 2001 From: Joshua Kissoon Date: Mon, 28 Apr 2014 15:25:07 +0530 Subject: [PATCH] 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 --- .../{Kademlia.java => KademliaNode.java} | 81 ++++++++---- src/kademlia/core/DefaultConfiguration.java | 2 +- src/kademlia/message/ConnectReceiver.java | 8 +- .../message/ContentLookupReceiver.java | 8 +- src/kademlia/message/MessageFactory.java | 10 +- src/kademlia/message/NodeLookupReceiver.java | 7 +- src/kademlia/message/NodeReplyMessage.java | 2 +- .../message/StoreContentReceiver.java | 6 +- src/kademlia/node/Node.java | 24 +--- .../operation/BucketRefreshOperation.java | 10 +- src/kademlia/operation/ConnectOperation.java | 11 +- .../operation/ContentLookupOperation.java | 9 +- .../operation/ContentRefreshOperation.java | 7 +- .../operation/KadRefreshOperation.java | 6 +- .../operation/NodeLookupOperation.java | 78 +++++------ src/kademlia/operation/StoreOperation.java | 7 +- src/kademlia/routing/KadBucket.java | 11 +- src/kademlia/routing/RoutingTable.java | 36 ++++- .../tests/AutoRefreshOperationTest.java | 12 +- .../tests/AutoRefreshOperationTest2.java | 8 +- src/kademlia/tests/ContentSendingTest.java | 6 +- src/kademlia/tests/ContentUpdatingTest.java | 6 +- src/kademlia/tests/NodeConnectionTest.java | 18 +-- src/kademlia/tests/RefreshOperationTest.java | 6 +- .../tests/RoutingTableSimulation.java | 17 ++- .../tests/RoutingTableStateTesting.java | 125 ++++++++++++++++++ src/kademlia/tests/SaveStateTest.java | 14 +- src/kademlia/tests/SaveStateTest2.java | 8 +- src/kademlia/tests/SimpleMessageTest.java | 6 +- 29 files changed, 363 insertions(+), 186 deletions(-) rename src/kademlia/{Kademlia.java => KademliaNode.java} (81%) create mode 100644 src/kademlia/tests/RoutingTableStateTesting.java diff --git a/src/kademlia/Kademlia.java b/src/kademlia/KademliaNode.java similarity index 81% rename from src/kademlia/Kademlia.java rename to src/kademlia/KademliaNode.java index 9b596f9..04b6c02 100644 --- a/src/kademlia/Kademlia.java +++ b/src/kademlia/KademliaNode.java @@ -34,7 +34,7 @@ import kademlia.util.serializer.JsonRoutingTableSerializer; 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 * @since 20140215 @@ -43,7 +43,7 @@ import kademlia.util.serializer.JsonSerializer; * @todo Handle IPv6 Addresses * */ -public class Kademlia +public class KademliaNode { /* Kademlia Attributes */ @@ -53,6 +53,7 @@ public class Kademlia private final transient Node localNode; private final transient KadServer server; private final transient DHT dht; + private transient RoutingTable routingTable; private final transient Timer timer; private final int udpPort; private transient KadConfiguration config; @@ -66,24 +67,26 @@ public class Kademlia * The instance is bootstraped to an existing network by specifying the * address of a bootstrap node in the network. * - * @param ownerId The Name of this node used for storage - * @param localNode The Local Node for this Kad instance - * @param udpPort The UDP port to use for routing messages - * @param dht The DHT for this instance + * @param ownerId The Name of this node used for storage + * @param localNode The Local Node for this Kad instance + * @param udpPort The UDP port to use for routing messages + * @param dht The DHT for this instance * @param config + * @param routingTable * * @throws IOException If an error occurred while reading id or local map * from disk or a network error occurred while * 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.udpPort = udpPort; this.localNode = localNode; this.dht = dht; 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.timer = new Timer(true); @@ -97,7 +100,7 @@ public class Kademlia try { /* Runs a DHT RefreshOperation */ - Kademlia.this.refresh(); + KademliaNode.this.refresh(); } 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, - new DHT(ownerId, new DefaultConfiguration()), new DefaultConfiguration()); + this( + 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.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.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; @@ -155,7 +178,7 @@ public class Kademlia * @section Read Basic Kad data */ din = new DataInputStream(new FileInputStream(getStateStorageFolderName(ownerId, iconfig) + File.separator + "kad.kns")); - Kademlia ikad = new JsonSerializer().read(din); + KademliaNode ikad = new JsonSerializer().read(din); /** * @section Read the routing table @@ -168,7 +191,6 @@ public class Kademlia */ din = new DataInputStream(new FileInputStream(getStateStorageFolderName(ownerId, iconfig) + File.separator + "node.kns")); Node inode = new JsonSerializer().read(din); - inode.setRoutingTable(irtbl); /** * @section Read the DHT @@ -177,7 +199,7 @@ public class Kademlia DHT idht = new JsonDHTSerializer().read(din); 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 { - Operation op = new ConnectOperation(this.server, this.localNode, n, this.config); + Operation op = new ConnectOperation(this.server, this, n, this.config); op.execute(); } @@ -240,7 +262,7 @@ public class Kademlia */ 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(); /* 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 */ - ContentLookupOperation clo = new ContentLookupOperation(server, localNode, param, this.config); + ContentLookupOperation clo = new ContentLookupOperation(server, this, param, this.config); clo.execute(); return clo.getContentFound(); } @@ -291,7 +313,7 @@ public class Kademlia */ 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 */ dout = new DataOutputStream(new FileOutputStream(getStateStorageFolderName(this.ownerId, this.config) + File.separator + "kad.kns")); - new JsonSerializer().write(this, dout); + new JsonSerializer().write(this, dout); /** * @section Save the node state @@ -357,7 +379,7 @@ public class Kademlia * 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")); - new JsonRoutingTableSerializer().write(this.localNode.getRoutingTable(), dout); + new JsonRoutingTableSerializer().write(this.getRoutingTable(), dout); /** * @section Save the DHT @@ -384,6 +406,11 @@ public class Kademlia return nodeStateFolder.toString(); } + public RoutingTable getRoutingTable() + { + return this.routingTable; + } + /** * Creates a string containing all data about this Kademlia instance * @@ -403,7 +430,7 @@ public class Kademlia sb.append("\n"); sb.append("Routing Table: "); - sb.append(this.localNode.getRoutingTable()); + sb.append(this.getRoutingTable()); sb.append("\n"); sb.append("\n"); diff --git a/src/kademlia/core/DefaultConfiguration.java b/src/kademlia/core/DefaultConfiguration.java index 0d6343e..7b31564 100644 --- a/src/kademlia/core/DefaultConfiguration.java +++ b/src/kademlia/core/DefaultConfiguration.java @@ -14,7 +14,7 @@ public class DefaultConfiguration implements KadConfiguration private final static long RESPONSE_TIMEOUT = 1500; private final static long OPERATION_TIMEOUT = 3000; 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 STALE = 1; private final static String LOCAL_FOLDER = "kademlia"; diff --git a/src/kademlia/message/ConnectReceiver.java b/src/kademlia/message/ConnectReceiver.java index b1ae4fe..236a2d1 100644 --- a/src/kademlia/message/ConnectReceiver.java +++ b/src/kademlia/message/ConnectReceiver.java @@ -1,8 +1,8 @@ package kademlia.message; import java.io.IOException; +import kademlia.KademliaNode; import kademlia.core.KadServer; -import kademlia.node.Node; /** * Receives a ConnectMessage and sends an AcknowledgeMessage as reply. @@ -14,9 +14,9 @@ public class ConnectReceiver implements Receiver { 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.localNode = local; @@ -38,7 +38,7 @@ public class ConnectReceiver implements Receiver this.localNode.getRoutingTable().insert(mess.getOrigin()); /* 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 */ this.server.reply(mess.getOrigin(), msg, comm); diff --git a/src/kademlia/message/ContentLookupReceiver.java b/src/kademlia/message/ContentLookupReceiver.java index bf40e44..75d4383 100644 --- a/src/kademlia/message/ContentLookupReceiver.java +++ b/src/kademlia/message/ContentLookupReceiver.java @@ -1,10 +1,10 @@ package kademlia.message; import java.io.IOException; +import kademlia.KademliaNode; import kademlia.core.KadConfiguration; import kademlia.core.KadServer; import kademlia.dht.DHT; -import kademlia.node.Node; /** * 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 Node localNode; + private final KademliaNode localNode; private final DHT dht; 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.localNode = localNode; @@ -42,7 +42,7 @@ public class ContentLookupReceiver implements Receiver if (this.dht.contains(msg.getParameters())) { /* 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); } else diff --git a/src/kademlia/message/MessageFactory.java b/src/kademlia/message/MessageFactory.java index 2b0c8a9..a4ee16b 100644 --- a/src/kademlia/message/MessageFactory.java +++ b/src/kademlia/message/MessageFactory.java @@ -2,10 +2,10 @@ package kademlia.message; import java.io.DataInputStream; import java.io.IOException; +import kademlia.KademliaNode; import kademlia.core.KadConfiguration; import kademlia.core.KadServer; import kademlia.dht.DHT; -import kademlia.node.Node; /** * Handles creating messages and receivers @@ -16,11 +16,11 @@ import kademlia.node.Node; public class MessageFactory { - private final Node localNode; + private final KademliaNode localNode; private final DHT dht; private final KadConfiguration config; - public MessageFactory(Node local, DHT dht, KadConfiguration config) + public MessageFactory(KademliaNode local, DHT dht, KadConfiguration config) { this.localNode = local; this.dht = dht; @@ -64,12 +64,10 @@ public class MessageFactory return new ContentLookupReceiver(server, this.localNode, this.dht, this.config); case NodeLookupMessage.CODE: return new NodeLookupReceiver(server, this.localNode, this.config); - case SimpleMessage.CODE: - return new SimpleReceiver(); case StoreContentMessage.CODE: return new StoreContentReceiver(server, this.localNode, this.dht); default: - System.out.println("No reveiver found for message. Code: " + code); + System.out.println("No receiver found for message. Code: " + code); return new SimpleReceiver(); } } diff --git a/src/kademlia/message/NodeLookupReceiver.java b/src/kademlia/message/NodeLookupReceiver.java index 79a1c87..7f4ac0b 100644 --- a/src/kademlia/message/NodeLookupReceiver.java +++ b/src/kademlia/message/NodeLookupReceiver.java @@ -2,6 +2,7 @@ package kademlia.message; import java.io.IOException; import java.util.List; +import kademlia.KademliaNode; import kademlia.core.KadConfiguration; import kademlia.core.KadServer; import kademlia.node.Node; @@ -16,10 +17,10 @@ public class NodeLookupReceiver implements Receiver { private final KadServer server; - private final Node localNode; + private final KademliaNode localNode; private final KadConfiguration config; - public NodeLookupReceiver(KadServer server, Node local, KadConfiguration config) + public NodeLookupReceiver(KadServer server, KademliaNode local, KadConfiguration config) { this.server = server; this.localNode = local; @@ -48,7 +49,7 @@ public class NodeLookupReceiver implements Receiver List nodes = this.localNode.getRoutingTable().findClosest(msg.getLookupId(), this.config.k()); /* 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 */ this.server.reply(origin, reply, comm); diff --git a/src/kademlia/message/NodeReplyMessage.java b/src/kademlia/message/NodeReplyMessage.java index 993cf13..07a1f72 100644 --- a/src/kademlia/message/NodeReplyMessage.java +++ b/src/kademlia/message/NodeReplyMessage.java @@ -89,6 +89,6 @@ public class NodeReplyMessage implements Message @Override public String toString() { - return "ConnectMessage[origin NodeId=" + origin.getNodeId() + "]"; + return "NodeReplyMessage[origin NodeId=" + origin.getNodeId() + "]"; } } diff --git a/src/kademlia/message/StoreContentReceiver.java b/src/kademlia/message/StoreContentReceiver.java index 49facb6..e170444 100644 --- a/src/kademlia/message/StoreContentReceiver.java +++ b/src/kademlia/message/StoreContentReceiver.java @@ -1,9 +1,9 @@ package kademlia.message; import java.io.IOException; +import kademlia.KademliaNode; import kademlia.core.KadServer; import kademlia.dht.DHT; -import kademlia.node.Node; /** * Receiver for incoming StoreContentMessage @@ -15,10 +15,10 @@ public class StoreContentReceiver implements Receiver { private final KadServer server; - private final Node localNode; + private final KademliaNode localNode; private final DHT dht; - public StoreContentReceiver(KadServer server, Node localNode, DHT dht) + public StoreContentReceiver(KadServer server, KademliaNode localNode, DHT dht) { this.server = server; this.localNode = localNode; diff --git a/src/kademlia/node/Node.java b/src/kademlia/node/Node.java index 6dd7e16..8f0f30b 100644 --- a/src/kademlia/node/Node.java +++ b/src/kademlia/node/Node.java @@ -7,10 +7,9 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; 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 * @since 20140202 @@ -24,15 +23,12 @@ public class Node implements Streamable private int port; private final String strRep; - private transient RoutingTable routingTable; - public Node(NodeId nid, InetAddress ip, int port) { this.nodeId = nid; this.inetAddress = ip; this.port = port; this.strRep = this.nodeId.toString(); - this.routingTable = new RoutingTable(this); } /** @@ -109,24 +105,6 @@ public class Node implements Streamable 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 public boolean equals(Object o) { diff --git a/src/kademlia/operation/BucketRefreshOperation.java b/src/kademlia/operation/BucketRefreshOperation.java index 60c6d7f..4a1d70f 100644 --- a/src/kademlia/operation/BucketRefreshOperation.java +++ b/src/kademlia/operation/BucketRefreshOperation.java @@ -1,9 +1,9 @@ package kademlia.operation; import java.io.IOException; +import kademlia.KademliaNode; import kademlia.core.KadConfiguration; import kademlia.core.KadServer; -import kademlia.node.Node; import kademlia.node.NodeId; /** @@ -17,10 +17,10 @@ public class BucketRefreshOperation implements Operation { private final KadServer server; - private final Node localNode; + private final KademliaNode localNode; private final KadConfiguration config; - public BucketRefreshOperation(KadServer server, Node localNode, KadConfiguration config) + public BucketRefreshOperation(KadServer server, KademliaNode localNode, KadConfiguration config) { this.server = server; this.localNode = localNode; @@ -43,7 +43,7 @@ public class BucketRefreshOperation implements Operation for (int i = 1; i < NodeId.ID_LENGTH; i++) { /* 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 */ new Thread() @@ -53,7 +53,7 @@ public class BucketRefreshOperation implements Operation { 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) { diff --git a/src/kademlia/operation/ConnectOperation.java b/src/kademlia/operation/ConnectOperation.java index 9e65b24..7d2efbc 100644 --- a/src/kademlia/operation/ConnectOperation.java +++ b/src/kademlia/operation/ConnectOperation.java @@ -7,6 +7,7 @@ package kademlia.operation; import kademlia.message.Receiver; import java.io.IOException; +import kademlia.KademliaNode; import kademlia.core.KadConfiguration; import kademlia.core.KadServer; 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 private final KadServer server; - private final Node localNode; + private final KademliaNode localNode; private final Node bootstrapNode; 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 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.localNode = local; @@ -50,7 +51,7 @@ public class ConnectOperation implements Operation, Receiver /* Contact the bootstrap node */ this.error = true; this.attempts = 0; - Message m = new ConnectMessage(this.localNode); + Message m = new ConnectMessage(this.localNode.getNode()); /* Send a connect message to the bootstrap node */ 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 */ - 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(); /** @@ -127,7 +128,7 @@ public class ConnectOperation implements Operation, Receiver { 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 { diff --git a/src/kademlia/operation/ContentLookupOperation.java b/src/kademlia/operation/ContentLookupOperation.java index f7eac5b..dab7968 100644 --- a/src/kademlia/operation/ContentLookupOperation.java +++ b/src/kademlia/operation/ContentLookupOperation.java @@ -10,6 +10,7 @@ import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; +import kademlia.KademliaNode; import kademlia.dht.GetParameter; import kademlia.core.KadConfiguration; import kademlia.core.KadServer; @@ -40,7 +41,7 @@ public class ContentLookupOperation implements Operation, Receiver private static final Byte FAILED = (byte) 0x03; private final KadServer server; - private final Node localNode; + private final KademliaNode localNode; private StorageEntry contentFound = null; 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 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 */ - this.lookupMessage = new ContentLookupMessage(localNode, params); + this.lookupMessage = new ContentLookupMessage(localNode.getNode(), params); this.server = server; this.localNode = localNode; @@ -94,7 +95,7 @@ public class ContentLookupOperation implements Operation, Receiver try { /* Set the local node as already asked */ - nodes.put(this.localNode, ASKED); + nodes.put(this.localNode.getNode(), ASKED); this.addNodes(this.localNode.getRoutingTable().getAllNodes()); diff --git a/src/kademlia/operation/ContentRefreshOperation.java b/src/kademlia/operation/ContentRefreshOperation.java index 90c6744..8fac0d8 100644 --- a/src/kademlia/operation/ContentRefreshOperation.java +++ b/src/kademlia/operation/ContentRefreshOperation.java @@ -2,6 +2,7 @@ package kademlia.operation; import java.io.IOException; import java.util.List; +import kademlia.KademliaNode; import kademlia.core.KadConfiguration; import kademlia.core.KadServer; import kademlia.dht.DHT; @@ -21,11 +22,11 @@ public class ContentRefreshOperation implements Operation { private final KadServer server; - private final Node localNode; + private final KademliaNode localNode; private final DHT dht; 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.localNode = localNode; @@ -66,7 +67,7 @@ public class ContentRefreshOperation implements Operation List closestNodes = this.localNode.getRoutingTable().findClosest(e.getKey(), this.config.k()); /* 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*/ for (Node n : closestNodes) diff --git a/src/kademlia/operation/KadRefreshOperation.java b/src/kademlia/operation/KadRefreshOperation.java index d928543..7904d45 100644 --- a/src/kademlia/operation/KadRefreshOperation.java +++ b/src/kademlia/operation/KadRefreshOperation.java @@ -1,10 +1,10 @@ package kademlia.operation; import java.io.IOException; +import kademlia.KademliaNode; import kademlia.core.KadConfiguration; import kademlia.core.KadServer; import kademlia.dht.DHT; -import kademlia.node.Node; /** * 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 Node localNode; + private final KademliaNode localNode; private final DHT dht; 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.localNode = localNode; diff --git a/src/kademlia/operation/NodeLookupOperation.java b/src/kademlia/operation/NodeLookupOperation.java index 152b55b..2f905af 100644 --- a/src/kademlia/operation/NodeLookupOperation.java +++ b/src/kademlia/operation/NodeLookupOperation.java @@ -8,6 +8,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; +import kademlia.KademliaNode; import kademlia.core.KadConfiguration; import kademlia.core.KadServer; import kademlia.exceptions.RoutingException; @@ -35,14 +36,14 @@ public class NodeLookupOperation implements Operation, Receiver private static final String AWAITING = "Awaiting"; private static final String ASKED = "Asked"; private static final String FAILED = "Failed"; - + private final KadServer server; - private final Node localNode; + private final KademliaNode localNode; private final NodeId lookupId; private final KadConfiguration config; - + private boolean error; - + private final Message lookupMessage; // Message sent to each peer private final Map nodes; @@ -51,7 +52,7 @@ public class NodeLookupOperation implements Operation, Receiver /* Used to sort nodes */ private final Comparator comparator; - + { messagesTransiting = new HashMap<>(); @@ -63,14 +64,14 @@ public class NodeLookupOperation implements Operation, Receiver * @param lookupId The ID for which to find nodes close to * @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.localNode = localNode; this.lookupId = lookupId; this.config = config; - - this.lookupMessage = new NodeLookupMessage(localNode, lookupId); + + this.lookupMessage = new NodeLookupMessage(localNode.getNode(), lookupId); /** * We initialize a TreeMap to store nodes. @@ -93,9 +94,9 @@ public class NodeLookupOperation implements Operation, Receiver error = true; /* Set the local node as already asked */ - nodes.put(this.localNode, ASKED); - - this.addNodes(this.localNode.getRoutingTable().getAllNodes()); + nodes.put(this.localNode.getNode(), ASKED); + + 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 */ int totalTimeWaited = 0; @@ -118,28 +119,16 @@ public class NodeLookupOperation implements Operation, Receiver throw new RoutingException("Lookup Timeout."); } - /** - * @deprecated - replaced by the above code - * 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."); -// } -// } + /* Now after we've finished, we would have an idea of offline nodes, lets update our routing table */ + this.localNode.getRoutingTable().setUnresponsiveContacts(this.getFailedNodes()); + } catch (InterruptedException e) { throw new RuntimeException(e); } } - + public List getClosestNodes() { return this.closestNodes(ASKED); @@ -183,7 +172,7 @@ public class NodeLookupOperation implements Operation, Receiver /* Get unqueried nodes among the K closest seen that have not FAILED */ List unasked = this.closestNodesNotFailed(UNASKED); - + if (unasked.isEmpty() && this.messagesTransiting.isEmpty()) { /* We have no unasked nodes nor any messages in transit, we're finished! */ @@ -198,9 +187,9 @@ public class NodeLookupOperation implements Operation, Receiver for (int i = 0; (this.messagesTransiting.size() < this.config.maxConcurrentMessagesTransiting()) && (i < unasked.size()); i++) { Node n = (Node) unasked.get(i); - + int comm = server.sendMessage(n, lookupMessage, this); - + this.nodes.put(n, AWAITING); this.messagesTransiting.put(comm, n); } @@ -218,7 +207,7 @@ public class NodeLookupOperation implements Operation, Receiver { List closestNodes = new ArrayList<>(this.config.k()); int remainingSpaces = this.config.k(); - + for (Map.Entry e : this.nodes.entrySet()) { if (status.equals(e.getValue())) @@ -231,7 +220,7 @@ public class NodeLookupOperation implements Operation, Receiver } } } - + return closestNodes; } @@ -247,7 +236,7 @@ public class NodeLookupOperation implements Operation, Receiver { List closestNodes = new ArrayList<>(this.config.k()); int remainingSpaces = this.config.k(); - + for (Map.Entry e : this.nodes.entrySet()) { if (!FAILED.equals(e.getValue())) @@ -257,14 +246,14 @@ public class NodeLookupOperation implements Operation, Receiver /* We got one with the required status, now add it */ closestNodes.add(e.getKey()); } - + if (--remainingSpaces == 0) { break; } } } - + return closestNodes; } @@ -308,7 +297,7 @@ public class NodeLookupOperation implements Operation, Receiver { /* Get the node associated with this communication */ Node n = this.messagesTransiting.get(new Integer(comm)); - + if (n == null) { throw new UnknownMessageException("Unknown comm: " + comm); @@ -318,7 +307,22 @@ public class NodeLookupOperation implements Operation, Receiver this.nodes.put(n, FAILED); this.localNode.getRoutingTable().remove(n); this.messagesTransiting.remove(comm); - + this.askNodesorFinish(); } + + public List getFailedNodes() + { + List failedNodes = new ArrayList<>(); + + for (Map.Entry e : this.nodes.entrySet()) + { + if (e.getValue().equals(FAILED)) + { + failedNodes.add(e.getKey()); + } + } + + return failedNodes; + } } diff --git a/src/kademlia/operation/StoreOperation.java b/src/kademlia/operation/StoreOperation.java index d80bfb2..c43eae2 100644 --- a/src/kademlia/operation/StoreOperation.java +++ b/src/kademlia/operation/StoreOperation.java @@ -2,6 +2,7 @@ package kademlia.operation; import java.io.IOException; import java.util.List; +import kademlia.KademliaNode; import kademlia.core.KadConfiguration; import kademlia.core.KadServer; import kademlia.dht.DHT; @@ -21,7 +22,7 @@ public class StoreOperation implements Operation { private final KadServer server; - private final Node localNode; + private final KademliaNode localNode; private final KadContent content; private final DHT localDht; private final KadConfiguration config; @@ -33,7 +34,7 @@ public class StoreOperation implements Operation * @param localDht The local DHT * @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.localNode = localNode; @@ -51,7 +52,7 @@ public class StoreOperation implements Operation List nodes = ndlo.getClosestNodes(); /* 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*/ for (Node n : nodes) diff --git a/src/kademlia/routing/KadBucket.java b/src/kademlia/routing/KadBucket.java index e320138..fa7dbce 100644 --- a/src/kademlia/routing/KadBucket.java +++ b/src/kademlia/routing/KadBucket.java @@ -15,12 +15,19 @@ import kademlia.node.Node; public class KadBucket implements Bucket { + /* How deep is this bucket in the Routing Table */ private final int depth; + + /* Contacts stored in this routing table */ private final Map contacts; + /* A set of last seen contacts that can replace any current contact that is unresponsive */ + private final Map replacementCache; + { contacts = new TreeMap<>(new ContactLastSeenComparator()); + replacementCache = new TreeMap<>(new ContactLastSeenComparator()); } /** @@ -94,9 +101,9 @@ public class KadBucket implements Bucket } @Override - public List getContacts() + public synchronized List getContacts() { - return new ArrayList<>(this.contacts.values()); + return (this.contacts.isEmpty()) ? new ArrayList<>() : new ArrayList<>(this.contacts.values()); } @Override diff --git a/src/kademlia/routing/RoutingTable.java b/src/kademlia/routing/RoutingTable.java index 23c2c4a..52c04fe 100644 --- a/src/kademlia/routing/RoutingTable.java +++ b/src/kademlia/routing/RoutingTable.java @@ -2,6 +2,7 @@ package kademlia.routing; import java.util.ArrayList; import java.util.List; +import kademlia.core.KadConfiguration; import kademlia.node.Node; import kademlia.node.NodeId; @@ -17,9 +18,12 @@ public class RoutingTable private final Node localNode; // The current node private transient Bucket[] buckets; - public RoutingTable(Node localNode) + private final KadConfiguration config; + + public RoutingTable(Node localNode, KadConfiguration config) { this.localNode = localNode; + this.config = config; /* Initialize all of the buckets to a specific depth */ this.initialize(); @@ -99,7 +103,7 @@ public class RoutingTable * * @return List A List of contacts closest to target */ - public final List findClosest(NodeId target, int numNodesRequired) + public synchronized final List findClosest(NodeId target, int numNodesRequired) { List closest = new ArrayList<>(numNodesRequired); @@ -232,14 +236,35 @@ public class RoutingTable 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 contacts) + { + if (contacts.isEmpty()) + { + return; + } + + System.out.println("Unresponsive contacts: "); + for (Node n : contacts) + { + System.out.println(n); + } + } + @Override - public final String toString() + public synchronized final String toString() { StringBuilder sb = new StringBuilder("\nPrinting Routing Table Started ***************** \n"); + int totalContacts = 0; for (Bucket b : this.buckets) { if (b.numContacts() > 0) { + totalContacts += b.numContacts(); sb.append("# nodes in Bucket with depth "); sb.append(b.getDepth()); sb.append(": "); @@ -249,6 +274,11 @@ public class RoutingTable sb.append("\n"); } } + + sb.append("\nTotal Contacts: "); + sb.append(totalContacts); + sb.append("\n\n"); + sb.append("Printing Routing Table Ended ******************** "); return sb.toString(); diff --git a/src/kademlia/tests/AutoRefreshOperationTest.java b/src/kademlia/tests/AutoRefreshOperationTest.java index d1d4b0d..592a397 100644 --- a/src/kademlia/tests/AutoRefreshOperationTest.java +++ b/src/kademlia/tests/AutoRefreshOperationTest.java @@ -3,7 +3,7 @@ package kademlia.tests; import java.util.Timer; import java.util.TimerTask; import kademlia.core.DefaultConfiguration; -import kademlia.Kademlia; +import kademlia.KademliaNode; import kademlia.core.KadConfiguration; import kademlia.node.NodeId; @@ -21,11 +21,11 @@ public class AutoRefreshOperationTest try { /* Setting up 2 Kad networks */ - final Kademlia kad1 = new Kademlia("JoshuaK", new NodeId("ASF456789djem45674DH"), 12049); - final Kademlia kad2 = new Kademlia("Crystal", new NodeId("AJDHR678947584567464"), 4585); - final Kademlia kad3 = new Kademlia("Shameer", new NodeId("AS84k6789KRNS45KFJ8W"), 8104); - final Kademlia kad4 = new Kademlia("Lokesh.", new NodeId("ASF45678947A845674GG"), 8335); - final Kademlia kad5 = new Kademlia("Chandu.", new NodeId("AS84kUD894758456dyrj"), 13345); + final KademliaNode kad1 = new KademliaNode("JoshuaK", new NodeId("ASF456789djem45674DH"), 12049); + final KademliaNode kad2 = new KademliaNode("Crystal", new NodeId("AJDHR678947584567464"), 4585); + final KademliaNode kad3 = new KademliaNode("Shameer", new NodeId("AS84k6789KRNS45KFJ8W"), 8104); + final KademliaNode kad4 = new KademliaNode("Lokesh.", new NodeId("ASF45678947A845674GG"), 8335); + final KademliaNode kad5 = new KademliaNode("Chandu.", new NodeId("AS84kUD894758456dyrj"), 13345); /* Connecting nodes */ System.out.println("Connecting Nodes"); diff --git a/src/kademlia/tests/AutoRefreshOperationTest2.java b/src/kademlia/tests/AutoRefreshOperationTest2.java index 4eedbae..a14dbd6 100644 --- a/src/kademlia/tests/AutoRefreshOperationTest2.java +++ b/src/kademlia/tests/AutoRefreshOperationTest2.java @@ -3,7 +3,7 @@ package kademlia.tests; import java.util.Timer; import java.util.TimerTask; import kademlia.core.DefaultConfiguration; -import kademlia.Kademlia; +import kademlia.KademliaNode; import kademlia.core.KadConfiguration; import kademlia.node.NodeId; @@ -21,9 +21,9 @@ public class AutoRefreshOperationTest2 try { /* Setting up 2 Kad networks */ - final Kademlia kad1 = new Kademlia("JoshuaK", new NodeId("ASF456789djem4567463"), 12049); - final Kademlia kad2 = new Kademlia("Crystal", new NodeId("AS84k678DJRW84567465"), 4585); - final Kademlia kad3 = new Kademlia("Shameer", new NodeId("AS84k67894758456746A"), 8104); + final KademliaNode kad1 = new KademliaNode("JoshuaK", new NodeId("ASF456789djem4567463"), 12049); + final KademliaNode kad2 = new KademliaNode("Crystal", new NodeId("AS84k678DJRW84567465"), 4585); + final KademliaNode kad3 = new KademliaNode("Shameer", new NodeId("AS84k67894758456746A"), 8104); /* Connecting nodes */ System.out.println("Connecting Nodes"); diff --git a/src/kademlia/tests/ContentSendingTest.java b/src/kademlia/tests/ContentSendingTest.java index 901b22c..ba591d6 100644 --- a/src/kademlia/tests/ContentSendingTest.java +++ b/src/kademlia/tests/ContentSendingTest.java @@ -2,7 +2,7 @@ package kademlia.tests; import java.io.IOException; import kademlia.dht.GetParameter; -import kademlia.Kademlia; +import kademlia.KademliaNode; import kademlia.dht.StorageEntry; import kademlia.exceptions.ContentNotFoundException; import kademlia.node.NodeId; @@ -21,9 +21,9 @@ public class ContentSendingTest try { /* 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()); - 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()); kad2.bootstrap(kad1.getNode()); diff --git a/src/kademlia/tests/ContentUpdatingTest.java b/src/kademlia/tests/ContentUpdatingTest.java index 83b5834..03ae45d 100644 --- a/src/kademlia/tests/ContentUpdatingTest.java +++ b/src/kademlia/tests/ContentUpdatingTest.java @@ -2,7 +2,7 @@ package kademlia.tests; import java.io.IOException; import kademlia.dht.GetParameter; -import kademlia.Kademlia; +import kademlia.KademliaNode; import kademlia.dht.StorageEntry; import kademlia.exceptions.ContentNotFoundException; import kademlia.node.NodeId; @@ -21,9 +21,9 @@ public class ContentUpdatingTest try { /* 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()); - 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()); kad2.bootstrap(kad1.getNode()); diff --git a/src/kademlia/tests/NodeConnectionTest.java b/src/kademlia/tests/NodeConnectionTest.java index ea6d3de..a946979 100644 --- a/src/kademlia/tests/NodeConnectionTest.java +++ b/src/kademlia/tests/NodeConnectionTest.java @@ -1,7 +1,7 @@ package kademlia.tests; import java.io.IOException; -import kademlia.Kademlia; +import kademlia.KademliaNode; import kademlia.node.NodeId; /** @@ -18,10 +18,10 @@ public class NodeConnectionTest try { /* 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()); - 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()); System.out.println("Created Node Kad 2: " + kad2.getNode().getNodeId()); // System.out.println(kad1.getNode().getNodeId() + " ^ " + kad2.getNode().getNodeId() + " = " + diff12); @@ -37,7 +37,7 @@ public class NodeConnectionTest // 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("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("Connecting Kad 3 and Kad 2"); @@ -47,20 +47,20 @@ public class NodeConnectionTest // 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); + 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("Connecting Kad 4 and Kad 2"); kad4.bootstrap(kad2.getNode()); 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(kad2.getNode().getRoutingTable()); + System.out.println(kad2.getRoutingTable()); 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(kad4.getNode().getRoutingTable()); + System.out.println(kad4.getRoutingTable()); } catch (IOException e) { diff --git a/src/kademlia/tests/RefreshOperationTest.java b/src/kademlia/tests/RefreshOperationTest.java index 8a48f8c..44ac406 100644 --- a/src/kademlia/tests/RefreshOperationTest.java +++ b/src/kademlia/tests/RefreshOperationTest.java @@ -2,7 +2,7 @@ package kademlia.tests; import java.io.IOException; import kademlia.dht.GetParameter; -import kademlia.Kademlia; +import kademlia.KademliaNode; import kademlia.dht.StorageEntry; import kademlia.exceptions.ContentNotFoundException; import kademlia.node.NodeId; @@ -21,8 +21,8 @@ public class RefreshOperationTest try { /* Setting up 2 Kad networks */ - Kademlia kad1 = new Kademlia("JoshuaK", new NodeId("ASF45678947584567467"), 7574); - Kademlia kad2 = new Kademlia("Crystal", new NodeId("ASERTKJDHGVHERJHGFLK"), 7572); + KademliaNode kad1 = new KademliaNode("JoshuaK", new NodeId("ASF45678947584567467"), 7574); + KademliaNode kad2 = new KademliaNode("Crystal", new NodeId("ASERTKJDHGVHERJHGFLK"), 7572); kad2.bootstrap(kad1.getNode()); /* Lets create the content and share it */ diff --git a/src/kademlia/tests/RoutingTableSimulation.java b/src/kademlia/tests/RoutingTableSimulation.java index 04bec6e..63b0cf6 100644 --- a/src/kademlia/tests/RoutingTableSimulation.java +++ b/src/kademlia/tests/RoutingTableSimulation.java @@ -1,6 +1,6 @@ package kademlia.tests; -import kademlia.Kademlia; +import kademlia.KademliaNode; import kademlia.node.NodeId; import kademlia.routing.RoutingTable; @@ -18,13 +18,13 @@ public class RoutingTableSimulation try { /* Setting up 2 Kad networks */ - Kademlia kad1 = new Kademlia("JoshuaK", new NodeId("ASF45678947584567463"), 12049); - Kademlia kad2 = new Kademlia("Crystal", new NodeId("ASF45678947584567464"), 4585); - Kademlia kad3 = new Kademlia("Shameer", new NodeId("ASF45678947584567465"), 8104); - Kademlia kad4 = new Kademlia("Lokesh", new NodeId("ASF45678947584567466"), 8335); - Kademlia kad5 = new Kademlia("Chandu", new NodeId("ASF45678947584567467"), 13345); + KademliaNode kad1 = new KademliaNode("JoshuaK", new NodeId("ASF45678947584567463"), 12049); + KademliaNode kad2 = new KademliaNode("Crystal", new NodeId("ASF45678947584567464"), 4585); + KademliaNode kad3 = new KademliaNode("Shameer", new NodeId("ASF45678947584567465"), 8104); + KademliaNode kad4 = new KademliaNode("Lokesh", new NodeId("ASF45678947584567466"), 8335); + KademliaNode kad5 = new KademliaNode("Chandu", new NodeId("ASF45678947584567467"), 13345); - RoutingTable rt = kad1.getNode().getRoutingTable(); + RoutingTable rt = kad1.getRoutingTable(); rt.insert(kad2.getNode()); rt.insert(kad3.getNode()); @@ -36,6 +36,9 @@ public class RoutingTableSimulation rt.insert(kad3.getNode()); 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) { diff --git a/src/kademlia/tests/RoutingTableStateTesting.java b/src/kademlia/tests/RoutingTableStateTesting.java new file mode 100644 index 0000000..06e62c7 --- /dev/null +++ b/src/kademlia/tests/RoutingTableStateTesting.java @@ -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(); + } +} diff --git a/src/kademlia/tests/SaveStateTest.java b/src/kademlia/tests/SaveStateTest.java index 521b7fc..7fb9bd0 100644 --- a/src/kademlia/tests/SaveStateTest.java +++ b/src/kademlia/tests/SaveStateTest.java @@ -1,6 +1,6 @@ package kademlia.tests; -import kademlia.Kademlia; +import kademlia.KademliaNode; import kademlia.node.NodeId; /** @@ -17,11 +17,11 @@ public class SaveStateTest try { /* Setting up 2 Kad networks */ - Kademlia kad1 = new Kademlia("JoshuaK", new NodeId("ASF45678947584567463"), 12049); - Kademlia kad2 = new Kademlia("Crystal", new NodeId("ASF45678947584567464"), 4585); - Kademlia kad3 = new Kademlia("Shameer", new NodeId("ASF45678947584567465"), 8104); - Kademlia kad4 = new Kademlia("Lokesh", new NodeId("ASF45678947584567466"), 8335); - Kademlia kad5 = new Kademlia("Chandu", new NodeId("ASF45678947584567467"), 13345); + KademliaNode kad1 = new KademliaNode("JoshuaK", new NodeId("ASF45678947584567463"), 12049); + KademliaNode kad2 = new KademliaNode("Crystal", new NodeId("ASF45678947584567464"), 4585); + KademliaNode kad3 = new KademliaNode("Shameer", new NodeId("ASF45678947584567465"), 8104); + KademliaNode kad4 = new KademliaNode("Lokesh", new NodeId("ASF45678947584567466"), 8335); + KademliaNode kad5 = new KademliaNode("Chandu", new NodeId("ASF45678947584567467"), 13345); /* Connecting 2 to 1 */ System.out.println("Connecting Nodes 1 & 2"); @@ -76,7 +76,7 @@ public class SaveStateTest kad1.shutdown(true); System.out.println("\n\n\nReloading Kad instance from file"); - Kademlia kadR2 = Kademlia.loadFromFile("JoshuaK"); + KademliaNode kadR2 = KademliaNode.loadFromFile("JoshuaK"); System.out.println(kadR2); } catch (IllegalStateException e) diff --git a/src/kademlia/tests/SaveStateTest2.java b/src/kademlia/tests/SaveStateTest2.java index c6fdbd5..85f46fa 100644 --- a/src/kademlia/tests/SaveStateTest2.java +++ b/src/kademlia/tests/SaveStateTest2.java @@ -1,6 +1,6 @@ package kademlia.tests; -import kademlia.Kademlia; +import kademlia.KademliaNode; import kademlia.dht.GetParameter; import kademlia.dht.StorageEntry; import kademlia.node.NodeId; @@ -20,8 +20,8 @@ public class SaveStateTest2 try { /* Setting up 2 Kad networks */ - Kademlia kad1 = new Kademlia("JoshuaK", new NodeId("ASF45678947584567463"), 12049); - Kademlia kad2 = new Kademlia("Crystal", new NodeId("ASF45678947584567464"), 4585); + KademliaNode kad1 = new KademliaNode("JoshuaK", new NodeId("ASF45678947584567463"), 12049); + KademliaNode kad2 = new KademliaNode("Crystal", new NodeId("ASF45678947584567464"), 4585); /* Connecting 2 to 1 */ System.out.println("Connecting Nodes 1 & 2"); @@ -46,7 +46,7 @@ public class SaveStateTest2 kad1.shutdown(true); System.out.println("\n\n\nReloading Kad instance from file"); - kad1 = Kademlia.loadFromFile("JoshuaK"); + kad1 = KademliaNode.loadFromFile("JoshuaK"); kad1.bootstrap(kad2.getNode()); System.out.println(kad2); diff --git a/src/kademlia/tests/SimpleMessageTest.java b/src/kademlia/tests/SimpleMessageTest.java index d26783c..71f35ca 100644 --- a/src/kademlia/tests/SimpleMessageTest.java +++ b/src/kademlia/tests/SimpleMessageTest.java @@ -1,7 +1,7 @@ package kademlia.tests; import java.io.IOException; -import kademlia.Kademlia; +import kademlia.KademliaNode; import kademlia.message.SimpleMessage; import kademlia.node.NodeId; import kademlia.message.SimpleReceiver; @@ -19,8 +19,8 @@ public class SimpleMessageTest { try { - Kademlia kad1 = new Kademlia("Joshua", new NodeId("12345678901234567890"), 7574); - Kademlia kad2 = new Kademlia("Crystal", new NodeId("12345678901234567891"), 7572); + KademliaNode kad1 = new KademliaNode("Joshua", new NodeId("12345678901234567890"), 7574); + KademliaNode kad2 = new KademliaNode("Crystal", new NodeId("12345678901234567891"), 7572); kad1.getServer().sendMessage(kad2.getNode(), new SimpleMessage("Some Message"), new SimpleReceiver()); }