[SSHD-832] Allow user to specify local address for port forwarding

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

Branch: refs/heads/master
Commit: 20dedf3262bc7d067cf69fe3edab2a004ac40698
Parents: ace6c9f
Author: Markus Opitz <[email protected]>
Authored: Mon Jul 9 20:56:42 2018 +0300
Committer: Goldstein Lyor <[email protected]>
Committed: Tue Jul 10 07:24:51 2018 +0300

----------------------------------------------------------------------
 .../src/main/java/org/apache/sshd/client/SshClient.java |  5 +++--
 .../java/org/apache/sshd/common/io/IoConnector.java     | 10 ++++++++--
 .../org/apache/sshd/common/io/nio2/Nio2Connector.java   |  5 ++++-
 .../apache/sshd/server/forward/TcpipServerChannel.java  | 12 +++++++++++-
 .../org/apache/sshd/common/io/mina/MinaConnector.java   |  4 ++--
 .../java/org/apache/sshd/netty/NettyIoConnector.java    |  9 +++++++--
 6 files changed, 35 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/20dedf32/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java 
b/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java
index 31e4234..733304f 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java
@@ -551,8 +551,9 @@ public class SshClient extends AbstractFactoryManager 
implements ClientFactoryMa
         }
 
         ConnectFuture connectFuture = new DefaultConnectFuture(username + "@" 
+ address, null);
-        SshFutureListener<IoConnectFuture> listener = 
createConnectCompletionListener(connectFuture, username, address, identities, 
useDefaultIdentities);
-        connector.connect(address).addListener(listener);
+        SshFutureListener<IoConnectFuture> listener =
+            createConnectCompletionListener(connectFuture, username, address, 
identities, useDefaultIdentities);
+        connector.connect(address, null).addListener(listener);
         return connectFuture;
     }
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/20dedf32/sshd-core/src/main/java/org/apache/sshd/common/io/IoConnector.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/IoConnector.java 
b/sshd-core/src/main/java/org/apache/sshd/common/io/IoConnector.java
index 98ab8be..c546d44 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/IoConnector.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/IoConnector.java
@@ -21,9 +21,15 @@ package org.apache.sshd.common.io;
 import java.net.SocketAddress;
 
 /**
+ * @author <a href="mailto:[email protected]";>Apache MINA SSHD Project</a>
  */
 public interface IoConnector extends IoService {
 
-    IoConnectFuture connect(SocketAddress address);
-
+    /**
+     * @param targetAddress The target address to connect to
+     * @param localAddress The local address to use - if {@code null} an
+     * automatic ephemeral port and bind address is used
+     * @return The {@link IoConnectFuture future} representing the connection 
request
+     */
+    IoConnectFuture connect(SocketAddress targetAddress, SocketAddress 
localAddress);
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/20dedf32/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 7ccb5de..2924caf 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
@@ -43,7 +43,7 @@ public class Nio2Connector extends Nio2Service implements 
IoConnector {
     }
 
     @Override
-    public IoConnectFuture connect(SocketAddress address) {
+    public IoConnectFuture connect(SocketAddress address, SocketAddress 
localAddress) {
         boolean debugEnabled = log.isDebugEnabled();
         if (debugEnabled) {
             log.debug("Connecting to {}", address);
@@ -56,6 +56,9 @@ public class Nio2Connector extends Nio2Service implements 
IoConnector {
             AsynchronousChannelGroup group = getChannelGroup();
             channel = openAsynchronousSocketChannel(address, group);
             socket = setSocketOptions(channel);
+            if (localAddress != null) {
+                socket.bind(localAddress);
+            }
             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/20dedf32/sshd-core/src/main/java/org/apache/sshd/server/forward/TcpipServerChannel.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/server/forward/TcpipServerChannel.java
 
b/sshd-core/src/main/java/org/apache/sshd/server/forward/TcpipServerChannel.java
index a16a0de..949fd55 100644
--- 
a/sshd-core/src/main/java/org/apache/sshd/server/forward/TcpipServerChannel.java
+++ 
b/sshd-core/src/main/java/org/apache/sshd/server/forward/TcpipServerChannel.java
@@ -21,6 +21,7 @@ package org.apache.sshd.server.forward;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.net.ConnectException;
+import java.net.SocketAddress;
 import java.util.Collection;
 import java.util.Objects;
 import java.util.concurrent.ExecutorService;
@@ -102,6 +103,7 @@ public class TcpipServerChannel extends 
AbstractServerChannel implements Forward
     private SshdSocketAddress tunnelEntrance;
     private SshdSocketAddress tunnelExit;
     private SshdSocketAddress originatorAddress;
+    private SocketAddress localAddress;
 
     public TcpipServerChannel(ForwardingFilter.Type type) {
         this.type = Objects.requireNonNull(type, "No channel type specified");
@@ -111,6 +113,14 @@ public class TcpipServerChannel extends 
AbstractServerChannel implements Forward
         return type;
     }
 
+    public SocketAddress getLocalAddress() {
+        return localAddress;
+    }
+
+    public void setLocalAddress(SocketAddress localAddress) {
+        this.localAddress = localAddress;
+    }
+
     @Override
     public SshdSocketAddress getTunnelEntrance() {
         return tunnelEntrance;
@@ -227,7 +237,7 @@ public class TcpipServerChannel extends 
AbstractServerChannel implements Forward
 
         IoServiceFactory ioServiceFactory = manager.getIoServiceFactory();
         connector = ioServiceFactory.createConnector(handler);
-        IoConnectFuture future = 
connector.connect(address.toInetSocketAddress());
+        IoConnectFuture future = 
connector.connect(address.toInetSocketAddress(), getLocalAddress());
         future.addListener(future1 -> handleChannelConnectResult(f, future1));
         return f;
     }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/20dedf32/sshd-mina/src/main/java/org/apache/sshd/common/io/mina/MinaConnector.java
----------------------------------------------------------------------
diff --git 
a/sshd-mina/src/main/java/org/apache/sshd/common/io/mina/MinaConnector.java 
b/sshd-mina/src/main/java/org/apache/sshd/common/io/mina/MinaConnector.java
index 77bb90a..22e85cc 100644
--- a/sshd-mina/src/main/java/org/apache/sshd/common/io/mina/MinaConnector.java
+++ b/sshd-mina/src/main/java/org/apache/sshd/common/io/mina/MinaConnector.java
@@ -74,7 +74,7 @@ public class MinaConnector extends MinaService implements 
org.apache.sshd.common
     }
 
     @Override
-    public IoConnectFuture connect(SocketAddress address) {
+    public IoConnectFuture connect(SocketAddress address, SocketAddress 
localAddress) {
         class Future extends DefaultSshFuture<IoConnectFuture> implements 
IoConnectFuture {
             Future(Object lock) {
                 super(address, lock);
@@ -110,7 +110,7 @@ public class MinaConnector extends MinaService implements 
org.apache.sshd.common
 
         IoConnectFuture future = new Future(null);
         IoConnector connector = getConnector();
-        ConnectFuture connectFuture = connector.connect(address);
+        ConnectFuture connectFuture = connector.connect(address, localAddress);
         connectFuture.addListener((IoFutureListener<ConnectFuture>) cf -> {
             Throwable t = cf.getException();
             if (t != null) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/20dedf32/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoConnector.java
----------------------------------------------------------------------
diff --git 
a/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoConnector.java 
b/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoConnector.java
index c485790..9dde3d9 100644
--- a/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoConnector.java
+++ b/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoConnector.java
@@ -70,14 +70,19 @@ public class NettyIoConnector extends NettyIoService 
implements IoConnector {
     }
 
     @Override
-    public IoConnectFuture connect(SocketAddress address) {
+    public IoConnectFuture connect(SocketAddress address, SocketAddress 
localAddress) {
         boolean debugEnabled = log.isDebugEnabled();
         if (debugEnabled) {
             log.debug("Connecting to {}", address);
         }
 
         IoConnectFuture future = new DefaultIoConnectFuture(address, null);
-        ChannelFuture chf = bootstrap.connect(address);
+        ChannelFuture chf;
+        if (localAddress != null) {
+            chf = bootstrap.connect(address, localAddress);
+        } else {
+            chf = bootstrap.connect(address);
+        }
         Channel channel = chf.channel();
         channel.attr(CONNECT_FUTURE_KEY).set(future);
         chf.addListener(cf -> {

Reply via email to