/**
  * Binding completes the connection and makes it available to be used with the ConnectionManager.
  */
 private boolean bind(
     TcpIpConnection connection, Address remoteEndPoint, Address localEndpoint, boolean reply) {
   if (logger.isFinestEnabled()) {
     logger.finest("Binding " + connection + " to " + remoteEndPoint + ", reply is " + reply);
   }
   final Address thisAddress = ioService.getThisAddress();
   if (ioService.isSocketBindAny()
       && !connection.isClient()
       && !thisAddress.equals(localEndpoint)) {
     logger.warning(
         "Wrong bind request from "
             + remoteEndPoint
             + "! This node is not requested endpoint: "
             + localEndpoint);
     connection.close();
     return false;
   }
   connection.setEndPoint(remoteEndPoint);
   ioService.onSuccessfulConnection(remoteEndPoint);
   if (reply) {
     sendBindRequest(connection, remoteEndPoint, false);
   }
   if (checkAlreadyConnected(connection, remoteEndPoint)) {
     return false;
   }
   return registerConnection(remoteEndPoint, connection);
 }
 @Override
 public Connection getOrConnect(final Address address, final boolean silent) {
   Connection connection = connectionsMap.get(address);
   if (connection == null && live) {
     if (connectionsInProgress.add(address)) {
       ioService.shouldConnectTo(address);
       ioService.executeAsync(new InitConnectionTask(this, address, silent));
     }
   }
   return connection;
 }
 void sendBindRequest(TcpIpConnection connection, Address remoteEndPoint, boolean replyBack) {
   connection.setEndPoint(remoteEndPoint);
   ioService.onSuccessfulConnection(remoteEndPoint);
   // make sure bind packet is the first packet sent to the end point.
   if (logger.isFinestEnabled()) {
     logger.finest("Sending bind packet to " + remoteEndPoint);
   }
   BindMessage bind = new BindMessage(ioService.getThisAddress(), remoteEndPoint, replyBack);
   byte[] bytes = ioService.getSerializationService().toBytes(bind);
   Packet packet = new Packet(bytes);
   packet.setHeader(Packet.HEADER_BIND);
   connection.write(packet);
   // now you can send anything...
 }
  private void startAcceptorThread() {
    if (acceptorThread != null) {
      logger.warning("SocketAcceptor thread is already live! Shutting down old acceptor...");
      acceptorThread.shutdown();
      acceptorThread = null;
    }

    acceptorThread =
        new SocketAcceptorThread(
            ioService.getThreadGroup(),
            ioService.getThreadPrefix() + "Acceptor",
            serverSocketChannel,
            this);
    acceptorThread.start();
  }
 void failedConnection(Address address, Throwable t, boolean silent) {
   connectionsInProgress.remove(address);
   ioService.onFailedConnection(address);
   if (!silent) {
     getConnectionMonitor(address, false).onError(t);
   }
 }
 public boolean isSocketInterceptorEnabled() {
   final SocketInterceptorConfig socketInterceptorConfig = ioService.getSocketInterceptorConfig();
   if (socketInterceptorConfig != null && socketInterceptorConfig.isEnabled()) {
     return true;
   }
   return false;
 }
  public void destroyConnection(final Connection connection) {
    final Address endPoint = connection.getEndPoint();
    final boolean removed = mapConnections.remove(endPoint, connection);
    if (!removed) {
      return;
    }

    logger.info("Removed connection to endpoint: " + endPoint + ", connection: " + connection);
    ioService
        .getEventService()
        .executeEventCallback(
            new StripedRunnable() {
              @Override
              public void run() {
                for (ConnectionListener listener : connectionListeners) {
                  listener.connectionRemoved(connection);
                }
              }

              @Override
              public int getKey() {
                return endPoint.hashCode();
              }
            });
  }
  public TcpIpConnectionManager(
      IOService ioService,
      ServerSocketChannel serverSocketChannel,
      LoggingService loggingService,
      MetricsRegistry metricsRegistry,
      IOThreadingModel ioThreadingModel) {
    this.ioService = ioService;
    this.ioThreadingModel = ioThreadingModel;
    this.serverSocketChannel = serverSocketChannel;
    this.loggingService = loggingService;
    this.logger = loggingService.getLogger(TcpIpConnectionManager.class);
    final Collection<Integer> ports = ioService.getOutboundPorts();
    this.outboundPortCount = ports.size();
    this.outboundPorts.addAll(ports);
    this.socketChannelWrapperFactory = ioService.getSocketChannelWrapperFactory();

    metricsRegistry.scanAndRegister(this, "tcp.connection");
  }
  @Override
  public void handle(Packet packet) throws Exception {
    assert packet.isHeaderSet(Packet.HEADER_BIND);

    BindMessage bind = ioService.getSerializationService().toObject(packet);
    bind(
        (TcpIpConnection) packet.getConn(),
        bind.getLocalAddress(),
        bind.getTargetAddress(),
        bind.shouldReply());
  }
  @Override
  public boolean registerConnection(final Address remoteEndPoint, final Connection connection) {
    if (remoteEndPoint.equals(ioService.getThisAddress())) {
      return false;
    }

    if (connection instanceof TcpIpConnection) {
      TcpIpConnection tcpConnection = (TcpIpConnection) connection;
      Address currentEndPoint = tcpConnection.getEndPoint();
      if (currentEndPoint != null && !currentEndPoint.equals(remoteEndPoint)) {
        throw new IllegalArgumentException(
            connection + " has already a different endpoint than: " + remoteEndPoint);
      }
      tcpConnection.setEndPoint(remoteEndPoint);

      if (!connection.isClient()) {
        TcpIpConnectionMonitor connectionMonitor = getConnectionMonitor(remoteEndPoint, true);
        tcpConnection.setMonitor(connectionMonitor);
      }
    }
    connectionsMap.put(remoteEndPoint, connection);
    connectionsInProgress.remove(remoteEndPoint);
    ioService
        .getEventService()
        .executeEventCallback(
            new StripedRunnable() {
              @Override
              public void run() {
                for (ConnectionListener listener : connectionListeners) {
                  listener.connectionAdded(connection);
                }
              }

              @Override
              public int getKey() {
                return remoteEndPoint.hashCode();
              }
            });
    return true;
  }
 public void interceptSocket(Socket socket, boolean onAccept) throws IOException {
   if (!isSocketInterceptorEnabled()) {
     return;
   }
   final MemberSocketInterceptor memberSocketInterceptor = ioService.getMemberSocketInterceptor();
   if (memberSocketInterceptor == null) {
     return;
   }
   if (onAccept) {
     memberSocketInterceptor.onAccept(socket);
   } else {
     memberSocketInterceptor.onConnect(socket);
   }
 }
 public MockConnectionManager(
     IOService ioService,
     ConcurrentMap<Address, NodeEngineImpl> nodes,
     Node node,
     Object joinerLock) {
   this.ioService = ioService;
   this.nodes = nodes;
   this.node = node;
   this.joinerLock = joinerLock;
   this.logger = ioService.getLogger(MockConnectionManager.class.getName());
   synchronized (this.joinerLock) {
     this.nodes.put(node.getThisAddress(), node.nodeEngine);
   }
 }
 protected void initSocket(Socket socket) throws Exception {
   if (ioService.getSocketLingerSeconds() > 0) {
     socket.setSoLinger(true, ioService.getSocketLingerSeconds());
   }
   socket.setKeepAlive(ioService.getSocketKeepAlive());
   socket.setTcpNoDelay(ioService.getSocketNoDelay());
   socket.setReceiveBufferSize(ioService.getSocketReceiveBufferSize() * KILO_BYTE);
   socket.setSendBufferSize(ioService.getSocketSendBufferSize() * KILO_BYTE);
 }
  private boolean send(Packet packet, Address target, SendTask sendTask) {
    Connection connection = getConnection(target);
    if (connection != null) {
      return connection.write(packet);
    }

    if (sendTask == null) {
      sendTask = new SendTask(packet, target);
    }

    int retries = sendTask.retries;
    if (retries < RETRY_NUMBER && ioService.isActive()) {
      getOrConnect(target, true);
      // TODO: Caution: may break the order guarantee of the packets sent from the same thread!
      scheduler.schedule(sendTask, (retries + 1) * DELAY_FACTOR, TimeUnit.MILLISECONDS);
      return true;
    }
    return false;
  }
  private void fireConnectionRemovedEvent(final Connection connection, final Address endPoint) {
    if (live) {
      ioService
          .getEventService()
          .executeEventCallback(
              new StripedRunnable() {
                @Override
                public void run() {
                  for (ConnectionListener listener : connectionListeners) {
                    listener.connectionRemoved(connection);
                  }
                }

                @Override
                public int getKey() {
                  return endPoint.hashCode();
                }
              });
    }
  }
  @Override
  public boolean registerConnection(final Address remoteEndpoint, final Connection connection) {
    mapConnections.put(remoteEndpoint, (MockConnection) connection);
    ioService
        .getEventService()
        .executeEventCallback(
            new StripedRunnable() {
              @Override
              public void run() {
                for (ConnectionListener listener : connectionListeners) {
                  listener.connectionAdded(connection);
                }
              }

              @Override
              public int getKey() {
                return remoteEndpoint.hashCode();
              }
            });
    return true;
  }