/** run */
 public void run() {
   long now = System.currentTimeMillis();
   if ((socketCleaner == null) || (now - entry.getLastUse() >= connectionTimeout)) {
     if (logger.isDebugEnabled()) {
       logger.debug(
           "Socket has not been used for "
               + (now - entry.getLastUse())
               + " micro seconds, closing it");
     }
     sockets.remove(entry.getPeerAddress());
     try {
       synchronized (entry) {
         entry.getSocket().close();
       }
       logger.info("Socket to " + entry.getPeerAddress() + " closed due to timeout");
     } catch (IOException ex) {
       logger.error(ex);
     }
   } else {
     if (logger.isDebugEnabled()) {
       logger.debug("Scheduling " + ((entry.getLastUse() + connectionTimeout) - now));
     }
     socketCleaner.schedule(
         new SocketTimeout(entry), (entry.getLastUse() + connectionTimeout) - now);
   }
 }
 /** Closes all open sockets and stops the internal server thread that processes messages. */
 public void close() {
   ServerThread st = server;
   if (st != null) {
     st.close();
     try {
       st.join();
     } catch (InterruptedException ex) {
       logger.warn(ex);
     }
     server = null;
     for (Iterator it = sockets.values().iterator(); it.hasNext(); ) {
       SocketEntry entry = (SocketEntry) it.next();
       try {
         synchronized (entry) {
           entry.getSocket().close();
         }
         logger.debug("Socket to " + entry.getPeerAddress() + " closed");
       } catch (IOException iox) {
         // ingore
         logger.debug(iox);
       }
     }
     if (socketCleaner != null) {
       socketCleaner.cancel();
     }
     socketCleaner = null;
   }
 }
 /**
  * Closes a connection to the supplied remote address, if it is open. This method is particularly
  * useful when not using a timeout for remote connections.
  *
  * @param remoteAddress the address of the peer socket.
  * @return <code>true</code> if the connection has been closed and <code>false</code> if there was
  *     nothing to close.
  * @since 1.7.1
  */
 public synchronized boolean close(Address remoteAddress) throws IOException {
   if (logger.isDebugEnabled()) {
     logger.debug("Closing socket for peer address " + remoteAddress);
   }
   SocketEntry entry = (SocketEntry) sockets.remove(remoteAddress);
   if (entry != null) {
     synchronized (entry) {
       entry.getSocket().close();
     }
     logger.info("Socket to " + entry.getPeerAddress() + " closed");
     return true;
   }
   return false;
 }
    private void processPending() {
      synchronized (pending) {
        while (pending.size() > 0) {
          SocketEntry entry = (SocketEntry) pending.removeFirst();
          try {
            // Register the channel with the selector, indicating
            // interest in connection completion and attaching the
            // target object so that we can get the target back
            // after the key is added to the selector's
            // selected-key set
            if (entry.getSocket().isConnected()) {
              entry.getSocket().getChannel().register(selector, SelectionKey.OP_WRITE, entry);
            } else {
              entry.getSocket().getChannel().register(selector, SelectionKey.OP_CONNECT, entry);
            }

          } catch (IOException iox) {
            logger.error(iox);
            // Something went wrong, so close the channel and
            // record the failure
            try {
              entry.getSocket().getChannel().close();
              TransportStateEvent e =
                  new TransportStateEvent(
                      DefaultTcpTransportMapping.this,
                      entry.getPeerAddress(),
                      TransportStateEvent.STATE_CLOSED,
                      iox);
              fireConnectionStateChanged(e);
            } catch (IOException ex) {
              logger.error(ex);
            }
            lastError = iox;
          }
        }
      }
    }
    public void sendMessage(Address address, byte[] message) throws java.io.IOException {
      Socket s = null;
      SocketEntry entry = (SocketEntry) sockets.get(address);
      if (logger.isDebugEnabled()) {
        logger.debug("Looking up connection for destination '" + address + "' returned: " + entry);
        logger.debug(sockets.toString());
      }
      if (entry != null) {
        s = entry.getSocket();
      }
      if ((s == null) || (s.isClosed())) {
        if (logger.isDebugEnabled()) {
          logger.debug("Socket for address '" + address + "' is closed, opening it...");
        }
        SocketChannel sc = null;
        try {
          // Open the channel, set it to non-blocking, initiate connect
          sc = SocketChannel.open();
          sc.configureBlocking(false);
          sc.connect(
              new InetSocketAddress(
                  ((TcpAddress) address).getInetAddress(), ((TcpAddress) address).getPort()));
          s = sc.socket();
          entry = new SocketEntry((TcpAddress) address, s);
          entry.addMessage(message);
          sockets.put(address, entry);

          synchronized (pending) {
            pending.add(entry);
          }

          selector.wakeup();
          logger.debug("Trying to connect to " + address);
        } catch (IOException iox) {
          logger.error(iox);
          throw iox;
        }
      } else {
        entry.addMessage(message);
        synchronized (pending) {
          pending.add(entry);
        }
        selector.wakeup();
      }
    }
 private void readMessage(SelectionKey sk, SocketChannel readChannel, TcpAddress incomingAddress)
     throws IOException {
   // note that socket has been used
   SocketEntry entry = (SocketEntry) sockets.get(incomingAddress);
   if (entry != null) {
     entry.used();
     ByteBuffer readBuffer = entry.getReadBuffer();
     if (readBuffer != null) {
       readChannel.read(readBuffer);
       if (readBuffer.hasRemaining()) {
         readChannel.register(selector, SelectionKey.OP_READ, entry);
       } else {
         dispatchMessage(incomingAddress, readBuffer, readBuffer.capacity());
       }
       return;
     }
   }
   ByteBuffer byteBuffer = ByteBuffer.wrap(buf);
   byteBuffer.limit(messageLengthDecoder.getMinHeaderLength());
   long bytesRead = readChannel.read(byteBuffer);
   if (logger.isDebugEnabled()) {
     logger.debug("Reading header " + bytesRead + " bytes from " + incomingAddress);
   }
   MessageLength messageLength = new MessageLength(0, Integer.MIN_VALUE);
   if (bytesRead == messageLengthDecoder.getMinHeaderLength()) {
     messageLength = messageLengthDecoder.getMessageLength(ByteBuffer.wrap(buf));
     if (logger.isDebugEnabled()) {
       logger.debug("Message length is " + messageLength);
     }
     if ((messageLength.getMessageLength() > getMaxInboundMessageSize())
         || (messageLength.getMessageLength() <= 0)) {
       logger.error(
           "Received message length "
               + messageLength
               + " is greater than inboundBufferSize "
               + getMaxInboundMessageSize());
       synchronized (entry) {
         entry.getSocket().close();
         logger.info("Socket to " + entry.getPeerAddress() + " closed due to an error");
       }
     } else {
       byteBuffer.limit(messageLength.getMessageLength());
       bytesRead += readChannel.read(byteBuffer);
       if (bytesRead == messageLength.getMessageLength()) {
         dispatchMessage(incomingAddress, byteBuffer, bytesRead);
       } else {
         byte[] message = new byte[byteBuffer.limit()];
         byteBuffer.flip();
         byteBuffer.get(message, 0, byteBuffer.limit() - byteBuffer.remaining());
         entry.setReadBuffer(ByteBuffer.wrap(message));
       }
       readChannel.register(selector, SelectionKey.OP_READ, entry);
     }
   } else if (bytesRead < 0) {
     logger.debug("Socket closed remotely");
     sk.cancel();
     readChannel.close();
     TransportStateEvent e =
         new TransportStateEvent(
             DefaultTcpTransportMapping.this,
             incomingAddress,
             TransportStateEvent.STATE_DISCONNECTED_REMOTELY,
             null);
     fireConnectionStateChanged(e);
   }
 }