KademliaDHT/src/kademlia/operation/ConnectOperation.java

123 lines
3.4 KiB
Java
Raw Normal View History

2014-02-18 20:37:07 +00:00
/**
* @author Joshua Kissoon
* @created 20140218
* @desc Operation that handles connecting to an existing Kademlia network using a bootstrap node
*/
package kademlia.operation;
import java.io.IOException;
import kademlia.core.Configuration;
import kademlia.core.KadServer;
import kademlia.exceptions.RoutingException;
import kademlia.message.AcknowledgeMessage;
import kademlia.message.ConnectMessage;
import kademlia.message.Message;
import kademlia.node.Node;
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 Node bootstrapNode;
private boolean error;
private int attempts;
/**
* @param server The message server used to send/receive messages
* @param local The local node
* @param bootstrap Node to use to bootstrap the local node onto the network
*/
public ConnectOperation(KadServer server, Node local, Node bootstrap)
{
this.server = server;
this.localNode = local;
this.bootstrapNode = bootstrap;
}
/**
* @return null
*/
@Override
public synchronized Object execute()
{
try
{
/* Contact the bootstrap node */
this.error = true;
this.attempts = 0;
Message m = new ConnectMessage(this.localNode);
/* Send a connect message to the bootstrap node */
server.sendMessage(this.bootstrapNode, m, this);
/* Wait for a while */
wait(Configuration.OPERATION_TIMEOUT);
if (error)
{
/* Means the contact failed */
throw new RoutingException("Bootstrap node did not respond: " + bootstrapNode);
}
/* @todo Perform lookup for our own ID to get nodes close to us */
/* @todo Refresh buckets to get a good routing table */
return null;
}
catch (IOException | InterruptedException e)
{
e.printStackTrace();
}
return null;
}
/**
* Receives an AcknowledgeMessage from the bootstrap node.
*
* @param comm
*/
@Override
public synchronized void receive(Message incoming, int comm)
{
/* The incoming message will be an acknowledgement message */
AcknowledgeMessage msg = (AcknowledgeMessage) incoming;
System.out.println("ConnectOperation now handling Acknowledgement Message: " + msg);
/* The bootstrap node has responded, insert it into our space */
this.localNode.getRoutingTable().insert(this.bootstrapNode);
/* We got a response, so the error is false */
error = false;
/* Wake up any waiting thread */
notify();
}
/**
* Resends a ConnectMessage to the boot strap node a maximum of MAX_ATTEMPTS
* times.
*
* @param comm
*
* @throws java.io.IOException
*/
@Override
public synchronized void timeout(int comm) throws IOException
{
if (++this.attempts < MAX_CONNECT_ATTEMPTS)
{
this.server.sendMessage(this.bootstrapNode, new ConnectMessage(this.localNode), this);
}
else
{
/* We just exit, so notify all other threads that are possibly waiting */
notify();
}
}
}