/interpreter/tags/at2dist091109/src/edu/vub/at/actors/net/comm/MasterConnectionThread.java
Java | 162 lines | 84 code | 20 blank | 58 comment | 12 complexity | 0c9475db9e29d2658c56173ae23c3a0b MD5 | raw file
1/** 2 * AmbientTalk/2 Project 3 * (c) Programming Technology Lab, 2006 - 2007 4 * Authors: Tom Van Cutsem & Stijn Mostinckx 5 * 6 * Permission is hereby granted, free of charge, to any person 7 * obtaining a copy of this software and associated documentation 8 * files (the "Software"), to deal in the Software without 9 * restriction, including without limitation the rights to use, 10 * copy, modify, merge, publish, distribute, sublicense, and/or 11 * sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following 13 * conditions: 14 * 15 * The above copyright notice and this permission notice shall be 16 * included in all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 * OTHER DEALINGS IN THE SOFTWARE. 26 */ 27package edu.vub.at.actors.net.comm; 28 29import edu.vub.at.util.logging.Logging; 30 31import java.io.DataInputStream; 32import java.io.IOException; 33import java.net.InetAddress; 34import java.net.NetworkInterface; 35import java.net.ServerSocket; 36import java.net.Socket; 37import java.net.SocketException; 38import java.net.UnknownHostException; 39import java.util.Enumeration; 40 41/** 42 * This thread is responsible for opening up a {@link ServerSocket} connection that listens 43 * for incoming <i>slave</i> VMs. An incoming slave connection is registered with the 44 * communication bus such that a {@link CommandProcessor} can further handle communication with the slave. 45 * 46 * @author jededeck 47 * @author tvcutsem 48 */ 49public class MasterConnectionThread extends Thread { 50 51 private volatile ServerSocket listenSocket_; 52 53 private volatile boolean isActive_ = true; 54 55 private final CommunicationBus communicationBus_; 56 57 public MasterConnectionThread(CommunicationBus owner) { 58 super("MasterConnectionThread for " + owner); 59 communicationBus_ = owner; 60 } 61 62 /** 63 * Tries to create a local server socket connection to handle incoming 64 * slave connection requests. 65 * @param onNetwork needed for initializing the proper {@link Address} (tells me on which overlay network I should host) 66 * @return the {@link Address} encapsulating connection information to my socket 67 * @throws IOException if the local socket cannot be created. It is guaranteed that, if this 68 * exception is raised, this thread will <b>not</b> have started. 69 */ 70 public Address startServing(String onNetwork) throws IOException { 71 InetAddress myAddress = InetAddress.getByName(getCurrentEnvironmentNetworkIp()); 72 listenSocket_ = new ServerSocket(0, 50, myAddress); // create a socket that will listen on any free port 73 this.start(); 74 return new Address(myAddress, listenSocket_.getLocalPort(), onNetwork); 75 } 76 77 public void stopServing() { 78 isActive_ = false; 79 // we need to force the master to quit, it might be blocked on the server socket 80 try { 81 if (listenSocket_ != null) { 82 listenSocket_.close(); 83 } 84 } catch (IOException e) { } 85 } 86 87 /** 88 * Perpetually listen for incoming slave connections on my server socket. 89 * If a slave connects, read its address and register the incoming connection 90 * with the {@link CommunicationBus}. 91 */ 92 public void run() { 93 try { 94 Socket slave = null; 95 while (isActive_) { 96 97 try { 98 // accept an incoming slave connection 99 slave = listenSocket_.accept(); 100 101 // read the slave's Address 102 DataInputStream din = new DataInputStream(slave.getInputStream()); 103 int addressLength = din.readInt(); 104 byte[] address = new byte[addressLength]; 105 din.read(address); 106 107 Address slaveAddress = Address.fromBytes(address); 108 109 Logging.Network_LOG.debug("Detected incoming slave connection to " + slaveAddress); 110 111 // only signal the connection of a slave if everything went OK so far 112 communicationBus_.addConnection(slaveAddress, slave); 113 114 slave = null; 115 } catch(IOException e) { 116 Logging.Network_LOG.warn(toString() + ": error setting up connection with slave: " + e.getMessage()); 117 // explicitly close the connection with the slave if one was created 118 try { 119 if (slave != null) { slave.close(); } 120 } catch (IOException ioe) { } 121 } 122 } 123 } finally { 124 if (listenSocket_ != null) { 125 try { 126 listenSocket_.close(); 127 } catch (IOException e) { } 128 } 129 Logging.Network_LOG.debug(toString() + " shutting down."); 130 } 131 } 132 133 /** 134 * @return the current environment's IP address, taking into account the Internet connection to any of the available 135 * machine's Network interfaces. Examples of the outputs can be in octet or in IPV6 format. 136 * Based on source code by Marcello de Sales (marcello.sales@gmail.com) 137 * from <tt>http://www.jguru.com/faq/view.jsp?EID=15835</tt> (adapted from Java 1.5 to 1.4) 138 */ 139 private static String getCurrentEnvironmentNetworkIp() { 140 try { 141 Enumeration netInterfaces = NetworkInterface.getNetworkInterfaces(); 142 while (netInterfaces.hasMoreElements()) { 143 NetworkInterface ni = (NetworkInterface) netInterfaces.nextElement(); 144 Enumeration address = ni.getInetAddresses(); 145 while (address.hasMoreElements()) { 146 InetAddress addr = (InetAddress) address.nextElement(); 147 if (!addr.isLoopbackAddress() && addr.isSiteLocalAddress() 148 && !(addr.getHostAddress().indexOf(":") > -1)) { 149 return addr.getHostAddress(); 150 } 151 } 152 } 153 } catch (SocketException e) { } 154 155 return "127.0.0.1"; 156 } 157 158 159 public String toString() { 160 return super.getName(); 161 } 162}