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