You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by lg...@apache.org on 2018/07/10 04:24:59 UTC

[2/3] mina-sshd git commit: [SSHD-832] Allow users to specify a local socket address when creating an SSH client connection

[SSHD-832] Allow users to specify a local socket address when creating an SSH client connection


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

Branch: refs/heads/master
Commit: f1cc85099aab8f8d9e09c054bcbbeea18fd669b1
Parents: 20dedf3
Author: Lyor Goldstein <ly...@gmail.com>
Authored: Mon Jul 9 21:11:41 2018 +0300
Committer: Goldstein Lyor <ly...@c-b4.com>
Committed: Tue Jul 10 07:24:51 2018 +0300

----------------------------------------------------------------------
 .../java/org/apache/sshd/client/SshClient.java  | 41 ++++++++-------
 .../client/session/ClientSessionCreator.java    | 52 ++++++++++++++++++--
 .../AbstractSimpleClientSessionCreator.java     | 19 ++++++-
 .../org/apache/sshd/common/AttributeStore.java  |  4 +-
 .../apache/sshd/common/io/IoConnectFuture.java  |  2 +-
 .../org/apache/sshd/common/io/IoSession.java    | 11 ++---
 .../apache/sshd/common/io/IoWriteFuture.java    |  2 +-
 7 files changed, 99 insertions(+), 32 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f1cc8509/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 733304f..143e4d7 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
@@ -131,7 +131,6 @@ import org.apache.sshd.common.util.net.SshdSocketAddress;
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
 public class SshClient extends AbstractFactoryManager implements ClientFactoryManager, ClientSessionCreator, Closeable {
-
     public static final Factory<SshClient> DEFAULT_SSH_CLIENT_FACTORY = SshClient::new;
 
     /**
@@ -433,7 +432,9 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
     }
 
     @Override
-    public ConnectFuture connect(String username, String host, int port) throws IOException {
+    public ConnectFuture connect(
+            String username, String host, int port, SocketAddress localAddress)
+                throws IOException {
         HostConfigEntryResolver resolver = getHostConfigEntryResolver();
         HostConfigEntry entry = resolver.resolveEffectiveHost(host, port, username);
         if (entry == null) {
@@ -455,14 +456,16 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
             }
         }
 
-        return connect(entry);
+        return connect(entry, localAddress);
     }
 
     @Override
-    public ConnectFuture connect(String username, SocketAddress address) throws IOException {
-        Objects.requireNonNull(address, "No target address");
-        if (address instanceof InetSocketAddress) {
-            InetSocketAddress inetAddress = (InetSocketAddress) address;
+    public ConnectFuture connect(
+            String username, SocketAddress targetAddress, SocketAddress localAddress)
+                throws IOException {
+        Objects.requireNonNull(targetAddress, "No target address");
+        if (targetAddress instanceof InetSocketAddress) {
+            InetSocketAddress inetAddress = (InetSocketAddress) targetAddress;
             String host = ValidateUtils.checkNotNullAndNotEmpty(inetAddress.getHostString(), "No host");
             int port = inetAddress.getPort();
             ValidateUtils.checkTrue(port > 0, "Invalid port: %d", port);
@@ -474,7 +477,7 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
                     log.debug("connect({}@{}:{}) no overrides", username, host, port);
                 }
 
-                return doConnect(username, address, Collections.emptyList(), true);
+                return doConnect(username, targetAddress, localAddress, Collections.emptyList(), true);
             } else {
                 if (log.isDebugEnabled()) {
                     log.debug("connect({}@{}:{}) effective: {}", username, host, port, entry);
@@ -484,21 +487,22 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
             }
         } else {
             if (log.isDebugEnabled()) {
-                log.debug("connect({}@{}) not an InetSocketAddress: {}", username, address, address.getClass().getName());
+                log.debug("connect({}@{}) not an InetSocketAddress: {}", username, targetAddress, targetAddress.getClass().getName());
             }
-            return doConnect(username, address, Collections.emptyList(), true);
+            return doConnect(username, targetAddress, localAddress, Collections.emptyList(), true);
         }
     }
 
     @Override
-    public ConnectFuture connect(HostConfigEntry hostConfig) throws IOException {
+    public ConnectFuture connect(HostConfigEntry hostConfig, SocketAddress localAddress) throws IOException {
         Objects.requireNonNull(hostConfig, "No host configuration");
         String host = ValidateUtils.checkNotNullAndNotEmpty(hostConfig.getHostName(), "No target host");
         int port = hostConfig.getPort();
         ValidateUtils.checkTrue(port > 0, "Invalid port: %d", port);
 
         Collection<KeyPair> keys = loadClientIdentities(hostConfig.getIdentities(), IoUtils.EMPTY_LINK_OPTIONS);
-        return doConnect(hostConfig.getUsername(), new InetSocketAddress(host, port), keys, !hostConfig.isIdentitiesOnly());
+        return doConnect(hostConfig.getUsername(), new InetSocketAddress(host, port),
+                localAddress, keys, !hostConfig.isIdentitiesOnly());
     }
 
     protected List<KeyPair> loadClientIdentities(Collection<String> locations, LinkOption... options) throws IOException {
@@ -544,16 +548,17 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
     }
 
     protected ConnectFuture doConnect(
-            String username, SocketAddress address, Collection<? extends KeyPair> identities,  boolean useDefaultIdentities)
-                    throws IOException {
+            String username, SocketAddress targetAddress, SocketAddress localAddress,
+            Collection<? extends KeyPair> identities, boolean useDefaultIdentities)
+                throws IOException {
         if (connector == null) {
             throw new IllegalStateException("SshClient not started. Please call start() method before connecting to a server");
         }
 
-        ConnectFuture connectFuture = new DefaultConnectFuture(username + "@" + address, null);
+        ConnectFuture connectFuture = new DefaultConnectFuture(username + "@" + targetAddress, null);
         SshFutureListener<IoConnectFuture> listener =
-            createConnectCompletionListener(connectFuture, username, address, identities, useDefaultIdentities);
-        connector.connect(address, null).addListener(listener);
+            createConnectCompletionListener(connectFuture, username, targetAddress, identities, useDefaultIdentities);
+        connector.connect(targetAddress, localAddress).addListener(listener);
         return connectFuture;
     }
 
@@ -573,7 +578,7 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
                 if (t != null) {
                     if (log.isDebugEnabled()) {
                         log.debug("operationComplete({}@{}) failed ({}): {}",
-                                  username, address, t.getClass().getSimpleName(), t.getMessage());
+                              username, address, t.getClass().getSimpleName(), t.getMessage());
                     }
                     connectFuture.setException(t);
                 } else {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f1cc8509/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSessionCreator.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSessionCreator.java b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSessionCreator.java
index c3d46e5..4d0a7e8 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSessionCreator.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSessionCreator.java
@@ -39,7 +39,24 @@ public interface ClientSessionCreator {
      * connect to it
      * @see #connect(HostConfigEntry)
      */
-    ConnectFuture connect(String username, String host, int port) throws IOException;
+    default ConnectFuture connect(String username, String host, int port) throws IOException {
+        return connect(username, host, port, null);
+    }
+
+    /**
+     * Resolves the <U>effective</U> {@link HostConfigEntry} and connects to it
+     *
+     * @param username The intended username
+     * @param host The target host name/address - never {@code null}/empty
+     * @param port The target port
+     * @param localAddress The local address to use - if {@code null} an
+     * automatic ephemeral port and bind address is used
+     * @return A {@link ConnectFuture}
+     * @throws IOException If failed to resolve the effective target or
+     * connect to it
+     * @see #connect(HostConfigEntry)
+     */
+    ConnectFuture connect(String username, String host, int port, SocketAddress localAddress) throws IOException;
 
     /**
      * Resolves the <U>effective</U> {@link HostConfigEntry} and connects to it
@@ -53,12 +70,41 @@ public interface ClientSessionCreator {
      * connect to it
      * @see #connect(HostConfigEntry)
      */
-    ConnectFuture connect(String username, SocketAddress address) throws IOException;
+    default ConnectFuture connect(String username, SocketAddress address) throws IOException {
+        return connect(username, address, null);
+    }
+
+    /**
+     * Resolves the <U>effective</U> {@link HostConfigEntry} and connects to it
+     *
+     * @param username The intended username
+     * @param targetAddress The intended target {@link SocketAddress} - never {@code null}.
+     * If this is an {@link java.net.InetSocketAddress} then the <U>effective</U>
+     * {@link HostConfigEntry} is resolved and used.
+     * @param localAddress The local address to use - if {@code null} an
+     * automatic ephemeral port and bind address is used
+     * @return A {@link ConnectFuture}
+     * @throws IOException If failed to resolve the effective target or
+     * connect to it
+     * @see #connect(HostConfigEntry)
+     */
+    ConnectFuture connect(String username, SocketAddress targetAddress, SocketAddress localAddress) throws IOException;
+
+    /**
+     * @param hostConfig The effective {@link HostConfigEntry} to connect to - never {@code null}
+     * @return A {@link ConnectFuture}
+     * @throws IOException If failed to create the connection future
+     */
+    default ConnectFuture connect(HostConfigEntry hostConfig) throws IOException {
+        return connect(hostConfig, null);
+    }
 
     /**
      * @param hostConfig The effective {@link HostConfigEntry} to connect to - never {@code null}
+     * @param localAddress The local address to use - if {@code null} an
+     * automatic ephemeral port and bind address is used
      * @return A {@link ConnectFuture}
      * @throws IOException If failed to create the connection future
      */
-    ConnectFuture connect(HostConfigEntry hostConfig) throws IOException;
+    ConnectFuture connect(HostConfigEntry hostConfig, SocketAddress localAddress) throws IOException;
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f1cc8509/sshd-core/src/main/java/org/apache/sshd/client/simple/AbstractSimpleClientSessionCreator.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/simple/AbstractSimpleClientSessionCreator.java b/sshd-core/src/main/java/org/apache/sshd/client/simple/AbstractSimpleClientSessionCreator.java
index b929c6f..3dd904f 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/simple/AbstractSimpleClientSessionCreator.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/simple/AbstractSimpleClientSessionCreator.java
@@ -136,7 +136,7 @@ public abstract class AbstractSimpleClientSessionCreator extends AbstractSimpleC
      * @return The {@link SimpleClient} wrapper. <B>Note:</B> closing the wrapper
      * also closes the underlying sessions creator.
      */
-    public static SimpleClient wrap(final ClientSessionCreator creator, final Channel channel) {
+    public static SimpleClient wrap(ClientSessionCreator creator, Channel channel) {
         Objects.requireNonNull(creator, "No sessions creator");
         Objects.requireNonNull(channel, "No channel");
         return new AbstractSimpleClientSessionCreator() {
@@ -146,16 +146,33 @@ public abstract class AbstractSimpleClientSessionCreator extends AbstractSimpleC
             }
 
             @Override
+            public ConnectFuture connect(String username, String host, int port, SocketAddress localAddress)
+                    throws IOException {
+                return creator.connect(username, host, port, localAddress);
+            }
+
+            @Override
             public ConnectFuture connect(String username, SocketAddress address) throws IOException {
                 return creator.connect(username, address);
             }
 
             @Override
+            public ConnectFuture connect(String username, SocketAddress targetAddress, SocketAddress localAddress)
+                    throws IOException {
+                return creator.connect(username, targetAddress, localAddress);
+            }
+
+            @Override
             public ConnectFuture connect(HostConfigEntry hostConfig) throws IOException {
                 return creator.connect(hostConfig);
             }
 
             @Override
+            public ConnectFuture connect(HostConfigEntry hostConfig, SocketAddress localAddress) throws IOException {
+                return creator.connect(hostConfig, localAddress);
+            }
+
+            @Override
             public boolean isOpen() {
                 return channel.isOpen();
             }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f1cc8509/sshd-core/src/main/java/org/apache/sshd/common/AttributeStore.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/AttributeStore.java b/sshd-core/src/main/java/org/apache/sshd/common/AttributeStore.java
index 4907efa..2b58d94 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/AttributeStore.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/AttributeStore.java
@@ -66,7 +66,7 @@ public interface AttributeStore {
      *
      * @param <T> The generic attribute type
      * @param key The key of the attribute; must not be {@code null}.
-     * @return <tt>null</tt> if there is no value associated with the specified key
+     * @return {@code null} if there is no value associated with the specified key
      */
     <T> T getAttribute(AttributeKey<T> key);
 
@@ -95,7 +95,7 @@ public interface AttributeStore {
      *
      * @param <T> The generic attribute type
      * @param key The key of the attribute; must not be {@code null}.
-     * @return <tt>null</tt> if there is no value associated with the specified key
+     * @return {@code null} if there is no value associated with the specified key
      */
     <T> T resolveAttribute(AttributeKey<T> key);
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f1cc8509/sshd-core/src/main/java/org/apache/sshd/common/io/IoConnectFuture.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/IoConnectFuture.java b/sshd-core/src/main/java/org/apache/sshd/common/io/IoConnectFuture.java
index 91f2a90..0f946b3 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/IoConnectFuture.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/IoConnectFuture.java
@@ -32,7 +32,7 @@ public interface IoConnectFuture extends SshFuture<IoConnectFuture> {
     /**
      * Returns the cause of the connection failure.
      *
-     * @return <tt>null</tt> if the connect operation is not finished yet,
+     * @return {@code null} if the connect operation is not finished yet,
      * or if the connection attempt is successful.
      * @see #getSession()
      */

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f1cc8509/sshd-core/src/main/java/org/apache/sshd/common/io/IoSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/IoSession.java b/sshd-core/src/main/java/org/apache/sshd/common/io/IoSession.java
index 1c629bd..489eda7 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/IoSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/IoSession.java
@@ -34,7 +34,7 @@ public interface IoSession extends PacketWriter, Closeable {
      * Returns the value of the user-defined attribute of this session.
      *
      * @param key the key of the attribute
-     * @return <tt>null</tt> if there is no attribute with the specified key
+     * @return {@code null} if there is no attribute with the specified key
      */
     Object getAttribute(Object key);
 
@@ -43,7 +43,7 @@ public interface IoSession extends PacketWriter, Closeable {
      *
      * @param key   the key of the attribute
      * @param value the value of the attribute
-     * @return The old value of the attribute.  <tt>null</tt> if it is new.
+     * @return The old value of the attribute.  {@code null} if it is new.
      */
     Object setAttribute(Object key, Object value);
 
@@ -61,7 +61,7 @@ public interface IoSession extends PacketWriter, Closeable {
      *
      * @param key The key of the attribute we want to set
      * @param value The value we want to set
-     * @return The old value of the attribute.  <tt>null</tt> if not found.
+     * @return The old value of the attribute.  {@code null} if not found.
      */
     Object setAttributeIfAbsent(Object key, Object value);
 
@@ -69,7 +69,7 @@ public interface IoSession extends PacketWriter, Closeable {
      * Removes a user-defined attribute with the specified key.
      *
      * @param key The key of the attribute we want to remove
-     * @return The old value of the attribute - <tt>null</tt> if not found.
+     * @return The old value of the attribute - {@code null} if not found.
      */
     Object removeAttribute(Object key);
 
@@ -79,8 +79,7 @@ public interface IoSession extends PacketWriter, Closeable {
     SocketAddress getRemoteAddress();
 
     /**
-     * @return the socket address of local machine which is associated with this
-     * session.
+     * @return the socket address of local machine which is associated with this session.
      */
     SocketAddress getLocalAddress();
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f1cc8509/sshd-core/src/main/java/org/apache/sshd/common/io/IoWriteFuture.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/IoWriteFuture.java b/sshd-core/src/main/java/org/apache/sshd/common/io/IoWriteFuture.java
index 95d33bd..543f285 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/IoWriteFuture.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/IoWriteFuture.java
@@ -30,7 +30,7 @@ public interface IoWriteFuture extends SshFuture<IoWriteFuture>, VerifiableFutur
     /**
      * @return the cause of the write failure if and only if the write
      * operation has failed due to an {@link Exception}.  Otherwise,
-     * <tt>null</tt> is returned (use {@link #isDone()} to distinguish
+     * {@code null} is returned (use {@link #isDone()} to distinguish
      * between the two.
      */
     Throwable getException();