/hazelcast/src/main/java/com/hazelcast/nio/SocketConnector.java

https://bitbucket.org/gabral6_gmailcom/hazelcast · Java · 173 lines · 140 code · 11 blank · 22 comment · 20 complexity · fb6c04fa406272ac8140115e76379994 MD5 · raw file

  1. /*
  2. * Copyright (c) 2008-2013, Hazelcast, Inc. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.hazelcast.nio;
  17. import com.hazelcast.logging.ILogger;
  18. import com.hazelcast.util.AddressUtil;
  19. import java.io.IOException;
  20. import java.net.*;
  21. import java.nio.channels.SocketChannel;
  22. import java.util.Collection;
  23. import java.util.logging.Level;
  24. public class SocketConnector implements Runnable {
  25. private final ConnectionManager connectionManager;
  26. private final Address address;
  27. private final ILogger logger;
  28. private final boolean silent;
  29. public SocketConnector(ConnectionManager connectionManager, Address address, boolean silent) {
  30. this.connectionManager = connectionManager;
  31. this.address = address;
  32. this.logger = connectionManager.ioService.getLogger(this.getClass().getName());
  33. this.silent = silent;
  34. }
  35. public void run() {
  36. if (!connectionManager.isLive()) {
  37. String message = "ConnectionManager is not live, connection attempt to " +
  38. address + " is cancelled!";
  39. log(Level.FINEST, message);
  40. return;
  41. }
  42. try {
  43. connectionManager.ioService.onIOThreadStart();
  44. log(Level.FINEST, "Starting to connect to " + address);
  45. final Address thisAddress = connectionManager.ioService.getThisAddress();
  46. if (address.isIPv4()) {
  47. // remote is IPv4; connect...
  48. tryToConnect(address.getInetSocketAddress(), 0);
  49. } else if (thisAddress.isIPv6() && thisAddress.getScopeId() != null) {
  50. // Both remote and this addresses are IPv6.
  51. // This is a local IPv6 address and scope id is known.
  52. // find correct inet6 address for remote and connect...
  53. final Inet6Address inetAddress = AddressUtil
  54. .getInetAddressFor((Inet6Address) address.getInetAddress(), thisAddress.getScopeId());
  55. tryToConnect(new InetSocketAddress(inetAddress, address.getPort()), 0);
  56. } else {
  57. // remote is IPv6 and this is either IPv4 or a global IPv6.
  58. // find possible remote inet6 addresses and try each one to connect...
  59. final Collection<Inet6Address> possibleInetAddresses = AddressUtil.getPossibleInetAddressesFor(
  60. (Inet6Address) address.getInetAddress());
  61. final Level level = silent ? Level.FINEST : Level.INFO;
  62. log(level, "Trying to connect possible IPv6 addresses: " + possibleInetAddresses);
  63. boolean connected = false;
  64. Exception error = null;
  65. for (Inet6Address inetAddress : possibleInetAddresses) {
  66. try {
  67. tryToConnect(new InetSocketAddress(inetAddress, address.getPort()), 3000);
  68. connected = true;
  69. break;
  70. } catch (Exception e) {
  71. error = e;
  72. }
  73. }
  74. if (!connected) {
  75. // could not connect any of addresses
  76. throw error;
  77. }
  78. }
  79. } catch (Throwable e) {
  80. logger.log(Level.FINEST, e.getMessage(), e);
  81. connectionManager.failedConnection(address, e, silent);
  82. }
  83. }
  84. private void tryToConnect(final InetSocketAddress socketAddress, final int timeout)
  85. throws Exception {
  86. final SocketChannel socketChannel = SocketChannel.open();
  87. connectionManager.initSocket(socketChannel.socket());
  88. bindSocket(socketChannel);
  89. final String message = "Connecting to " + socketAddress
  90. + ", timeout: " + timeout
  91. + ", bind-any: " + connectionManager.ioService.isSocketBindAny();
  92. log(Level.FINEST, message);
  93. try {
  94. socketChannel.configureBlocking(true);
  95. if (timeout > 0) {
  96. socketChannel.socket().connect(socketAddress, timeout);
  97. } else {
  98. socketChannel.connect(socketAddress);
  99. }
  100. log(Level.FINEST, "Successfully connected to: " + address + " using socket " + socketChannel.socket());
  101. MemberSocketInterceptor memberSocketInterceptor = connectionManager.getMemberSocketInterceptor();
  102. if (memberSocketInterceptor != null) {
  103. log(Level.FINEST, "Calling member socket interceptor: " + memberSocketInterceptor
  104. + " for " + socketChannel);
  105. memberSocketInterceptor.onConnect(socketChannel.socket());
  106. }
  107. socketChannel.configureBlocking(false);
  108. final SocketChannelWrapper socketChannelWrapper = connectionManager
  109. .wrapSocketChannel(socketChannel, true);
  110. Connection connection = connectionManager.assignSocketChannel(socketChannelWrapper);
  111. connectionManager.sendBindRequest(connection, address, true);
  112. } catch (Exception e) {
  113. closeSocket(socketChannel);
  114. final Level level = silent ? Level.FINEST : Level.INFO;
  115. log(level, "Could not connect to: "
  116. + socketAddress + ". Reason: " + e.getClass().getSimpleName()
  117. + "[" + e.getMessage() + "]");
  118. throw e;
  119. }
  120. }
  121. private void bindSocket(final SocketChannel socketChannel) throws IOException {
  122. final InetAddress inetAddress;
  123. if (connectionManager.ioService.isSocketBindAny()) {
  124. inetAddress = null;
  125. } else {
  126. final Address thisAddress = connectionManager.ioService.getThisAddress();
  127. inetAddress = thisAddress.getInetAddress();
  128. }
  129. final Socket socket = socketChannel.socket();
  130. if (connectionManager.useAnyOutboundPort()) {
  131. final SocketAddress socketAddress = new InetSocketAddress(inetAddress, 0);
  132. socket.bind(socketAddress);
  133. } else {
  134. IOException ex = null;
  135. final int retryCount = connectionManager.getOutboundPortCount() * 2;
  136. for (int i = 0; i < retryCount; i++) {
  137. final int port = connectionManager.acquireOutboundPort();
  138. final SocketAddress socketAddress = new InetSocketAddress(inetAddress, port);
  139. try {
  140. socket.bind(socketAddress);
  141. return;
  142. } catch (IOException e) {
  143. ex = e;
  144. log(Level.FINEST, "Could not bind port[ " + port + "]: " + e.getMessage());
  145. }
  146. }
  147. throw ex;
  148. }
  149. }
  150. private void closeSocket(final SocketChannel socketChannel) {
  151. if (socketChannel != null) {
  152. try {
  153. socketChannel.close();
  154. } catch (final IOException ignored) {
  155. }
  156. }
  157. }
  158. private void log(Level level, String message) {
  159. logger.log(level, message);
  160. connectionManager.ioService.getSystemLogService().logConnection(message);
  161. }
  162. }