PageRenderTime 34ms CodeModel.GetById 21ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

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

http://ambienttalk.googlecode.com/
Java | 181 lines | 93 code | 20 blank | 68 comment | 12 complexity | 3d2362d4bba8cd15dc7549250d1def88 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.actors.natives.ELVirtualMachine;
 30import edu.vub.at.util.logging.Logging;
 31
 32import java.io.DataInputStream;
 33import java.io.IOException;
 34import java.net.InetAddress;
 35import java.net.NetworkInterface;
 36import java.net.ServerSocket;
 37import java.net.Socket;
 38import java.net.SocketException;
 39import java.net.UnknownHostException;
 40import java.util.Enumeration;
 41
 42/**
 43 * This thread is responsible for opening up a {@link ServerSocket} connection that listens
 44 * for incoming <i>slave</i> VMs. An incoming slave connection is registered with the
 45 * communication bus such that a {@link CommandProcessor} can further handle communication with the slave.
 46 * 
 47 * @author jededeck
 48 * @author tvcutsem
 49 */
 50public class MasterConnectionThread extends Thread {
 51	
 52	private volatile ServerSocket listenSocket_;
 53	
 54	private volatile boolean isActive_ = true;
 55	
 56	private CommunicationBus communicationBus_;
 57	
 58	public MasterConnectionThread(CommunicationBus owner) {
 59		super("MasterConnectionThread for " + owner);
 60		communicationBus_ = owner;
 61	}
 62	
 63	/**
 64	 * Tries to create a local server socket connection to handle incoming
 65	 * slave connection requests.
 66	 * @param onNetwork needed for initializing the proper {@link Address} (tells me on which overlay network I should host)
 67	 * @return the {@link Address} encapsulating connection information to my socket
 68	 * @throws IOException if the local socket cannot be created. It is guaranteed that, if this
 69	 * exception is raised, this thread will <b>not</b> have started.
 70	 */
 71	public Address startServing() throws IOException { 
 72		InetAddress myAddress = InetAddress.getByName(getCurrentEnvironmentNetworkIp(communicationBus_.getIpAddress()));
 73		listenSocket_ = new ServerSocket(0, 50, myAddress); // create a socket that will listen on any free port
 74		this.start();
 75		return new Address(myAddress, listenSocket_.getLocalPort(), communicationBus_.getGroupName());
 76	}
 77
 78	public void stopServing() {
 79		isActive_ = false;
 80		// we need to force the master to quit, it might be blocked on the server socket
 81		try {
 82			if (listenSocket_ != null) {
 83				listenSocket_.close();
 84			}
 85		} catch (IOException e) { }
 86	}
 87
 88	/**
 89	 * Perpetually listen for incoming slave connections on my server socket.
 90	 * If a slave connects, read its address and register the incoming connection
 91	 * with the {@link CommunicationBus}.
 92	 */
 93	public void run() {
 94		try {
 95			Socket slave = null;
 96			while (isActive_) {
 97				
 98				try {
 99                    // accept an incoming slave connection
100					slave = listenSocket_.accept();
101					
102					// read the slave's Address
103					DataInputStream din = new DataInputStream(slave.getInputStream());
104					int addressLength = din.readInt();
105					byte[] address = new byte[addressLength];
106					din.read(address);
107					
108					Address slaveAddress = Address.fromBytes(address);
109					
110					Logging.Network_LOG.debug("Detected incoming slave connection to " + slaveAddress);
111					
112					// only signal the connection of a slave if everything went OK so far
113					communicationBus_.addConnection(slaveAddress, slave);
114					
115					slave = null;
116				} catch(IOException e) {
117					Logging.Network_LOG.warn(toString() + ": error setting up connection with slave: " + e.getMessage());
118					// explicitly close the connection with the slave if one was created
119					try {
120						if (slave != null) { slave.close(); }
121					} catch (IOException ioe) { }
122				}
123			}
124		} finally {
125			if (listenSocket_ != null) {
126				try {
127					listenSocket_.close();
128				} catch (IOException e) { }
129			}
130			Logging.Network_LOG.debug(toString() + " shutting down.");
131		}
132	}
133	
134    /**
135     * @param ipAddress is the ip address to which connect or ELVirtualMachine._DEFAULT_IP_ADDRESS_ 
136     * if it was not specified. In the later case a valid IP address is calculated. 
137     * @return the current environment's IP address, taking into account the Internet connection to any of the available
138     * machine's Network interfaces. Examples of the outputs can be in octet or in IPV6 format.
139     * Based on source code by Marcello de Sales (marcello.sales@gmail.com)
140     * from <tt>http://www.jguru.com/faq/view.jsp?EID=15835</tt> (adapted from Java 1.5 to 1.4)
141     * 
142     * Main change on code: !addr.isSiteLocalAddress() test removed because of inconsistencies in 
143     * linux and Android platforms when running under a private network configuration.
144     * This change implies that devices connected to a private and public network interface,
145     * getCurrentEnvironmentNetworkIp returns the first one found in the network interfaces 
146     * which may not be the desired one. For those cases it is recommended to use 
147     * -ip iat option to pass the desired IP address directly.
148     */
149    private static String getCurrentEnvironmentNetworkIp(String ipAddress) {
150    	if (ELVirtualMachine._DEFAULT_IP_ADDRESS_.equals(ipAddress)) {
151    		try {
152    			Enumeration netInterfaces = NetworkInterface.getNetworkInterfaces();
153    			while (netInterfaces.hasMoreElements()) {
154    				NetworkInterface ni = (NetworkInterface) netInterfaces.nextElement();
155    				Enumeration address = ni.getInetAddresses();
156    				while (address.hasMoreElements()) {
157    					InetAddress addr = (InetAddress) address.nextElement();
158    					// !addr.isSiteLocalAddress() removed, see note above.
159    					if (!addr.isLoopbackAddress() 
160                                && !(addr.getHostAddress().indexOf(":") > -1)) {
161                            return addr.getHostAddress();
162                        }
163    				}
164    			}
165    		} catch (SocketException e) { }
166
167    		try {
168    			return InetAddress.getLocalHost().getHostAddress();
169    		} catch (UnknownHostException e) {
170    			return "127.0.0.1";
171    		}
172    	} else{
173    		return ipAddress;
174    	}
175    }
176
177	
178	public String toString() {
179		return super.getName();
180	}
181}