diff --git a/src/kademlia/core/DefaultConfiguration.java b/src/kademlia/core/DefaultConfiguration.java index a2bdf57..1cc6520 100644 --- a/src/kademlia/core/DefaultConfiguration.java +++ b/src/kademlia/core/DefaultConfiguration.java @@ -10,7 +10,7 @@ import java.io.File; public class DefaultConfiguration implements KadConfiguration { - private final static long RESTORE_INTERVAL = 60 * 1000; // Default at 1 hour + private final static long RESTORE_INTERVAL = 10 * 1000; // Default at 1 hour private final static long RESPONSE_TIMEOUT = 1500; private final static long OPERATION_TIMEOUT = 3000; private final static int CONCURRENCY = 10; diff --git a/src/kademlia/core/KadServer.java b/src/kademlia/core/KadServer.java index 6d3c9fc..036c794 100644 --- a/src/kademlia/core/KadServer.java +++ b/src/kademlia/core/KadServer.java @@ -36,7 +36,7 @@ public class KadServer /* Server Objects */ private final int udpPort; private final DatagramSocket socket; - private boolean isRunning; + private transient boolean isRunning; private final Map receivers; private final Timer timer; // Schedule future tasks private final Map tasks; // Keep track of scheduled tasks @@ -109,7 +109,7 @@ public class KadServer { if (!isRunning) { - throw new IllegalStateException("Kad Server is not running."); + throw new IllegalStateException("Kad Server is not running on node " + this.localNode); } /* Generate a random communication ID */ diff --git a/src/kademlia/routing/Bucket.java b/src/kademlia/routing/Bucket.java index 537a90b..e98bbd2 100644 --- a/src/kademlia/routing/Bucket.java +++ b/src/kademlia/routing/Bucket.java @@ -4,7 +4,7 @@ import java.util.List; import kademlia.node.Node; /** - * A bucket used to store Nodes in the routing table. + * A bucket used to store Contacts in the routing table. * * @author Joshua Kissoon * @created 20140215 @@ -13,12 +13,28 @@ public interface Bucket { /** - * Adds a new node to the bucket + * Adds a contact to the bucket * - * @param n the new node + * @param c the new contact + */ + public void insert(Contact c); + + /** + * Create a new contact and insert it into the bucket. + * + * @param n The node to create the contact from */ public void insert(Node n); + /** + * Checks if this bucket contain a contact + * + * @param c The contact to check for + * + * @return boolean + */ + public boolean containsContact(Contact c); + /** * Checks if this bucket contain a node * @@ -26,21 +42,28 @@ public interface Bucket * * @return boolean */ - public boolean containNode(Node n); + public boolean containsNode(Node n); /** - * Remove a node from this bucket + * Remove a contact from this bucket * - * @param n The node to remove + * @param c The contact to remove + */ + public void removeContact(Contact c); + + /** + * Remove the contact object related to a node from this bucket + * + * @param n The node of the contact to remove */ public void removeNode(Node n); /** - * Counts the number of nodes in this bucket. + * Counts the number of contacts in this bucket. * - * @return Integer The number of nodes in this bucket + * @return Integer The number of contacts in this bucket */ - public int numNodes(); + public int numContacts(); /** * @return Integer The depth of this bucket in the RoutingTable @@ -48,7 +71,7 @@ public interface Bucket public int getDepth(); /** - * @return An Iterable structure with all nodes in this bucket + * @return An Iterable structure with all contacts in this bucket */ - public List getNodes(); + public List getContacts(); } diff --git a/src/kademlia/routing/Contact.java b/src/kademlia/routing/Contact.java new file mode 100644 index 0000000..48d7630 --- /dev/null +++ b/src/kademlia/routing/Contact.java @@ -0,0 +1,29 @@ +package kademlia.routing; + +import kademlia.node.Node; + +/** + * Keeps information about contacts of the Node; Contacts are stored in the Buckets in the Routing Table. + * + * Contacts are used instead of nodes because more information is needed than just the node information. + * - Information such as + * -- Last alive time + * + * @author Joshua Kissoon + * @since 20140425 + */ +public class Contact +{ + + private final Node n; + + public Contact(Node n) + { + this.n = n; + } + + public Node getNode() + { + return this.n; + } +} diff --git a/src/kademlia/routing/KadBucket.java b/src/kademlia/routing/KadBucket.java index fd6612a..7f039f9 100644 --- a/src/kademlia/routing/KadBucket.java +++ b/src/kademlia/routing/KadBucket.java @@ -17,11 +17,11 @@ public class KadBucket implements Bucket { private final int depth; - private final Map nodes; + private final Map contacts; { - nodes = new HashMap<>(); + contacts = new HashMap<>(); } /** @@ -33,49 +33,55 @@ public class KadBucket implements Bucket } @Override - public void insert(Node n) + public void insert(Contact c) { /* @todo Check if the bucket is filled already and handle the situation */ /* Check if the contact is already in the bucket */ - if (this.nodes.containsKey(n.getNodeId())) + if (this.contacts.containsKey(c.getNode().getNodeId())) { /* @todo If it is, then move it to the front */ /* @todo Possibly use a doubly linked list instead of an ArrayList */ } else { - nodes.put(n.getNodeId(), n); + contacts.put(c.getNode().getNodeId(), c); } } - /** - * Checks if this bucket contain a node - * - * @param n The node to check for - * - * @return boolean - */ @Override - public boolean containNode(Node n) + public void insert(Node n) { - return this.nodes.containsKey(n.getNodeId()); + this.insert(new Contact(n)); + } + + @Override + public boolean containsContact(Contact c) + { + return this.contacts.containsKey(c.getNode().getNodeId()); + } + + @Override + public boolean containsNode(Node n) + { + return this.contacts.containsKey(n.getNodeId()); + } + + @Override + public void removeContact(Contact c) + { + this.contacts.remove(c.getNode().getNodeId()); } - /** - * Remove a node from this bucket - * - * @param n The node to remove - */ @Override public void removeNode(Node n) { - this.nodes.remove(n.getNodeId()); + this.contacts.remove(n.getNodeId()); } @Override - public int numNodes() + public int numContacts() { - return this.nodes.size(); + return this.contacts.size(); } @Override @@ -85,9 +91,9 @@ public class KadBucket implements Bucket } @Override - public List getNodes() + public List getContacts() { - return new ArrayList<>(this.nodes.values()); + return new ArrayList<>(this.contacts.values()); } @Override @@ -96,10 +102,10 @@ public class KadBucket implements Bucket StringBuilder sb = new StringBuilder("Bucket at depth: "); sb.append(this.depth); sb.append("\n Nodes: \n"); - for (Node n : this.nodes.values()) + for (Contact n : this.contacts.values()) { sb.append("Node: "); - sb.append(n.getNodeId().toString()); + sb.append(n.getNode().getNodeId().toString()); sb.append("\n"); } diff --git a/src/kademlia/routing/RoutingTable.java b/src/kademlia/routing/RoutingTable.java index 5fa9c6b..ac11dd6 100644 --- a/src/kademlia/routing/RoutingTable.java +++ b/src/kademlia/routing/RoutingTable.java @@ -41,9 +41,19 @@ public class RoutingTable } /** - * Adds a new node to the routing table based on how far it is from the LocalNode. + * Adds a contact to the routing table based on how far it is from the LocalNode. * - * @param n The contact to add + * @param c The contact to add + */ + public final void insert(Contact c) + { + this.buckets[this.getBucketId(c.getNode().getNodeId())].insert(c); + } + + /** + * Adds a node to the routing table based on how far it is from the LocalNode. + * + * @param n The node to add */ public final void insert(Node n) { @@ -60,7 +70,7 @@ public class RoutingTable int bucketId = this.getBucketId(n.getNodeId()); /* If the bucket has the contact, remove it */ - if (this.buckets[bucketId].containNode(n)) + if (this.buckets[bucketId].containsNode(n)) { this.buckets[bucketId].removeNode(n); } @@ -97,11 +107,11 @@ public class RoutingTable int bucketIndex = this.getBucketId(target); /* Add the contacts from this bucket to the return contacts */ - for (Node c : this.buckets[bucketIndex].getNodes()) + for (Contact c : this.buckets[bucketIndex].getContacts()) { if (closest.size() < numNodesRequired) { - closest.add(c); + closest.add(c.getNode()); } else { @@ -120,11 +130,11 @@ public class RoutingTable */ for (int i = 1; (bucketIndex - i) >= 0; i++) { - for (Node c : this.buckets[bucketIndex - i].getNodes()) + for (Contact c : this.buckets[bucketIndex - i].getContacts()) { if (closest.size() < numNodesRequired) { - closest.add(c); + closest.add(c.getNode()); } else { @@ -149,11 +159,11 @@ public class RoutingTable */ for (int i = 1; (bucketIndex + i) < NodeId.ID_LENGTH; i++) { - for (Node c : this.buckets[bucketIndex + i].getNodes()) + for (Contact c : this.buckets[bucketIndex + i].getContacts()) { if (closest.size() < numNodesRequired) { - closest.add(c); + closest.add(c.getNode()); } else { @@ -180,12 +190,30 @@ public class RoutingTable for (Bucket b : this.buckets) { - nodes.addAll(b.getNodes()); + for (Contact c : b.getContacts()) + { + nodes.add(c.getNode()); + } } return nodes; } + /** + * @return List A List of all Nodes in this RoutingTable + */ + public final List getAllContacts() + { + List contacts = new ArrayList<>(); + + for (Bucket b : this.buckets) + { + contacts.addAll(b.getContacts()); + } + + return contacts; + } + /** * @return Bucket[] The buckets in this Kad Instance */ @@ -210,12 +238,12 @@ public class RoutingTable StringBuilder sb = new StringBuilder("\nPrinting Routing Table Started ***************** \n"); for (Bucket b : this.buckets) { - if (b.numNodes() > 0) + if (b.numContacts() > 0) { sb.append("# nodes in Bucket with depth "); sb.append(b.getDepth()); sb.append(": "); - sb.append(b.numNodes()); + sb.append(b.numContacts()); sb.append("\n"); sb.append(b.toString()); sb.append("\n"); diff --git a/src/kademlia/tests/SaveStateTest.java b/src/kademlia/tests/SaveStateTest.java index 426f32c..521b7fc 100644 --- a/src/kademlia/tests/SaveStateTest.java +++ b/src/kademlia/tests/SaveStateTest.java @@ -79,7 +79,10 @@ public class SaveStateTest Kademlia kadR2 = Kademlia.loadFromFile("JoshuaK"); System.out.println(kadR2); } - + catch (IllegalStateException e) + { + + } catch (Exception e) { e.printStackTrace(); diff --git a/src/kademlia/util/serializer/JsonRoutingTableSerializer.java b/src/kademlia/util/serializer/JsonRoutingTableSerializer.java index 614883f..d55e3b9 100644 --- a/src/kademlia/util/serializer/JsonRoutingTableSerializer.java +++ b/src/kademlia/util/serializer/JsonRoutingTableSerializer.java @@ -13,6 +13,7 @@ import kademlia.routing.RoutingTable; import java.lang.reflect.Type; import java.util.List; import kademlia.node.Node; +import kademlia.routing.Contact; /** * A KadSerializer that serializes routing tables to JSON format @@ -43,6 +44,10 @@ public class JsonRoutingTableSerializer implements KadSerializer private final Gson gson; + Type contactCollectionType = new TypeToken>() + { + }.getType(); + { gson = new Gson(); @@ -58,15 +63,11 @@ public class JsonRoutingTableSerializer implements KadSerializer /* Write the basic RoutingTable */ gson.toJson(data, RoutingTable.class, writer); - /* Now Store the Nodes */ - Type collectionType = new TypeToken>() - { - }.getType(); - gson.toJson(data.getAllNodes(), collectionType, writer); + /* Now Store the Contacts */ + gson.toJson(data.getAllContacts(), contactCollectionType, writer); writer.endArray(); } - } @Override @@ -80,16 +81,13 @@ public class JsonRoutingTableSerializer implements KadSerializer /* Read the basic RoutingTable */ RoutingTable tbl = gson.fromJson(reader, RoutingTable.class); - /* Now get the nodes and add them back to the RoutingTable */ - Type collectionType = new TypeToken>() - { - }.getType(); - List nodes = gson.fromJson(reader, collectionType); + /* Now get the Contacts and add them back to the RoutingTable */ + List contacts = gson.fromJson(reader, contactCollectionType); tbl.initialize(); - for (Node n : nodes) + for (Contact c : contacts) { - tbl.insert(n); + tbl.insert(c); } reader.endArray();