diff --git a/ws2012/P2P/uebungen/4/build.xml b/ws2012/P2P/uebungen/4/build.xml new file mode 100644 index 00000000..c3a28e56 --- /dev/null +++ b/ws2012/P2P/uebungen/4/build.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + Builds, tests, and runs the project p2p_u4. + + + diff --git a/ws2012/P2P/uebungen/4/manifest.mf b/ws2012/P2P/uebungen/4/manifest.mf new file mode 100644 index 00000000..328e8e5b --- /dev/null +++ b/ws2012/P2P/uebungen/4/manifest.mf @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +X-COMMENT: Main-Class will be added automatically by build + diff --git a/ws2012/P2P/uebungen/4/nbproject/build-impl.xml b/ws2012/P2P/uebungen/4/nbproject/build-impl.xml new file mode 100644 index 00000000..6e719ec6 --- /dev/null +++ b/ws2012/P2P/uebungen/4/nbproject/build-impl.xml @@ -0,0 +1,924 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set platform.home + Must set platform.bootcp + Must set platform.java + Must set platform.javac + + The J2SE Platform is not correctly set up. + Your active platform is: ${platform.active}, but the corresponding property "platforms.${platform.active}.home" is not found in the project's properties files. + Either open the project in the IDE and setup the Platform with the same name or add it manually. + For example like this: + ant -Duser.properties.file=<path_to_property_file> jar (where you put the property "platforms.${platform.active}.home" in a .properties file) + or ant -Dplatforms.${platform.active}.home=<path_to_JDK_home> jar (where no properties file is used) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set src.dir + Must set build.dir + Must set dist.dir + Must set build.classes.dir + Must set dist.javadoc.dir + Must set build.test.classes.dir + Must set build.test.results.dir + Must set build.classes.excludes + Must set dist.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + To run this application from the command line without Ant, try: + + + + + + + ${platform.java} -cp "${run.classpath.with.dist.jar}" ${main.class} + + + + + + + + + + + + To run this application from the command line without Ant, try: + + ${platform.java} -jar "${dist.jar.resolved}" + + + + + + + + To run this application from the command line without Ant, try: + + ${platform.java} -jar "${dist.jar.resolved}" + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + Must select one file in the IDE or set run.class + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set debug.class + + + + + Must select one file in the IDE or set debug.class + + + + + Must set fix.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + Some tests failed; see details above. + + + + + + + + + Must select some files in the IDE or set test.includes + + + + Some tests failed; see details above. + + + + + Must select one file in the IDE or set test.class + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ws2012/P2P/uebungen/4/nbproject/genfiles.properties b/ws2012/P2P/uebungen/4/nbproject/genfiles.properties new file mode 100644 index 00000000..463f74b7 --- /dev/null +++ b/ws2012/P2P/uebungen/4/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=ca3c66c2 +build.xml.script.CRC32=a34fe718 +build.xml.stylesheet.CRC32=28e38971@1.38.3.45 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=ca3c66c2 +nbproject/build-impl.xml.script.CRC32=b618a294 +nbproject/build-impl.xml.stylesheet.CRC32=229523de@1.38.3.45 diff --git a/ws2012/P2P/uebungen/4/nbproject/private/config.properties b/ws2012/P2P/uebungen/4/nbproject/private/config.properties new file mode 100644 index 00000000..e69de29b diff --git a/ws2012/P2P/uebungen/4/nbproject/private/private.properties b/ws2012/P2P/uebungen/4/nbproject/private/private.properties new file mode 100644 index 00000000..86cef05c --- /dev/null +++ b/ws2012/P2P/uebungen/4/nbproject/private/private.properties @@ -0,0 +1,6 @@ +compile.on.save=true +do.depend=false +do.jar=true +javac.debug=true +javadoc.preview=true +user.properties.file=C:\\Users\\rylon\\.netbeans\\6.9\\build.properties diff --git a/ws2012/P2P/uebungen/4/nbproject/project.properties b/ws2012/P2P/uebungen/4/nbproject/project.properties new file mode 100644 index 00000000..e791923d --- /dev/null +++ b/ws2012/P2P/uebungen/4/nbproject/project.properties @@ -0,0 +1,73 @@ +annotation.processing.enabled=true +annotation.processing.enabled.in.editor=false +annotation.processing.run.all.processors=true +annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output +application.title=p2p_u4 +application.vendor=rylon +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form +# This directory is removed when the project is cleaned: +build.dir=build +build.generated.dir=${build.dir}/generated +build.generated.sources.dir=${build.dir}/generated-sources +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +# Uncomment to specify the preferred debugger connection transport: +#debug.transport=dt_socket +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=${dist.dir}/p2p_u4.jar +dist.javadoc.dir=${dist.dir}/javadoc +endorsed.classpath= +excludes= +file.reference.4-src=src +includes=** +jar.compress=false +javac.classpath= +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.processorpath=\ + ${javac.classpath} +javac.source=1.7 +javac.target=1.7 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir}:\ + ${libs.junit.classpath}:\ + ${libs.junit_4.classpath} +javac.test.processorpath=\ + ${javac.test.classpath} +javadoc.additionalparam= +javadoc.author=false +javadoc.encoding=${source.encoding} +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +main.class= +manifest.file=manifest.mf +meta.inf.dir=${src.dir}/META-INF +platform.active=JDK_1.7 +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +# Space-separated list of JVM arguments used when running the project +# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value +# or test-sys-prop.name=value to set system properties for unit tests): +run.jvmargs= +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +source.encoding=UTF-8 +src.dir=${file.reference.4-src} diff --git a/ws2012/P2P/uebungen/4/nbproject/project.xml b/ws2012/P2P/uebungen/4/nbproject/project.xml new file mode 100644 index 00000000..f62bcc9d --- /dev/null +++ b/ws2012/P2P/uebungen/4/nbproject/project.xml @@ -0,0 +1,14 @@ + + + org.netbeans.modules.java.j2seproject + + + p2p_u4 + + + + + + + + diff --git a/ws2012/P2P/uebungen/4/src/Main.java b/ws2012/P2P/uebungen/4/src/Main.java index f863742e..b6806d5f 100644 --- a/ws2012/P2P/uebungen/4/src/Main.java +++ b/ws2012/P2P/uebungen/4/src/Main.java @@ -9,66 +9,59 @@ import node.Node; public class Main { - public static Map nodes = new HashMap(); + public static Map nodes = new HashMap<>(); - /** - * grow a network: Starting with one peer, repeatedly let peers spawn or - * leave at random - * - * @throws IOException - */ - public static void main(String[] args) throws IOException { + /** + * grow a network: Starting with one peer, repeatedly let peers spawn or + * leave at random + * + * @param args + * @throws IOException + */ + public static void main(String[] args) throws IOException { - System.setProperty("java.util.logging.config.file", - "logging.properties"); + System.setProperty( "java.util.logging.config.file", + "logging.properties"); - try { - LogManager.getLogManager().readConfiguration(); - } + try { + LogManager.getLogManager().readConfiguration(); + } catch (Exception e) { + e.printStackTrace();} - catch (Exception e) { - e.printStackTrace(); - } + nodes.put("a", new Node()); - nodes.put("a", new Node()); + BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); + String s; + while ((s = in.readLine()) != null && s.length() != 0) { + String[] splitted = s.split(" "); - BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); - String s; - while ((s = in.readLine()) != null && s.length() != 0) { - String[] splitted = s.split(" "); + String node = splitted[0]; + String cmd = splitted[1]; - String node = splitted[0]; - String cmd = splitted[1]; - - if (nodes.containsKey(node)) { - - switch (cmd) { - case "spawn": - if (splitted.length > 2) { - Node newNode = nodes.get(node).spawn(); - String newNodeName = splitted[2]; - nodes.put(newNodeName, newNode); - } else { - System.out - .println("Please enter a name for the new node."); - } - break; - case "leave": - Node theNode = nodes.get(node); - theNode.leave(); - nodes.remove(theNode); - break; - case "status": - System.out.println(nodes.get(node)); - break; - default: - System.out.println("Unknown command."); - break; - } - - } else { - System.out.println("No such node."); - } - } - } + if (nodes.containsKey(node)) { + switch (cmd) { + case "spawn": + if (splitted.length > 2) { + Node newNode = nodes.get(node).spawn(); + String newNodeName = splitted[2]; + nodes.put(newNodeName, newNode); + } else { + System.out.println("Please enter a name for the new node.");} + break; + case "leave": + Node theNode = nodes.get(node); + theNode.leave(); + nodes.remove(node); + break; + case "status": + System.out.println(nodes.get(node)); + break; + default: + System.out.println("Unknown command."); + break; + } + } else { + System.out.println("No such node.");} + } + } } \ No newline at end of file diff --git a/ws2012/P2P/uebungen/4/src/node/Node.java b/ws2012/P2P/uebungen/4/src/node/Node.java index fe72c9de..6a664bff 100644 --- a/ws2012/P2P/uebungen/4/src/node/Node.java +++ b/ws2012/P2P/uebungen/4/src/node/Node.java @@ -10,330 +10,326 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; +import java.util.logging.Level; import java.util.logging.Logger; public class Node { - private final static Logger LOGGER = Logger.getLogger(Node.class.getName()); + private final static Logger LOGGER = Logger.getLogger(Node.class.getName()); - private static final int BUF_SIZE = 512; + private static final int BUF_SIZE = 512; - private DatagramChannel channel; - private ByteBuffer buf; + private DatagramChannel channel; + private ByteBuffer buf; - private String name = "Not initialized"; + private String name = "Not initialized"; - private List neighbors = new ArrayList(); + private List neighbors = new ArrayList<>(); - private Map acks = new HashMap(); + private Map acks = new HashMap<>(); - private volatile Thread thread; - private UDPListen udpListen; + private volatile Thread thread; + private UDPListen udpListen; - private Random generator; + private Random generator; - public Node() { - System.setProperty("java.net.preferIPv4Stack", "true"); - generator = new Random(System.currentTimeMillis()); - try { - channel = DatagramChannel.open(); - channel.socket().bind(new InetSocketAddress("localhost", 0)); - channel.configureBlocking(false); + public Node() { + //debug + System.setProperty("java.net.preferIPv4Stack", "true"); + generator = new Random(System.currentTimeMillis()); + try { + channel = DatagramChannel.open(); + channel.socket().bind(new InetSocketAddress("localhost", 0)); + channel.configureBlocking(false); - buf = ByteBuffer.allocate(BUF_SIZE); + buf = ByteBuffer.allocate(BUF_SIZE); - this.name = channel.socket().getLocalSocketAddress().toString(); + this.name = channel.socket().getLocalSocketAddress().toString(); - udpListen = new UDPListen(); - thread = new Thread(udpListen); - thread.start(); + udpListen = new UDPListen(); + thread = new Thread(udpListen); - LOGGER.info("Initialized node " + name); - } catch (IOException e) { - e.printStackTrace(); - } - } + LOGGER.log(Level.INFO, "Initialized node {0}", name); + } catch (IOException e) { + e.printStackTrace(); + } + } - /** - * Create another peer, mutually link creator and spawn. - * - * @return the spawned Node - * @throws IOException - * if no connection could be established to the new node - */ - public Node spawn() throws IOException { - // LOGGER.info("Name: " + getName() + ", Spawning new node."); - Node newNode = new Node(); + /** + * Create another peer, mutually link creator and spawn. + * + * @return the spawned Node + * @throws IOException + * if no connection could be established to the new node + */ + public Node spawn() throws IOException { + // LOGGER.info("Name: " + getName() + ", Spawning new node."); + Node newNode = new Node(); + + Send_Invite(newNode); + neighbors.add(newNode.getAddress()); - int ack_id = generateAck(newNode.getAddress()); - buf.clear(); - buf.put(MessageType.INVITE); - buf.putInt(ack_id); - buf.flip(); + return newNode; + } - try { - channel.send(buf, newNode.getAddress()); - } catch (IOException e) { - e.printStackTrace(); - } + public boolean Send_Invite(Node newNode){ + ByteBuffer buffer = ByteBuffer.allocate(BUF_SIZE); + int ack_id = generateAck(newNode.getAddress()); + buffer.put(MessageType.INVITE); + buffer.putInt(ack_id); + buffer.flip(); - neighbors.add(newNode.getAddress()); + try { + channel.send(buffer, newNode.getAddress()); + } catch (IOException e) { + e.printStackTrace(); + return false; + } + return true; + } - return newNode; - } + /** + * Adds a new ack, which this node is expecting to receive. + * + * @param addr + * the SocketAddress the ack should be received from + * @return the identifier for this ack + */ + private int generateAck(SocketAddress addr) { + int ack_id = generator.nextInt(); + acks.put(ack_id, new Ack(addr)); + return ack_id; + } - /** - * Adds a new ack, which this node is expecting to receive. - * - * @param addr - * the SocketAddress the ack should be received from - * @return the identifier for this ack - */ - public int generateAck(SocketAddress addr) { - int ack_id = generator.nextInt(); - acks.put(ack_id, new Ack(addr)); - return ack_id; - } + public SocketAddress getAddress() { + return channel.socket().getLocalSocketAddress();} - public SocketAddress getAddress() { - return channel.socket().getLocalSocketAddress(); - } + public boolean Send_NewNeighbor(SocketAddress receiver, SocketAddress neighbor){ + ByteBuffer buffer = ByteBuffer.allocate(BUF_SIZE); + int ack_id = generateAck(neighbor); + buffer.put(MessageType.NEW_NEIGHBOR); + buffer.putInt(ack_id); + InetSocketAddress a = (InetSocketAddress) neighbor; + for (String part : a.getHostString().split("\\.")) { + buffer.put(Byte.valueOf(part));} + buffer.putInt(a.getPort()); + buffer.flip(); - private void sendAddrTo(SocketAddress receiver, SocketAddress addr) { - InetSocketAddress a = (InetSocketAddress) addr; - int ack_id = generateAck(addr); + try { + channel.send(buffer, receiver); + } catch (IOException e) { + e.printStackTrace(); + return false; + } + return true; + } - buf.clear(); - buf.put(MessageType.NEW_NEIGHBOR); - buf.putInt(ack_id); + /** + * Sends an acknowledgment message to receiver (who hopefully is expecting + * it) + * + * @param receiver + * the node expecting an ack + * @param ack_id + * the id to identify the ack + */ + private boolean Send_Ack(SocketAddress receiver, int ack_id) { + ByteBuffer buffer = ByteBuffer.allocate(BUF_SIZE); + buffer.put(MessageType.ACK); + buffer.putInt(ack_id); + buffer.flip(); + try { + channel.send(buffer, receiver); + } catch (IOException e) { + e.printStackTrace(); + return false; + } + return true; + } - for (String part : a.getHostString().split("\\.")) { - buf.put(Byte.valueOf(part)); - } - buf.putInt(a.getPort()); + private boolean Send_Leave(SocketAddress neighbor){ + ByteBuffer buffer = ByteBuffer.allocate(BUF_SIZE); + int ack_id = generateAck(neighbor); + buffer.put(MessageType.LEAVE); + buffer.putInt(ack_id); + buffer.flip(); - // acks.get(ack_id).setBuf(BufferUtil.clone(buf)); + try { + channel.send(buffer, neighbor); + } catch (IOException e) { + e.printStackTrace(); + return false; + } + return true; + } + /** + * This node circularly links all neighbors (no mesh!) and removes itself + * from the network. + */ + public void leave() { + LOGGER.log(Level.INFO, "Name: {0}, Leaving...", getName()); - buf.flip(); - try { - channel.send(buf, receiver); - } catch (IOException e) { - // TODO - } - } + for (int i = 0; i < neighbors.size(); i++) { + if (neighbors.size() > 2) { + int pred = ((i - 1) + neighbors.size()) % neighbors.size(); + int succ = (i + 1) % neighbors.size(); + Send_NewNeighbor(neighbors.get(i), neighbors.get(succ)); + Send_NewNeighbor(neighbors.get(i), neighbors.get(pred)); + } else if (neighbors.size() == 2) { + Send_NewNeighbor(neighbors.get(i), neighbors.get(Math.abs(i - 1))); + } - /** - * Sends an acknowledgment message to receiver (who hopefully is expecting - * it) - * - * @param receiver - * the node expecting an ack - * @param ack_id - * the id to identify the ack - */ - private void sendAckTo(SocketAddress receiver, int ack_id) { - buf.clear(); - buf.put(MessageType.ACK); - buf.putInt(ack_id); - buf.flip(); - try { - channel.send(buf, receiver); - } catch (IOException e) { - // TODO - } - } + Send_Leave(neighbors.get(i)); + } - /** - * This node circularly links all neighbors (no mesh!) and removes itself - * from the network. - */ - public void leave() { - LOGGER.info("Name: " + getName() + ", Leaving..."); + try { + if (thread != null) { + udpListen.terminate(); + thread.join();} + } catch (InterruptedException e) { + e.printStackTrace();} + } - for (int i = 0; i < neighbors.size(); i++) { + public boolean hasNeighbor(SocketAddress addr) { + for (SocketAddress n : neighbors) { + if (n.toString().equals(addr.toString())) { + return true; + } + } + return false; + } - if (neighbors.size() > 2) { - int pred = ((i - 1) + neighbors.size()) % neighbors.size(); - int succ = (i + 1) % neighbors.size(); - sendAddrTo(neighbors.get(i), neighbors.get(succ)); - sendAddrTo(neighbors.get(i), neighbors.get(pred)); - } else if (neighbors.size() == 2) { - sendAddrTo(neighbors.get(i), neighbors.get(Math.abs(i - 1))); - } + public int getNeighborId(SocketAddress addr) { + for (int i = 0; i < neighbors.size(); i++) { + if (neighbors.get(i).toString().equals(addr.toString())) { + return i; + } + } + return -1; + } - buf.clear(); - int ack_id = generateAck(neighbors.get(i)); - buf.put(MessageType.LEAVE); - buf.putInt(ack_id); - buf.flip(); + public String getName() { + return this.name;} - try { - channel.send(buf, neighbors.get(i)); - } catch (IOException e) { - e.printStackTrace(); - } - } - try { - if (thread != null) { - udpListen.terminate(); - thread.join(); - } - } catch (InterruptedException e) { - e.printStackTrace(); - } - } + public String toString() { + StringBuilder result = new StringBuilder(256); + result.append("Node "); + result.append(getName()).append(", Neighbors: "); + result.append(neighbors); + return result.toString(); + } - public boolean hasNeighbor(SocketAddress addr) { - for (SocketAddress n : neighbors) { - if (n.toString().equals(addr.toString())) { - return true; - } - } - return false; - } + private class UDPListen implements Runnable { + private volatile boolean running = true; - public int getNeighborId(SocketAddress addr) { - for (int i = 0; i < neighbors.size(); i++) { - if (neighbors.get(i).toString().equals(addr.toString())) { - return i; - } - } - return -1; - } + private void Receive_Invite(SocketAddress from){ + LOGGER.log(Level.INFO, "{0} received invite from {1}", new Object[]{name, from.toString()}); + int ack_id = buf.getInt(); + Send_Ack(from, ack_id); + neighbors.add(from); + } - public String getName() { - return this.name; - } + private void Receive_Ack(SocketAddress from){ + LOGGER.log(Level.INFO, "{0} received ack from {1}", new Object[]{name, from.toString()}); + int ack_id = buf.getInt(); + if (!checkAck(from, ack_id)) { + LOGGER.log(Level.WARNING, "Received unexpected ack from: {0}", from.toString());} + } - public String toString() { - StringBuilder result = new StringBuilder(256); - result.append("Node "); - result.append(getName()).append(", Neighbors: "); - result.append(neighbors); - return result.toString(); - } + private void Receive_Leave(SocketAddress from){ + LOGGER.log(Level.INFO, "{0}: {1} is leaving. Deleting...", new Object[]{name, from.toString()}); - public class UDPListen implements Runnable { - private volatile boolean running = true; + int idToRemove = getNeighborId(from); + if (idToRemove != -1) { + neighbors.remove(idToRemove); + int ack_id = buf.getInt(); + Send_Ack(from, ack_id); + } + // If we don't know that neighbor, we don't have to + // ack + } - public void run() { - SocketAddress receivedFrom = null; - int ack_id; + private void Receive_NewNeighbor(SocketAddress from){ + int ack_id = buf.getInt(); + StringBuilder theAddr = new StringBuilder(); - while (running) { - try { - receivedFrom = channel.receive(buf); + // Read 4 Bytes and 1 Integer = 1 IP address + for (int i = 0; i < 4; i++) { + theAddr.append(buf.get()); + if (i < 3){ + theAddr.append(".");} + } + int port = buf.getInt(); - // channel.receive() is non blocking. So we need to check if - // something actually has been written to the buffer - if (buf.remaining() != BUF_SIZE) { - buf.flip(); + InetSocketAddress new_neighbor = new InetSocketAddress(theAddr.toString(), port); - byte messageType = buf.get(); + if (!hasNeighbor(new_neighbor)) { + // Add this neighbor to my neighbor list if it + // was not present before + neighbors.add(new_neighbor); - switch (messageType) { - case MessageType.INVITE: - LOGGER.info(name + " received invite from " - + receivedFrom.toString()); + LOGGER.log(Level.INFO, "{0} from {1} received new neighbor:{2}", new Object[]{name, from.toString(), new_neighbor.toString()}); + } - ack_id = buf.getInt(); + Send_Ack(from, ack_id); + } - sendAckTo(receivedFrom, ack_id); + public void run() { + SocketAddress receivedFrom = null; - neighbors.add(receivedFrom); - break; + while (running) { + try { + receivedFrom = channel.receive(buf); - case MessageType.ACK: - ack_id = buf.getInt(); + // channel.receive() is non blocking. So we need to check if + // something actually has been written to the buffer + if (buf.remaining() != BUF_SIZE) { + buf.flip(); - LOGGER.info(name + " received ack from " - + receivedFrom.toString()); + byte messageType = buf.get(); - if (!checkAck(receivedFrom, ack_id)) { - LOGGER.warning("Received unexpected ack from: " - + receivedFrom.toString()); - } + switch (messageType) { + case MessageType.INVITE: + Receive_Invite(receivedFrom); + break; + case MessageType.ACK: + Receive_Ack(receivedFrom); + break; + case MessageType.LEAVE: + Receive_Leave(receivedFrom); + break; + case MessageType.NEW_NEIGHBOR: + Receive_NewNeighbor(receivedFrom); + break; + default: + LOGGER.log(Level.INFO, "{0} received unknown command from {1}: [{2}]{3}", new Object[]{name, receivedFrom.toString(), messageType, new String(buf.array())}); + } + } else { + try { + Thread.sleep(10); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + buf.clear(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } - break; + private boolean checkAck(SocketAddress receivedFrom, int ack_id) { + if (acks.containsKey(ack_id)) { + Ack theAck = acks.get(ack_id); + if (theAck.check(receivedFrom)) { + acks.remove(ack_id); + return true; + } + } + return false; + } - case MessageType.LEAVE: - LOGGER.info(name + ": " + receivedFrom.toString() - + " is leaving. Deleting..."); - - int idToRemove = getNeighborId(receivedFrom); - if (idToRemove != -1) { - neighbors.remove(idToRemove); - ack_id = buf.getInt(); - sendAckTo(receivedFrom, ack_id); - } - // If we don't know that neighbor, we don't have to - // ack - break; - - case MessageType.NEW_NEIGHBOR: - ack_id = buf.getInt(); - StringBuilder theAddr = new StringBuilder(); - - // Read 4 Bytes and 1 Integer = 1 IP address - for (int i = 0; i < 4; i++) { - theAddr.append(buf.get()); - if (i < 3) - theAddr.append("."); - } - int port = buf.getInt(); - - InetSocketAddress new_neighbor = new InetSocketAddress( - theAddr.toString(), port); - - if (!hasNeighbor(new_neighbor)) { - // Add this neighbor to my neighbor list if it - // was not present before - neighbors.add(new_neighbor); - - LOGGER.info(name + " from " - + receivedFrom.toString() - + " received new neighbor:" - + new_neighbor.toString()); - } - - sendAckTo(receivedFrom, ack_id); - - break; - - default: - LOGGER.info(name - + " received unknown command from " - + receivedFrom.toString() + ": [" - + messageType + "]" - + new String(buf.array())); - } - } else { - try { - Thread.sleep(10); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - buf.clear(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - - private boolean checkAck(SocketAddress receivedFrom, int ack_id) { - if (acks.containsKey(ack_id)) { - Ack theAck = acks.get(ack_id); - if (theAck.check(receivedFrom)) { - acks.remove(theAck); - return true; - } - } - return false; - } - - public void terminate() { - running = false; - } - } + public void terminate() { + running = false;} + } }