NioServer: retain links by address string to minimize resource leak (#3525)

Every time a client connects, the NioServer will retain the link against
the InetSocketAddress object. If the same agent/client reconnects, it
will grow older links over time and in case of denial of service attack
or a client/script/monitoring-service reconnecting aggressively against
port 8250 will cause the `_links` weak hashmap to grow over time and
very quickly.

The fix will ensure that only one Link gets weakly retained for an
incoming client based on its address string.

Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
diff --git a/utils/src/main/java/com/cloud/utils/nio/Link.java b/utils/src/main/java/com/cloud/utils/nio/Link.java
index 6582440..9bc6abb 100644
--- a/utils/src/main/java/com/cloud/utils/nio/Link.java
+++ b/utils/src/main/java/com/cloud/utils/nio/Link.java
@@ -489,7 +489,7 @@
             try {
                 sslEngine.closeInbound();
             } catch (SSLException e) {
-                s_logger.warn("This SSL engine was forced to close inbound due to end of stream.");
+                s_logger.warn("This SSL engine was forced to close inbound due to end of stream.", e);
             }
             sslEngine.closeOutbound();
             // After closeOutbound the engine will be set to WRAP state,
diff --git a/utils/src/main/java/com/cloud/utils/nio/NioServer.java b/utils/src/main/java/com/cloud/utils/nio/NioServer.java
index ff54165..58ef463 100644
--- a/utils/src/main/java/com/cloud/utils/nio/NioServer.java
+++ b/utils/src/main/java/com/cloud/utils/nio/NioServer.java
@@ -25,6 +25,7 @@
 import java.nio.channels.SelectionKey;
 import java.nio.channels.ServerSocketChannel;
 import java.nio.channels.spi.SelectorProvider;
+import java.util.Map;
 import java.util.WeakHashMap;
 
 import org.apache.cloudstack.framework.ca.CAService;
@@ -36,13 +37,13 @@
     protected InetSocketAddress _localAddr;
     private ServerSocketChannel _serverSocket;
 
-    protected WeakHashMap<InetSocketAddress, Link> _links;
+    protected Map<String, Link> _links;
 
     public NioServer(final String name, final int port, final int workers, final HandlerFactory factory, final CAService caService) {
         super(name, port, workers, factory);
         setCAService(caService);
         _localAddr = null;
-        _links = new WeakHashMap<InetSocketAddress, Link>(1024);
+        _links = new WeakHashMap<String, Link>(10240);
     }
 
     public int getPort() {
@@ -61,7 +62,7 @@
 
         _serverSocket.register(_selector, SelectionKey.OP_ACCEPT, null);
 
-        s_logger.info("NioConnection started and listening on " + _serverSocket.socket().getLocalSocketAddress());
+        s_logger.info("NioServer started and listening on " + _serverSocket.socket().getLocalSocketAddress());
     }
 
     @Override
@@ -75,12 +76,12 @@
 
     @Override
     protected void registerLink(final InetSocketAddress addr, final Link link) {
-        _links.put(addr, link);
+        _links.put(addr.getAddress().toString(), link);
     }
 
     @Override
     protected void unregisterLink(final InetSocketAddress saddr) {
-        _links.remove(saddr);
+        _links.remove(saddr.getAddress().toString());
     }
 
     /**
@@ -93,7 +94,7 @@
      * @return null if not sent.  attach object in link if sent.
      */
     public Object send(final InetSocketAddress saddr, final byte[] data) throws ClosedChannelException {
-        final Link link = _links.get(saddr);
+        final Link link = _links.get(saddr.getAddress().toString());
         if (link == null) {
             return null;
         }