mirror of
https://github.com/ChronosX88/KademliaDHT.git
synced 2024-11-22 10:12:19 +00:00
Started working on Node refreshing the K-Buckets and DHT content at every time interval t
Started working on PUT, GET, STORE operation and on DHT Storage
This commit is contained in:
parent
3344511603
commit
44077d344d
@ -26,7 +26,7 @@ public class Configuration
|
|||||||
/**
|
/**
|
||||||
* Maximum number of concurrent messages in transit.
|
* Maximum number of concurrent messages in transit.
|
||||||
* */
|
* */
|
||||||
public static int CONCURRENCY = 2;
|
public static int CONCURRENCY = 10;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Log base exponent.
|
* Log base exponent.
|
||||||
|
@ -1,26 +1,29 @@
|
|||||||
/**
|
|
||||||
* @author Joshua Kissoon
|
|
||||||
* @created 20140215
|
|
||||||
* @desc The main Kademlia network management class
|
|
||||||
*/
|
|
||||||
package kademlia.core;
|
package kademlia.core;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
|
import kademlia.dht.DHTContent;
|
||||||
import kademlia.exceptions.RoutingException;
|
import kademlia.exceptions.RoutingException;
|
||||||
import kademlia.message.MessageFactory;
|
import kademlia.message.MessageFactory;
|
||||||
import kademlia.node.Node;
|
import kademlia.node.Node;
|
||||||
import kademlia.node.NodeId;
|
import kademlia.node.NodeId;
|
||||||
import kademlia.operation.ConnectOperation;
|
import kademlia.operation.ConnectOperation;
|
||||||
import kademlia.operation.Operation;
|
import kademlia.operation.Operation;
|
||||||
|
import kademlia.operation.RefreshOperation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The main Kademlia network management class
|
||||||
|
*
|
||||||
|
* @author Joshua Kissoon
|
||||||
|
* @since 20140215
|
||||||
|
*/
|
||||||
public class Kademlia
|
public class Kademlia
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Kademlia Attributes */
|
/* Kademlia Attributes */
|
||||||
private final String name;
|
private final String ownerId;
|
||||||
|
|
||||||
/* Objects to be used */
|
/* Objects to be used */
|
||||||
private final Node localNode;
|
private final Node localNode;
|
||||||
@ -36,7 +39,7 @@ 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 name The Name of this node used for storage
|
* @param ownerId The Name of this node used for storage
|
||||||
* @param defaultId Default id for the node
|
* @param defaultId Default id for the node
|
||||||
* @param udpPort The UDP port to use for routing messages
|
* @param udpPort The UDP port to use for routing messages
|
||||||
*
|
*
|
||||||
@ -44,9 +47,9 @@ public class Kademlia
|
|||||||
* from disk <i>or</i> a network error occurred while
|
* from disk <i>or</i> a network error occurred while
|
||||||
* attempting to connect to the network
|
* attempting to connect to the network
|
||||||
* */
|
* */
|
||||||
public Kademlia(String name, NodeId defaultId, int udpPort) throws IOException
|
public Kademlia(String ownerId, NodeId defaultId, int udpPort) throws IOException
|
||||||
{
|
{
|
||||||
this.name = name;
|
this.ownerId = ownerId;
|
||||||
this.localNode = new Node(defaultId, InetAddress.getLocalHost(), udpPort);
|
this.localNode = new Node(defaultId, InetAddress.getLocalHost(), udpPort);
|
||||||
this.messageFactory = new MessageFactory(localNode);
|
this.messageFactory = new MessageFactory(localNode);
|
||||||
this.server = new KadServer(udpPort, this.messageFactory, this.localNode);
|
this.server = new KadServer(udpPort, this.messageFactory, this.localNode);
|
||||||
@ -59,12 +62,15 @@ public class Kademlia
|
|||||||
@Override
|
@Override
|
||||||
public void run()
|
public void run()
|
||||||
{
|
{
|
||||||
/**
|
try
|
||||||
* @todo Create Operation that
|
{
|
||||||
* Refreshes all buckets and sends HashMessages to all nodes that are
|
/* Runs a RefreshOperation to refresh K-Buckets and stored content */
|
||||||
* among the K closest to mappings stored at this node. Also deletes any
|
new RefreshOperation(server, localNode).execute();
|
||||||
* mappings that this node is no longer among the K closest to.
|
}
|
||||||
* */
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
System.err.println("Refresh Operation Failed; Message: " + e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Delay // Interval
|
// Delay // Interval
|
||||||
@ -102,4 +108,29 @@ public class Kademlia
|
|||||||
Operation op = new ConnectOperation(this.server, this.localNode, n);
|
Operation op = new ConnectOperation(this.server, this.localNode, n);
|
||||||
op.execute();
|
op.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the specified value under the given key
|
||||||
|
* This value is stored on K nodes on the network, or all nodes if there are > K total nodes in the network
|
||||||
|
*
|
||||||
|
* @param content The content to put onto the DHT
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public boolean put(DHTContent content)
|
||||||
|
{
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get some content stored on the DHT
|
||||||
|
*
|
||||||
|
* @param key The key of this content
|
||||||
|
*
|
||||||
|
* @return DHTContent The content
|
||||||
|
*/
|
||||||
|
public DHTContent get(NodeId key)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
35
src/kademlia/dht/DHTContent.java
Normal file
35
src/kademlia/dht/DHTContent.java
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package kademlia.dht;
|
||||||
|
|
||||||
|
import kademlia.node.NodeId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Any piece of content that needs to be stored on the DHT
|
||||||
|
*
|
||||||
|
* @author Joshua Kissoon
|
||||||
|
* @since 20140224
|
||||||
|
*/
|
||||||
|
public interface DHTContent
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return NodeId The DHT key for this content
|
||||||
|
*/
|
||||||
|
public NodeId getKey();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return String The type of content
|
||||||
|
*/
|
||||||
|
public String getType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Each content will have an expiry date for when a user should delete it form his/her machine
|
||||||
|
*
|
||||||
|
* @return long The expiry date of this content
|
||||||
|
*/
|
||||||
|
public long getExpiryDate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The ID of the owner of this content
|
||||||
|
*/
|
||||||
|
public String getOwnerId();
|
||||||
|
}
|
@ -1,8 +1,3 @@
|
|||||||
/**
|
|
||||||
* @author Joshua
|
|
||||||
* @created
|
|
||||||
* @desc
|
|
||||||
*/
|
|
||||||
package kademlia.node;
|
package kademlia.node;
|
||||||
|
|
||||||
import java.io.DataInput;
|
import java.io.DataInput;
|
||||||
@ -15,6 +10,13 @@ import java.util.Comparator;
|
|||||||
import kademlia.message.Streamable;
|
import kademlia.message.Streamable;
|
||||||
import kademlia.routing.RoutingTable;
|
import kademlia.routing.RoutingTable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Node in the Kademlia network
|
||||||
|
*
|
||||||
|
* @author Joshua Kissoon
|
||||||
|
* @since 20140202
|
||||||
|
* @version 0.1
|
||||||
|
*/
|
||||||
public class Node implements Streamable
|
public class Node implements Streamable
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -167,6 +169,8 @@ public class Node implements Streamable
|
|||||||
{
|
{
|
||||||
Node n1 = (Node) o1;
|
Node n1 = (Node) o1;
|
||||||
Node n2 = (Node) o2;
|
Node n2 = (Node) o2;
|
||||||
|
|
||||||
|
/* Check if they are equal and return 0 */
|
||||||
if (n1.getNodeId().equals(n2.getNodeId()))
|
if (n1.getNodeId().equals(n2.getNodeId()))
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@ -179,18 +183,20 @@ public class Node implements Streamable
|
|||||||
int index2 = nodeId.xor(n2.getNodeId()).getFirstSetBitIndex();
|
int index2 = nodeId.xor(n2.getNodeId()).getFirstSetBitIndex();
|
||||||
//System.out.println("Node " + n2.getNodeId() + " distance: " + index2);
|
//System.out.println("Node " + n2.getNodeId() + " distance: " + index2);
|
||||||
|
|
||||||
/* If the first node is closer to the given node, return 1 */
|
|
||||||
int retval;
|
int retval;
|
||||||
if (index1 < index2)
|
if (index1 < index2)
|
||||||
{
|
{
|
||||||
|
/* If the first node is closer to the given node, return 1 */
|
||||||
retval = 1;
|
retval = 1;
|
||||||
}
|
}
|
||||||
else if (index1 > index2)
|
|
||||||
{
|
|
||||||
retval = -1;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* If the first node is farther to the given node, return 1
|
||||||
|
*
|
||||||
|
* @note -1 will also be returned if both nodes are the same distance away
|
||||||
|
* This really don't make a difference though, since they need to be sorted.
|
||||||
|
*/
|
||||||
retval = -1;
|
retval = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +68,11 @@ public class ConnectOperation implements Operation, Receiver
|
|||||||
Operation lookup = new NodeLookupOperation(this.server, this.localNode, this.localNode.getNodeId());
|
Operation lookup = new NodeLookupOperation(this.server, this.localNode, this.localNode.getNodeId());
|
||||||
lookup.execute();
|
lookup.execute();
|
||||||
|
|
||||||
/* @todo Refresh buckets to get a good routing table */
|
/**
|
||||||
|
* @todo Refresh buckets to get a good routing table
|
||||||
|
* I think after the above lookup operation, K buckets will be filled
|
||||||
|
* Not sure if this operation is needed here
|
||||||
|
*/
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,8 @@ public interface Operation
|
|||||||
* @return The return value can differ per operation
|
* @return The return value can differ per operation
|
||||||
*
|
*
|
||||||
* @throws kademlia.exceptions.RoutingException
|
* @throws kademlia.exceptions.RoutingException
|
||||||
|
*
|
||||||
|
* @todo Remove the Object return type, those operations that return things should have a method to return the data
|
||||||
*/
|
*/
|
||||||
public Object execute() throws IOException, RoutingException;
|
public Object execute() throws IOException, RoutingException;
|
||||||
}
|
}
|
||||||
|
43
src/kademlia/operation/RefreshOperation.java
Normal file
43
src/kademlia/operation/RefreshOperation.java
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package kademlia.operation;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import kademlia.core.KadServer;
|
||||||
|
import kademlia.node.Node;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* At each time interval t, nodes need to refresh their K-Buckets and their Data Storage
|
||||||
|
* This Operation will manage refreshing the K-Buckets and data storage
|
||||||
|
*
|
||||||
|
* @author Joshua Kissoon
|
||||||
|
* @created 20140224
|
||||||
|
*/
|
||||||
|
public class RefreshOperation implements Operation
|
||||||
|
{
|
||||||
|
|
||||||
|
private final KadServer server;
|
||||||
|
private final Node localNode;
|
||||||
|
|
||||||
|
public RefreshOperation(KadServer server, Node localNode)
|
||||||
|
{
|
||||||
|
this.server = server;
|
||||||
|
this.localNode = localNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized Object execute() throws IOException
|
||||||
|
{
|
||||||
|
/* @todo Do a Node Lookup operation to refresh K-Buckets */
|
||||||
|
new NodeLookupOperation(this.server, this.localNode, this.localNode.getNodeId()).execute();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @todo Send data in DHT to closest Nodes if they don't have it
|
||||||
|
* This is better than asking closest nodes for data,
|
||||||
|
* since the data may not always come from the closest nodes
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @todo Delete any content on this node that this node is not one of the K-Closest nodes to
|
||||||
|
* @todo Delete any expired content
|
||||||
|
*/
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
41
src/kademlia/operation/StoreOperation.java
Normal file
41
src/kademlia/operation/StoreOperation.java
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package kademlia.operation;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import kademlia.core.KadServer;
|
||||||
|
import kademlia.dht.DHTContent;
|
||||||
|
import kademlia.node.Node;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Operation that stores a DHT Content onto the K closest nodes to the content Key
|
||||||
|
*
|
||||||
|
* @author Joshua Kissoon
|
||||||
|
* @since 20140224
|
||||||
|
*/
|
||||||
|
public class StoreOperation implements Operation
|
||||||
|
{
|
||||||
|
|
||||||
|
private final KadServer server;
|
||||||
|
private final Node localNode;
|
||||||
|
private final DHTContent content;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param server
|
||||||
|
* @param localNode
|
||||||
|
* @param content The content to be stored on the DHT
|
||||||
|
*/
|
||||||
|
public StoreOperation(KadServer server, Node localNode, DHTContent content)
|
||||||
|
{
|
||||||
|
this.server = server;
|
||||||
|
this.localNode = localNode;
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized Object execute() throws IOException
|
||||||
|
{
|
||||||
|
/* Get the nodes on which we need to store the content */
|
||||||
|
ArrayList<Node> nodes = new NodeLookupOperation(this.server, this.localNode, this.content.getKey()).execute();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
12
src/kademlia/tests/DHTContentImpl.java
Normal file
12
src/kademlia/tests/DHTContentImpl.java
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package kademlia.tests;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple DHT Content object to test DHT storage
|
||||||
|
*
|
||||||
|
* @author Joshua Kissoon
|
||||||
|
* @since 20140224
|
||||||
|
*/
|
||||||
|
public class DHTContentImpl
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user