PageRenderTime 26ms CodeModel.GetById 13ms app.highlight 9ms RepoModel.GetById 2ms app.codeStats 0ms

/interpreter/tags/at2dist091109/src/edu/vub/at/actors/net/comm/MasterConnectionThread.java

http://ambienttalk.googlecode.com/
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}