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