You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by gn...@apache.org on 2014/12/12 14:18:15 UTC

[6/6] mina-sshd git commit: [SSHD-386] Allow controlling socket options

[SSHD-386] Allow controlling socket options

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

Branch: refs/heads/master
Commit: f3d58b906d795bac587f77eedb4647ad421b260d
Parents: 55bc681
Author: Guillaume Nodet <gn...@apache.org>
Authored: Fri Dec 12 14:07:55 2014 +0100
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Fri Dec 12 14:07:55 2014 +0100

----------------------------------------------------------------------
 .../org/apache/sshd/common/FactoryManager.java  | 42 ++++++++++++++++++++
 .../sshd/common/io/mina/MinaAcceptor.java       | 35 +++++-----------
 .../sshd/common/io/mina/MinaConnector.java      |  6 +--
 .../apache/sshd/common/io/mina/MinaService.java | 37 +++++++++++++++++
 .../sshd/common/io/nio2/Nio2Acceptor.java       | 14 ++++++-
 .../sshd/common/io/nio2/Nio2Connector.java      |  7 ++++
 .../apache/sshd/common/io/nio2/Nio2Service.java | 26 ++++++++++++
 7 files changed, 136 insertions(+), 31 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f3d58b90/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java b/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
index 037b718..c78f8e8 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
@@ -71,6 +71,48 @@ public interface FactoryManager {
     public static final String IDLE_TIMEOUT = "idle-timeout";
 
     /**
+     * Socket backlog.
+     * See {@link java.nio.channels.AsynchronousServerSocketChannel#bind(java.net.SocketAddress, int)}
+     */
+    public static final String SOCKET_BACKLOG = "socket-backlog";
+
+    /**
+     * Socket keep-alive.
+     * See {@link java.net.StandardSocketOptions#SO_KEEPALIVE}
+     */
+    public static final String SOCKET_KEEPALIVE = "socket-keepalive";
+
+    /**
+     * Socket send buffer size.
+     * See {@link java.net.StandardSocketOptions#SO_SNDBUF}
+     */
+    public static final String SOCKET_SNDBUF = "socket-sndbuf";
+
+    /**
+     * Socket receive buffer size.
+     * See {@link java.net.StandardSocketOptions#SO_RCVBUF}
+     */
+    public static final String SOCKET_RCVBUF = "socket-rcvbuf";
+
+    /**
+     * Socket reuse address.
+     * See {@link java.net.StandardSocketOptions#SO_REUSEADDR}
+     */
+    public static final String SOCKET_REUSEADDR = "socket-reuseaddr";
+
+    /**
+     * Socket linger.
+     * See {@link java.net.StandardSocketOptions#SO_LINGER}
+     */
+    public static final String SOCKET_LINGER = "socket-linger";
+
+    /**
+     * Socket tcp no-delay.
+     * See {@link java.net.StandardSocketOptions#TCP_NODELAY}
+     */
+    public static final String TCP_NODELAY = "tcp-nodelay";
+
+    /**
      * A map of properties that can be used to configure the SSH server
      * or client.  This map will never be changed by either the server or
      * client and is not supposed to be changed at runtime (changes are not

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f3d58b90/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 107972e..7a20d78 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
@@ -19,7 +19,6 @@
 package org.apache.sshd.common.io.mina;
 
 import java.io.IOException;
-import java.net.Socket;
 import java.net.SocketAddress;
 import java.util.Collection;
 import java.util.Set;
@@ -28,7 +27,6 @@ import org.apache.mina.core.service.IoAcceptor;
 import org.apache.mina.core.service.IoHandler;
 import org.apache.mina.core.service.IoProcessor;
 import org.apache.mina.core.service.IoService;
-import org.apache.mina.core.session.IoSessionConfig;
 import org.apache.mina.transport.socket.nio.NioSession;
 import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
 import org.apache.sshd.common.FactoryManager;
@@ -39,12 +37,20 @@ public class MinaAcceptor extends MinaService implements org.apache.sshd.common.
 
     protected volatile IoAcceptor acceptor;
     // Acceptor
-    protected int backlog = 50;
+    protected int backlog = 0;
     protected boolean reuseAddress = true;
-    protected IoSessionConfig sessionConfig;
 
     public MinaAcceptor(FactoryManager manager, org.apache.sshd.common.io.IoHandler handler, IoProcessor<NioSession> ioProcessor) {
         super(manager, handler, ioProcessor);
+
+        String valStr = manager.getProperties().get(FactoryManager.SOCKET_BACKLOG);
+        if (valStr != null) {
+            backlog = Integer.parseInt(valStr);
+        }
+        valStr = manager.getProperties().get(FactoryManager.SOCKET_REUSEADDR);
+        if (valStr != null) {
+            reuseAddress = Boolean.parseBoolean(valStr);
+        }
     }
 
     protected IoAcceptor createAcceptor() {
@@ -52,26 +58,7 @@ public class MinaAcceptor extends MinaService implements org.apache.sshd.common.
         acceptor.setCloseOnDeactivation(false);
         acceptor.setReuseAddress(reuseAddress);
         acceptor.setBacklog(backlog);
-
-        // MINA itself forces our socket receive buffer to 1024 bytes
-        // by default, despite what the operating system defaults to.
-        // This limits us to about 3 MB/s incoming data transfer.  By
-        // forcing back to the operating system default we can get a
-        // decent transfer rate again.
-        //
-        final Socket s = new Socket();
-        try {
-            try {
-                acceptor.getSessionConfig().setReceiveBufferSize(s.getReceiveBufferSize());
-            } finally {
-                s.close();
-            }
-        } catch (IOException e) {
-            log.warn("cannot adjust SO_RCVBUF back to system default", e);
-        }
-        if (sessionConfig != null) {
-            acceptor.getSessionConfig().setAll(sessionConfig);
-        }
+        configure(acceptor.getSessionConfig());
         return acceptor;
     }
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f3d58b90/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 8181652..6e4e368 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
@@ -25,7 +25,6 @@ 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.IoSessionConfig;
 import org.apache.mina.transport.socket.nio.NioSession;
 import org.apache.mina.transport.socket.nio.NioSocketConnector;
 import org.apache.sshd.common.FactoryManager;
@@ -37,7 +36,6 @@ import org.apache.sshd.common.io.IoConnectFuture;
 public class MinaConnector extends MinaService implements org.apache.sshd.common.io.IoConnector, IoHandler {
 
     protected volatile IoConnector connector;
-    protected IoSessionConfig sessionConfig;
 
     public MinaConnector(FactoryManager manager, org.apache.sshd.common.io.IoHandler handler, IoProcessor<NioSession> ioProcessor) {
         super(manager, handler, ioProcessor);
@@ -45,9 +43,7 @@ public class MinaConnector extends MinaService implements org.apache.sshd.common
 
     protected IoConnector createConnector() {
         NioSocketConnector connector = new NioSocketConnector(ioProcessor);
-        if (sessionConfig != null) {
-            connector.getSessionConfig().setAll(sessionConfig);
-        }
+        configure(connector.getSessionConfig());
         return connector;
     }
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f3d58b90/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 6d962ed..1981eb8 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
@@ -28,6 +28,8 @@ import org.apache.mina.core.service.IoProcessor;
 import org.apache.mina.core.service.IoService;
 import org.apache.mina.core.session.IdleStatus;
 import org.apache.mina.core.session.IoSession;
+import org.apache.mina.core.session.IoSessionConfig;
+import org.apache.mina.transport.socket.SocketSessionConfig;
 import org.apache.mina.transport.socket.nio.NioSession;
 import org.apache.sshd.common.Closeable;
 import org.apache.sshd.common.FactoryManager;
@@ -45,6 +47,7 @@ public abstract class MinaService extends IoHandlerAdapter implements org.apache
     protected final FactoryManager manager;
     protected final org.apache.sshd.common.io.IoHandler handler;
     protected final IoProcessor<NioSession> ioProcessor;
+    protected IoSessionConfig sessionConfig;
 
     public MinaService(FactoryManager manager, org.apache.sshd.common.io.IoHandler handler, IoProcessor<NioSession> ioProcessor) {
         this.manager = manager;
@@ -106,4 +109,38 @@ public abstract class MinaService extends IoHandlerAdapter implements org.apache
         return (org.apache.sshd.common.io.IoSession)
                 session.getAttribute(org.apache.sshd.common.io.IoSession.class);
     }
+
+    protected void configure(SocketSessionConfig config) {
+        Integer intVal;
+        Boolean boolVal;
+        if ((boolVal = getBoolean(FactoryManager.SOCKET_KEEPALIVE)) != null) {
+            config.setKeepAlive(boolVal);
+        }
+        if ((intVal = getInteger(FactoryManager.SOCKET_SNDBUF)) != null) {
+            config.setSendBufferSize(intVal);
+        }
+        if ((intVal = getInteger(FactoryManager.SOCKET_RCVBUF)) != null) {
+            config.setReceiveBufferSize(intVal);
+        }
+        if ((intVal = getInteger(FactoryManager.SOCKET_LINGER)) != null) {
+            config.setSoLinger(intVal);
+        }
+        if ((boolVal = getBoolean(FactoryManager.SOCKET_LINGER)) != null) {
+            config.setTcpNoDelay(boolVal);
+        }
+        if (sessionConfig != null) {
+            config.setAll(sessionConfig);
+        }
+    }
+
+    protected Integer getInteger(String property) {
+        String strVal = manager.getProperties().get(property);
+        return (strVal != null) ? Integer.parseInt(strVal) : null;
+    }
+
+    protected Boolean getBoolean(String property) {
+        String strVal = manager.getProperties().get(property);
+        return (strVal != null) ? Boolean.parseBoolean(strVal) : null;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f3d58b90/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 f9fab11..9bba704 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
@@ -41,18 +41,28 @@ import org.apache.sshd.common.io.IoHandler;
 public class Nio2Acceptor extends Nio2Service implements IoAcceptor {
 
     private final Map<SocketAddress, AsynchronousServerSocketChannel> channels;
-    private int backlog = 50;
+    private int backlog = 0;
 
     public Nio2Acceptor(FactoryManager manager, IoHandler handler, AsynchronousChannelGroup group) {
         super(manager, handler, group);
         channels = new ConcurrentHashMap<SocketAddress, AsynchronousServerSocketChannel>();
+
+        String valStr = manager.getProperties().get(FactoryManager.SOCKET_BACKLOG);
+        if (valStr != null) {
+            backlog = Integer.parseInt(valStr);
+        }
     }
 
     public void bind(Collection<? extends SocketAddress> addresses) throws IOException {
         for (SocketAddress address : addresses) {
             logger.debug("Binding Nio2Acceptor to address {}", address);
             AsynchronousServerSocketChannel socket = AsynchronousServerSocketChannel.open(group);
-            socket.setOption(StandardSocketOptions.SO_REUSEADDR, Boolean.TRUE);
+            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);
             socket.bind(address, backlog);
             SocketAddress local = socket.getLocalAddress();
             channels.put(local, socket);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f3d58b90/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 d427ef4..0ad182b 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,6 +20,7 @@ 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;
 
@@ -43,6 +44,12 @@ public class Nio2Connector extends Nio2Service implements IoConnector {
         final IoConnectFuture future = new DefaultIoConnectFuture(null);
         try {
             final AsynchronousSocketChannel socket = AsynchronousSocketChannel.open(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);
             socket.connect(address, null, new Nio2CompletionHandler<Void, Object>() {
                 protected void onCompleted(Void result, Object attachment) {
                     try {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f3d58b90/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 3c5a2b7..4bdb8f7 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
@@ -18,7 +18,10 @@
  */
 package org.apache.sshd.common.io.nio2;
 
+import java.io.IOException;
+import java.net.SocketOption;
 import java.nio.channels.AsynchronousChannelGroup;
+import java.nio.channels.NetworkChannel;
 import java.util.Collections;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
@@ -72,4 +75,27 @@ public abstract class Nio2Service extends CloseableUtils.AbstractInnerCloseable
     public void sessionClosed(Nio2Session session) {
         sessions.remove(session.getId());
     }
+
+    protected <T> void setOption(NetworkChannel socket, String property, SocketOption<T> option, T defaultValue) throws IOException {
+        String valStr = manager.getProperties().get(property);
+        T val = defaultValue;
+        if (valStr != null) {
+            Class<T> type = option.type();
+            if (type == Integer.class) {
+                val = type.cast(Integer.parseInt(valStr));
+            } else if (type == Boolean.class) {
+                val = type.cast(Boolean.parseBoolean(valStr));
+            } else {
+                throw new IllegalStateException("Unsupported socket option type " + type);
+            }
+        }
+        if (val != null) {
+            try {
+                socket.setOption(option, val);
+            } catch (IOException e) {
+                logger.warn("Unable to set socket option " + option + " to " + val, e);
+            }
+        }
+    }
+
 }