Repository: mina-sshd
Updated Branches:
  refs/heads/master 168adf20a -> 331bdfc9d


[SSHD-722] Propagate socket settings on accepted SSHD server 
AsynchronousServerSocketChannel


Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/331bdfc9
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/331bdfc9
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/331bdfc9

Branch: refs/heads/master
Commit: 331bdfc9d9ef7473dadbd674548a08a7c2a9cc88
Parents: 168adf2
Author: Lyor Goldstein <lyor.goldst...@gmail.com>
Authored: Sat Dec 10 11:25:30 2016 +0200
Committer: Lyor Goldstein <lyor.goldst...@gmail.com>
Committed: Sat Dec 10 11:25:30 2016 +0200

----------------------------------------------------------------------
 .../keys/loader/putty/RSAPuttyKeyDecoder.java   |  1 -
 .../io/DefaultIoServiceFactoryFactory.java      |  2 +-
 .../org/apache/sshd/common/io/IoAcceptor.java   |  1 +
 .../org/apache/sshd/common/io/IoHandler.java    |  1 +
 .../org/apache/sshd/common/io/IoService.java    |  6 ++
 .../apache/sshd/common/io/IoServiceFactory.java |  1 +
 .../sshd/common/io/mina/MinaAcceptor.java       | 23 +++---
 .../sshd/common/io/mina/MinaConnector.java      | 24 ++++--
 .../apache/sshd/common/io/mina/MinaService.java | 57 ++++++++++++---
 .../sshd/common/io/nio2/Nio2Acceptor.java       | 15 ++--
 .../sshd/common/io/nio2/Nio2Connector.java      | 11 +--
 .../apache/sshd/common/io/nio2/Nio2Service.java | 77 +++++++++++++++-----
 .../sshd/common/io/nio2/Nio2ServiceFactory.java |  1 +
 .../apache/sshd/common/io/nio2/Nio2Session.java |  1 +
 .../java/org/apache/sshd/server/SshServer.java  |  4 +-
 .../sshd/common/io/nio2/Nio2ServiceTest.java    | 73 +++++++++++++++++--
 16 files changed, 221 insertions(+), 77 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/331bdfc9/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/RSAPuttyKeyDecoder.java
----------------------------------------------------------------------
diff --git 
a/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/RSAPuttyKeyDecoder.java
 
b/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/RSAPuttyKeyDecoder.java
index b4f9687..d0de05d 100644
--- 
a/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/RSAPuttyKeyDecoder.java
+++ 
b/sshd-contrib/src/main/java/org/apache/sshd/common/config/keys/loader/putty/RSAPuttyKeyDecoder.java
@@ -67,5 +67,4 @@ public class RSAPuttyKeyDecoder extends 
AbstractPuttyKeyDecoder {
         PrivateKey prvKey = kf.generatePrivate(prvSpec);
         return Collections.singletonList(new KeyPair(pubKey, prvKey));
     }
-
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/331bdfc9/sshd-core/src/main/java/org/apache/sshd/common/io/DefaultIoServiceFactoryFactory.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/io/DefaultIoServiceFactoryFactory.java
 
b/sshd-core/src/main/java/org/apache/sshd/common/io/DefaultIoServiceFactoryFactory.java
index aad572d..cfba0f4 100644
--- 
a/sshd-core/src/main/java/org/apache/sshd/common/io/DefaultIoServiceFactoryFactory.java
+++ 
b/sshd-core/src/main/java/org/apache/sshd/common/io/DefaultIoServiceFactoryFactory.java
@@ -29,9 +29,9 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
+ * @author <a href="mailto:d...@mina.apache.org";>Apache MINA SSHD Project</a>
  */
 public class DefaultIoServiceFactoryFactory extends 
AbstractIoServiceFactoryFactory {
-
     private static final Logger LOGGER = 
LoggerFactory.getLogger(DefaultIoServiceFactoryFactory.class);
 
     private IoServiceFactoryFactory factory;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/331bdfc9/sshd-core/src/main/java/org/apache/sshd/common/io/IoAcceptor.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/IoAcceptor.java 
b/sshd-core/src/main/java/org/apache/sshd/common/io/IoAcceptor.java
index ce38403..a86b73e 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/IoAcceptor.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/IoAcceptor.java
@@ -27,6 +27,7 @@ import java.util.Set;
  * @author <a href="mailto:d...@mina.apache.org";>Apache MINA SSHD Project</a>
  */
 public interface IoAcceptor extends IoService {
+    int DEFAULT_BACKLOG = 0;
 
     void bind(Collection<? extends SocketAddress> addresses) throws 
IOException;
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/331bdfc9/sshd-core/src/main/java/org/apache/sshd/common/io/IoHandler.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/IoHandler.java 
b/sshd-core/src/main/java/org/apache/sshd/common/io/IoHandler.java
index 7a34d35..848604d 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/IoHandler.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/IoHandler.java
@@ -21,6 +21,7 @@ package org.apache.sshd.common.io;
 import org.apache.sshd.common.util.Readable;
 
 /**
+ * @author <a href="mailto:d...@mina.apache.org";>Apache MINA SSHD Project</a>
  */
 public interface IoHandler {
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/331bdfc9/sshd-core/src/main/java/org/apache/sshd/common/io/IoService.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/IoService.java 
b/sshd-core/src/main/java/org/apache/sshd/common/io/IoService.java
index c73f8f2..69dcdee 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/IoService.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/IoService.java
@@ -23,8 +23,14 @@ import java.util.Map;
 import org.apache.sshd.common.Closeable;
 
 /**
+ * @author <a href="mailto:d...@mina.apache.org";>Apache MINA SSHD Project</a>
  */
 public interface IoService extends Closeable {
+    /**
+     * Socket reuse address.
+     * See {@link java.net.StandardSocketOptions#SO_REUSEADDR}
+     */
+    boolean DEFAULT_REUSE_ADDRESS = true;
 
     /**
      * Returns the map of all sessions which are currently managed by this

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/331bdfc9/sshd-core/src/main/java/org/apache/sshd/common/io/IoServiceFactory.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/io/IoServiceFactory.java 
b/sshd-core/src/main/java/org/apache/sshd/common/io/IoServiceFactory.java
index cec089c..6d8c261 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/IoServiceFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/IoServiceFactory.java
@@ -21,6 +21,7 @@ package org.apache.sshd.common.io;
 import org.apache.sshd.common.Closeable;
 
 /**
+ * @author <a href="mailto:d...@mina.apache.org";>Apache MINA SSHD Project</a>
  */
 public interface IoServiceFactory extends Closeable {
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/331bdfc9/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaAcceptor.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaAcceptor.java 
b/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaAcceptor.java
index bfd87f6..c49315d 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaAcceptor.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaAcceptor.java
@@ -34,11 +34,9 @@ import org.apache.sshd.common.FactoryManager;
 import org.apache.sshd.common.PropertyResolverUtils;
 
 /**
+ * @author <a href="mailto:d...@mina.apache.org";>Apache MINA SSHD Project</a>
  */
 public class MinaAcceptor extends MinaService implements 
org.apache.sshd.common.io.IoAcceptor, IoHandler {
-    public static final int DEFAULT_BACKLOG = 0;
-    public static final boolean DEFAULT_REUSE_ADDRESS = true;
-
     protected final AtomicReference<IoAcceptor> acceptorHolder = new 
AtomicReference<>(null);
 
     // Acceptor
@@ -85,32 +83,37 @@ public class MinaAcceptor extends MinaService implements 
org.apache.sshd.common.
 
     @Override
     public void bind(Collection<? extends SocketAddress> addresses) throws 
IOException {
-        getAcceptor().bind(addresses);
+        IoAcceptor acceptor = getAcceptor();
+        acceptor.bind(addresses);
     }
 
     @Override
     public void bind(SocketAddress address) throws IOException {
-        getAcceptor().bind(address);
+        IoAcceptor acceptor = getAcceptor();
+        acceptor.bind(address);
     }
 
     @Override
     public void unbind() {
-        getAcceptor().unbind();
+        IoAcceptor acceptor = getAcceptor();
+        acceptor.unbind();
     }
 
     @Override
     public void unbind(Collection<? extends SocketAddress> addresses) {
-        getAcceptor().unbind(addresses);
+        IoAcceptor acceptor = getAcceptor();
+        acceptor.unbind(addresses);
     }
 
     @Override
     public void unbind(SocketAddress address) {
-        getAcceptor().unbind(address);
+        IoAcceptor acceptor = getAcceptor();
+        acceptor.unbind(address);
     }
 
     @Override
     public Set<SocketAddress> getBoundAddresses() {
-        return getAcceptor().getLocalAddresses();
+        IoAcceptor acceptor = getAcceptor();
+        return acceptor.getLocalAddresses();
     }
-
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/331bdfc9/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaConnector.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaConnector.java 
b/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaConnector.java
index 176d565..4b48787 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaConnector.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaConnector.java
@@ -26,6 +26,7 @@ import org.apache.mina.core.future.IoFutureListener;
 import org.apache.mina.core.service.IoConnector;
 import org.apache.mina.core.service.IoHandler;
 import org.apache.mina.core.service.IoProcessor;
+import org.apache.mina.core.session.IoSession;
 import org.apache.mina.transport.socket.nio.NioSession;
 import org.apache.mina.transport.socket.nio.NioSocketConnector;
 import org.apache.sshd.common.FactoryManager;
@@ -33,9 +34,9 @@ import org.apache.sshd.common.future.DefaultSshFuture;
 import org.apache.sshd.common.io.IoConnectFuture;
 
 /**
+ * @author <a href="mailto:d...@mina.apache.org";>Apache MINA SSHD Project</a>
  */
 public class MinaConnector extends MinaService implements 
org.apache.sshd.common.io.IoConnector, IoHandler {
-
     protected final AtomicReference<IoConnector> connectorHolder = new 
AtomicReference<>(null);
 
     public MinaConnector(FactoryManager manager, 
org.apache.sshd.common.io.IoHandler handler, IoProcessor<NioSession> 
ioProcessor) {
@@ -61,7 +62,9 @@ public class MinaConnector extends MinaService implements 
org.apache.sshd.common
             connectorHolder.set(connector);
         }
 
-        log.debug("Created IoConnector");
+        if (log.isDebugEnabled()) {
+            log.debug("Created IoConnector");
+        }
         return connector;
     }
 
@@ -104,17 +107,22 @@ public class MinaConnector extends MinaService implements 
org.apache.sshd.common
                 setValue(exception);
             }
         }
-        final IoConnectFuture future = new Future(null);
-        
getConnector().connect(address).addListener((IoFutureListener<ConnectFuture>) 
cf -> {
-            if (cf.getException() != null) {
-                future.setException(cf.getException());
+
+        IoConnectFuture future = new Future(null);
+        IoConnector connector = getConnector();
+        ConnectFuture connectFuture = connector.connect(address);
+        connectFuture.addListener((IoFutureListener<ConnectFuture>) cf -> {
+            Throwable t = cf.getException();
+            if (t != null) {
+                future.setException(t);
             } else if (cf.isCanceled()) {
                 future.cancel();
             } else {
-                future.setSession(getSession(cf.getSession()));
+                IoSession ioSession = cf.getSession();
+                org.apache.sshd.common.io.IoSession sshSession = 
getSession(ioSession);
+                future.setSession(sshSession);
             }
         });
         return future;
     }
-
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/331bdfc9/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaService.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaService.java 
b/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaService.java
index 2bff584..65014fc 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaService.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaService.java
@@ -21,6 +21,7 @@ package org.apache.sshd.common.io.mina;
 import java.util.HashMap;
 import java.util.Map;
 
+import org.apache.mina.core.RuntimeIoException;
 import org.apache.mina.core.buffer.IoBuffer;
 import org.apache.mina.core.service.IoHandler;
 import org.apache.mina.core.service.IoProcessor;
@@ -33,9 +34,11 @@ import org.apache.mina.transport.socket.nio.NioSession;
 import org.apache.sshd.common.Closeable;
 import org.apache.sshd.common.FactoryManager;
 import org.apache.sshd.common.PropertyResolverUtils;
+import org.apache.sshd.common.util.GenericUtils;
 import org.apache.sshd.common.util.closeable.AbstractCloseable;
 
 /**
+ * @author <a href="mailto:d...@mina.apache.org";>Apache MINA SSHD Project</a>
  */
 public abstract class MinaService extends AbstractCloseable implements 
org.apache.sshd.common.io.IoService, IoHandler, Closeable {
     protected final FactoryManager manager;
@@ -52,12 +55,14 @@ public abstract class MinaService extends AbstractCloseable 
implements org.apach
     protected abstract IoService getIoService();
 
     public void dispose() {
-        getIoService().dispose();
+        IoService ioService = getIoService();
+        ioService.dispose();
     }
 
     @Override
     protected void doCloseImmediately() {
-        getIoService().dispose();
+        IoService ioService = getIoService();
+        ioService.dispose();
         super.doCloseImmediately();
     }
 
@@ -123,33 +128,62 @@ public abstract class MinaService extends 
AbstractCloseable implements org.apach
     }
 
     protected void configure(SocketSessionConfig config) {
-        Integer intVal;
-        Boolean boolVal;
-        boolVal = getBoolean(FactoryManager.SOCKET_KEEPALIVE);
+        Boolean boolVal = getBoolean(FactoryManager.SOCKET_KEEPALIVE);
         if (boolVal != null) {
-            config.setKeepAlive(boolVal);
+            try {
+                config.setKeepAlive(boolVal);
+            } catch (RuntimeIoException t) {
+                handleConfigurationError(config, 
FactoryManager.SOCKET_KEEPALIVE, boolVal, t);
+            }
         }
-        intVal = getInteger(FactoryManager.SOCKET_SNDBUF);
+
+        Integer intVal = getInteger(FactoryManager.SOCKET_SNDBUF);
         if (intVal != null) {
-            config.setSendBufferSize(intVal);
+            try {
+                config.setSendBufferSize(intVal);
+            } catch (RuntimeIoException t) {
+                handleConfigurationError(config, FactoryManager.SOCKET_SNDBUF, 
intVal, t);
+            }
         }
+
         intVal = getInteger(FactoryManager.SOCKET_RCVBUF);
         if (intVal != null) {
-            config.setReceiveBufferSize(intVal);
+            try {
+                config.setReceiveBufferSize(intVal);
+            } catch (RuntimeIoException t) {
+                handleConfigurationError(config, FactoryManager.SOCKET_RCVBUF, 
intVal, t);
+            }
         }
+
         intVal = getInteger(FactoryManager.SOCKET_LINGER);
         if (intVal != null) {
-            config.setSoLinger(intVal);
+            try {
+                config.setSoLinger(intVal);
+            } catch (RuntimeIoException t) {
+                handleConfigurationError(config, FactoryManager.SOCKET_LINGER, 
intVal, t);
+            }
         }
+
         boolVal = getBoolean(FactoryManager.TCP_NODELAY);
         if (boolVal != null) {
-            config.setTcpNoDelay(boolVal);
+            try {
+                config.setTcpNoDelay(boolVal);
+            } catch (RuntimeIoException t) {
+                handleConfigurationError(config, FactoryManager.TCP_NODELAY, 
boolVal, t);
+            }
         }
+
         if (sessionConfig != null) {
             config.setAll(sessionConfig);
         }
     }
 
+    protected void handleConfigurationError(SocketSessionConfig config, String 
propName, Object propValue, RuntimeIoException t) {
+        Throwable e = GenericUtils.resolveExceptionCause(t);
+        log.warn("handleConfigurationError({}={}) failed ({}) to configure: 
{}",
+                 propName, propValue, e.getClass().getSimpleName(), 
e.getMessage());
+    }
+
     protected Integer getInteger(String property) {
         return PropertyResolverUtils.getInteger(manager, property);
     }
@@ -157,5 +191,4 @@ public abstract class MinaService extends AbstractCloseable 
implements org.apach
     protected Boolean getBoolean(String property) {
         return PropertyResolverUtils.getBoolean(manager, property);
     }
-
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/331bdfc9/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Acceptor.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Acceptor.java 
b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Acceptor.java
index 83d79db..23be6c1 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Acceptor.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Acceptor.java
@@ -20,7 +20,6 @@ package org.apache.sshd.common.io.nio2;
 
 import java.io.IOException;
 import java.net.SocketAddress;
-import java.net.StandardSocketOptions;
 import java.nio.channels.AsynchronousChannelGroup;
 import java.nio.channels.AsynchronousServerSocketChannel;
 import java.nio.channels.AsynchronousSocketChannel;
@@ -41,10 +40,9 @@ import org.apache.sshd.common.io.IoHandler;
 import org.apache.sshd.common.util.ValidateUtils;
 
 /**
+ * @author <a href="mailto:d...@mina.apache.org";>Apache MINA SSHD Project</a>
  */
 public class Nio2Acceptor extends Nio2Service implements IoAcceptor {
-    public static final int DEFAULT_BACKLOG = 0;
-
     protected final Map<SocketAddress, AsynchronousServerSocketChannel> 
channels = new ConcurrentHashMap<>();
     private int backlog = DEFAULT_BACKLOG;
 
@@ -60,13 +58,9 @@ public class Nio2Acceptor extends Nio2Service implements 
IoAcceptor {
             if (log.isDebugEnabled()) {
                 log.debug("Binding Nio2Acceptor to address {}", address);
             }
-            AsynchronousServerSocketChannel socket = 
openAsynchronousServerSocketChannel(address, group);
-            setOption(socket, FactoryManager.SOCKET_KEEPALIVE, 
StandardSocketOptions.SO_KEEPALIVE, null);
-            setOption(socket, FactoryManager.SOCKET_LINGER, 
StandardSocketOptions.SO_LINGER, null);
-            setOption(socket, FactoryManager.SOCKET_RCVBUF, 
StandardSocketOptions.SO_RCVBUF, null);
-            setOption(socket, FactoryManager.SOCKET_REUSEADDR, 
StandardSocketOptions.SO_REUSEADDR, Boolean.TRUE);
-            setOption(socket, FactoryManager.SOCKET_SNDBUF, 
StandardSocketOptions.SO_SNDBUF, null);
-            setOption(socket, FactoryManager.TCP_NODELAY, 
StandardSocketOptions.TCP_NODELAY, null);
+
+            AsynchronousServerSocketChannel socket =
+                    
setSocketOptions(openAsynchronousServerSocketChannel(address, group));
             socket.bind(address, backlog);
             SocketAddress local = socket.getLocalAddress();
             channels.put(local, socket);
@@ -172,6 +166,7 @@ public class Nio2Acceptor extends Nio2Service implements 
IoAcceptor {
             try {
                 // Create a session
                 IoHandler handler = getIoHandler();
+                setSocketOptions(result);
                 session = 
Objects.requireNonNull(createSession(Nio2Acceptor.this, address, result, 
handler), "No NIO2 session created");
                 handler.sessionCreated(session);
                 sessions.put(session.getId(), session);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/331bdfc9/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Connector.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Connector.java 
b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Connector.java
index 2c2b6a5..c7a9fe5 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Connector.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Connector.java
@@ -20,7 +20,6 @@ package org.apache.sshd.common.io.nio2;
 
 import java.io.IOException;
 import java.net.SocketAddress;
-import java.net.StandardSocketOptions;
 import java.nio.channels.AsynchronousChannelGroup;
 import java.nio.channels.AsynchronousSocketChannel;
 
@@ -49,14 +48,8 @@ public class Nio2Connector extends Nio2Service implements 
IoConnector {
         IoConnectFuture future = new DefaultIoConnectFuture(null);
         try {
             AsynchronousChannelGroup group = getChannelGroup();
-            AsynchronousSocketChannel socket = 
openAsynchronousSocketChannel(address, group);
-            setOption(socket, FactoryManager.SOCKET_KEEPALIVE, 
StandardSocketOptions.SO_KEEPALIVE, null);
-            setOption(socket, FactoryManager.SOCKET_LINGER, 
StandardSocketOptions.SO_LINGER, null);
-            setOption(socket, FactoryManager.SOCKET_RCVBUF, 
StandardSocketOptions.SO_RCVBUF, null);
-            setOption(socket, FactoryManager.SOCKET_REUSEADDR, 
StandardSocketOptions.SO_REUSEADDR, Boolean.TRUE);
-            setOption(socket, FactoryManager.SOCKET_SNDBUF, 
StandardSocketOptions.SO_SNDBUF, null);
-            setOption(socket, FactoryManager.TCP_NODELAY, 
StandardSocketOptions.TCP_NODELAY, null);
-
+            AsynchronousSocketChannel socket =
+                    setSocketOptions(openAsynchronousSocketChannel(address, 
group));
             Nio2CompletionHandler<Void, Object> completionHandler =
                     
ValidateUtils.checkNotNull(createConnectionCompletionHandler(future, socket, 
getFactoryManager(), getIoHandler()),
                                                "No connection completion 
handler created for %s",

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/331bdfc9/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Service.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Service.java 
b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Service.java
index a031532..aab42c4 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Service.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Service.java
@@ -21,10 +21,12 @@ package org.apache.sshd.common.io.nio2;
 import java.io.IOException;
 import java.net.SocketOption;
 import java.net.SocketTimeoutException;
+import java.net.StandardSocketOptions;
 import java.nio.channels.AsynchronousChannelGroup;
 import java.nio.channels.NetworkChannel;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
@@ -39,11 +41,28 @@ import org.apache.sshd.common.io.IoHandler;
 import org.apache.sshd.common.io.IoService;
 import org.apache.sshd.common.io.IoSession;
 import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.Pair;
 import org.apache.sshd.common.util.closeable.AbstractInnerCloseable;
 
 /**
+ * @author <a href="mailto:d...@mina.apache.org";>Apache MINA SSHD Project</a>
  */
 public abstract class Nio2Service extends AbstractInnerCloseable implements 
IoService, FactoryManagerHolder {
+    public static final Map<String, Pair<SocketOption<?>, Object>> 
CONFIGURABLE_OPTIONS =
+            Collections.unmodifiableMap(new LinkedHashMap<String, 
Pair<SocketOption<?>, Object>>() {
+                // Not serializing it
+                private static final long serialVersionUID = 1L;
+
+                {
+                    put(FactoryManager.SOCKET_KEEPALIVE, new 
Pair<SocketOption<?>, Object>(StandardSocketOptions.SO_KEEPALIVE, null));
+                    put(FactoryManager.SOCKET_LINGER, new 
Pair<SocketOption<?>, Object>(StandardSocketOptions.SO_LINGER, null));
+                    put(FactoryManager.SOCKET_RCVBUF, new 
Pair<SocketOption<?>, Object>(StandardSocketOptions.SO_RCVBUF, null));
+                    put(FactoryManager.SOCKET_REUSEADDR, new 
Pair<SocketOption<?>, Object>(StandardSocketOptions.SO_REUSEADDR, 
DEFAULT_REUSE_ADDRESS));
+                    put(FactoryManager.SOCKET_SNDBUF, new 
Pair<SocketOption<?>, Object>(StandardSocketOptions.SO_SNDBUF, null));
+                    put(FactoryManager.TCP_NODELAY, new Pair<SocketOption<?>, 
Object>(StandardSocketOptions.TCP_NODELAY, null));
+                }
+            });
+
     protected final Map<Long, IoSession> sessions;
     protected final AtomicBoolean disposing = new AtomicBoolean();
     private final FactoryManager manager;
@@ -105,7 +124,25 @@ public abstract class Nio2Service extends 
AbstractInnerCloseable implements IoSe
         sessions.remove(session.getId());
     }
 
-    protected <T> void setOption(NetworkChannel socket, String property, 
SocketOption<T> option, T defaultValue) throws IOException {
+    @SuppressWarnings("unchecked")
+    protected <S extends NetworkChannel> S setSocketOptions(S socket) throws 
IOException {
+        Collection<? extends SocketOption<?>> supported = 
socket.supportedOptions();
+        if (GenericUtils.isEmpty(supported)) {
+            return socket;
+        }
+
+        for (Map.Entry<String, Pair<SocketOption<?>, Object>> ce : 
CONFIGURABLE_OPTIONS.entrySet()) {
+            String property = ce.getKey();
+            Pair<SocketOption<?>, Object> defConfig = ce.getValue();
+            @SuppressWarnings("rawtypes")
+            SocketOption option = defConfig.getKey();
+            setOption(socket, property, option, defConfig.getValue());
+        }
+
+        return socket;
+    }
+
+    protected <T> boolean setOption(NetworkChannel socket, String property, 
SocketOption<T> option, T defaultValue) throws IOException {
         PropertyResolver manager = getFactoryManager();
         String valStr = PropertyResolverUtils.getString(manager, property);
         T val = defaultValue;
@@ -116,28 +153,34 @@ public abstract class Nio2Service extends 
AbstractInnerCloseable implements IoSe
             } else if (type == Boolean.class) {
                 val = type.cast(Boolean.valueOf(valStr));
             } else {
-                throw new IllegalStateException("Unsupported socket option 
type " + type);
+                throw new IllegalStateException("Unsupported socket option 
type (" + type + ") " + property + "=" + valStr);
             }
         }
 
-        if (val != null) {
-            Collection<? extends SocketOption<?>> supported = 
socket.supportedOptions();
-            if ((GenericUtils.size(supported) <= 0) || 
(!supported.contains(option))) {
-                log.warn("Unsupported socket option (" + option + ") to set 
using property '" + property + "' value=" + val);
-                return;
+        if (val == null) {
+            return false;
+        }
+
+        Collection<? extends SocketOption<?>> supported = 
socket.supportedOptions();
+        if (GenericUtils.isEmpty(supported) || (!supported.contains(option))) {
+            if (log.isDebugEnabled()) {
+                log.debug("Unsupported socket option ({}) to set using {}={}", 
option, property, val);
             }
+            return false;
+        }
 
-            try {
-                socket.setOption(option, val);
-                if (log.isDebugEnabled()) {
-                    log.debug("setOption({})[{}] from property={}", option, 
val, property);
-                }
-            } catch (IOException | RuntimeException e) {
-                log.warn("Unable (" + e.getClass().getSimpleName() + ")"
-                       + " to set socket option " + option
-                       + " using property '" + property + "' value=" + val
-                       + ": " + e.getMessage());
+        try {
+            socket.setOption(option, val);
+            if (log.isDebugEnabled()) {
+                log.debug("setOption({})[{}] from property={}", option, val, 
property);
             }
+            return true;
+        } catch (IOException | RuntimeException e) {
+            log.warn("Unable (" + e.getClass().getSimpleName() + ")"
+                   + " to set socket option " + option
+                   + " using property " + property + "=" + val
+                   + ": " + e.getMessage());
+            return false;
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/331bdfc9/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactory.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactory.java
 
b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactory.java
index 5fb773f..1cdb651 100644
--- 
a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactory.java
+++ 
b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactory.java
@@ -32,6 +32,7 @@ import org.apache.sshd.common.io.IoHandler;
 import org.apache.sshd.common.util.threads.ThreadUtils;
 
 /**
+ * @author <a href="mailto:d...@mina.apache.org";>Apache MINA SSHD Project</a>
  */
 public class Nio2ServiceFactory extends AbstractIoServiceFactory {
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/331bdfc9/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Session.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Session.java 
b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Session.java
index 9947581..a007116 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Session.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Session.java
@@ -45,6 +45,7 @@ import org.apache.sshd.common.util.buffer.Buffer;
 import org.apache.sshd.common.util.closeable.AbstractCloseable;
 
 /**
+ * @author <a href="mailto:d...@mina.apache.org";>Apache MINA SSHD Project</a>
  */
 public class Nio2Session extends AbstractCloseable implements IoSession {
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/331bdfc9/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java 
b/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java
index aa06c44..7fc8004 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java
@@ -386,7 +386,9 @@ public class SshServer extends AbstractFactoryManager 
implements ServerFactoryMa
     }
 
     protected IoAcceptor createAcceptor() {
-        return getIoServiceFactory().createAcceptor(getSessionFactory());
+        IoServiceFactory ioFactory = getIoServiceFactory();
+        SessionFactory sessFactory = getSessionFactory();
+        return ioFactory.createAcceptor(sessFactory);
     }
 
     protected SessionFactory createSessionFactory() {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/331bdfc9/sshd-core/src/test/java/org/apache/sshd/common/io/nio2/Nio2ServiceTest.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/test/java/org/apache/sshd/common/io/nio2/Nio2ServiceTest.java 
b/sshd-core/src/test/java/org/apache/sshd/common/io/nio2/Nio2ServiceTest.java
index 8b51101..eae0bc8 100644
--- 
a/sshd-core/src/test/java/org/apache/sshd/common/io/nio2/Nio2ServiceTest.java
+++ 
b/sshd-core/src/test/java/org/apache/sshd/common/io/nio2/Nio2ServiceTest.java
@@ -20,11 +20,23 @@
 package org.apache.sshd.common.io.nio2;
 
 import java.net.Socket;
+import java.net.SocketOption;
+import java.nio.channels.AsynchronousSocketChannel;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.sshd.common.FactoryManager;
 import org.apache.sshd.common.PropertyResolverUtils;
+import org.apache.sshd.common.io.IoSession;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.Pair;
 import org.apache.sshd.server.SshServer;
+import org.apache.sshd.server.session.ServerSessionImpl;
+import org.apache.sshd.server.session.SessionFactory;
 import org.apache.sshd.util.test.BaseTestSupport;
 import org.junit.FixMethodOrder;
 import org.junit.Test;
@@ -39,24 +51,69 @@ public class Nio2ServiceTest extends BaseTestSupport {
         super();
     }
 
-    @Test   // see SSHD-554
+    @Test   // see SSHD-554, SSHD-722
     public void testSetSocketOptions() throws Exception {
         try (SshServer sshd = setupTestServer()) {
-            PropertyResolverUtils.updateProperty(sshd, 
FactoryManager.SOCKET_KEEPALIVE, true);
-            PropertyResolverUtils.updateProperty(sshd, 
FactoryManager.SOCKET_LINGER, 5);
-            PropertyResolverUtils.updateProperty(sshd, 
FactoryManager.SOCKET_RCVBUF, 1024);
-            PropertyResolverUtils.updateProperty(sshd, 
FactoryManager.SOCKET_REUSEADDR, true);
-            PropertyResolverUtils.updateProperty(sshd, 
FactoryManager.SOCKET_SNDBUF, 1024);
-            PropertyResolverUtils.updateProperty(sshd, 
FactoryManager.TCP_NODELAY, true);
+            Map<String, Object> expectedOptions =
+                    Collections.unmodifiableMap(new LinkedHashMap<String, 
Object>() {
+                        // Not serializing it
+                        private static final long serialVersionUID = 1L;
 
-            sshd.start();
+                        {
+                            put(FactoryManager.SOCKET_KEEPALIVE, true);
+                            put(FactoryManager.SOCKET_LINGER, 5);
+                            put(FactoryManager.SOCKET_RCVBUF, 1024);
+                            put(FactoryManager.SOCKET_REUSEADDR, true);
+                            put(FactoryManager.SOCKET_SNDBUF, 1024);
+                            put(FactoryManager.TCP_NODELAY, true);
+                        }
+                    });
+            for (Map.Entry<String, ?> oe : expectedOptions.entrySet()) {
+                PropertyResolverUtils.updateProperty(sshd, oe.getKey(), 
oe.getValue());
+            }
+
+            Semaphore sigSem = new Semaphore(0, true);
+            sshd.setSessionFactory(new SessionFactory(sshd) {
+                @Override
+                protected ServerSessionImpl doCreateSession(IoSession 
ioSession) throws Exception {
+                    validateSocketOptions(ioSession);
+                    sigSem.release();
+                    return super.doCreateSession(ioSession);
+                }
+
+                private void validateSocketOptions(IoSession ioSession) throws 
Exception {
+                    if (!(ioSession instanceof Nio2Session)) {
+                        return;
+                    }
 
+                    AsynchronousSocketChannel socket = ((Nio2Session) 
ioSession).getSocket();
+                    Collection<? extends SocketOption<?>> supported = 
socket.supportedOptions();
+                    if (GenericUtils.isEmpty(supported)) {
+                        return;
+                    }
+
+                    for (Map.Entry<String, ?> oe : expectedOptions.entrySet()) 
{
+                        String propName = oe.getKey();
+                        Object expValue = oe.getValue();
+                        Pair<SocketOption<?>, ?> optionEntry = 
Nio2Service.CONFIGURABLE_OPTIONS.get(propName);
+                        SocketOption<?> option = optionEntry.getKey();
+                        if (!supported.contains(option)) {
+                            continue;
+                        }
+
+                        Object actValue = socket.getOption(option);
+                        assertEquals("Mismatched value for " + propName + "/" 
+ option, expValue, actValue);
+                    }
+                }
+            });
+            sshd.start();
             int port = sshd.getPort();
             long startTime = System.nanoTime();
             try (Socket s = new Socket(TEST_LOCALHOST, port)) {
                 long endTime = System.nanoTime();
                 long duration = endTime - startTime;
                 assertTrue("Connect duration is too high: " + duration, 
duration <= TimeUnit.SECONDS.toNanos(15L));
+                assertTrue("Validation not completed on time", 
sigSem.tryAcquire(15L, TimeUnit.SECONDS));
             } finally {
                 sshd.stop();
             }

Reply via email to