Updated Branches: refs/heads/master 555303e17 -> fea5aa335
[SSHD-264] DefaultSftpClient hangs on call to mkdir Fix the DefaultSftpClient to stop waiting when the channel is closed Fix the DefaultSftpClient to send attrs in the mkdir request Fix the SftpSubsystem to handle attributes in the mkdir request Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/fea5aa33 Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/fea5aa33 Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/fea5aa33 Branch: refs/heads/master Commit: fea5aa335af41cf86448335b64a88912ef5efd34 Parents: 555303e Author: Guillaume Nodet <[email protected]> Authored: Fri Jan 24 14:12:41 2014 +0100 Committer: Guillaume Nodet <[email protected]> Committed: Fri Jan 24 14:12:41 2014 +0100 ---------------------------------------------------------------------- .../sshd/client/channel/ChannelSubsystem.java | 10 ++++ .../sshd/client/sftp/DefaultSftpClient.java | 13 +++++ .../apache/sshd/server/sftp/SftpSubsystem.java | 3 + .../src/test/java/org/apache/sshd/SftpTest.java | 61 ++++++++++++-------- 4 files changed, 63 insertions(+), 24 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/fea5aa33/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSubsystem.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSubsystem.java b/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSubsystem.java index d38578c..965d486 100644 --- a/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSubsystem.java +++ b/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSubsystem.java @@ -21,6 +21,8 @@ package org.apache.sshd.client.channel; import java.io.IOException; import org.apache.sshd.common.SshConstants; +import org.apache.sshd.common.future.CloseFuture; +import org.apache.sshd.common.future.SshFutureListener; import org.apache.sshd.common.util.Buffer; /** @@ -50,4 +52,12 @@ public class ChannelSubsystem extends ChannelSession { super.doOpen(); } + + public void onClose(final Runnable run) { + closeFuture.addListener(new SshFutureListener<CloseFuture>() { + public void operationComplete(CloseFuture future) { + run.run(); + } + }); + } } http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/fea5aa33/sshd-core/src/main/java/org/apache/sshd/client/sftp/DefaultSftpClient.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/client/sftp/DefaultSftpClient.java b/sshd-core/src/main/java/org/apache/sshd/client/sftp/DefaultSftpClient.java index 0d5f62b..1f4f4a8 100644 --- a/sshd-core/src/main/java/org/apache/sshd/client/sftp/DefaultSftpClient.java +++ b/sshd-core/src/main/java/org/apache/sshd/client/sftp/DefaultSftpClient.java @@ -98,6 +98,7 @@ public class DefaultSftpClient implements SftpClient { private final Map<Integer, Buffer> messages; private final AtomicInteger cmdId = new AtomicInteger(100); private final Buffer receiveBuffer = new Buffer(); + private boolean closing; public DefaultSftpClient(ClientSession clientSession) throws IOException { this.clientSession = clientSession; @@ -119,6 +120,14 @@ public class DefaultSftpClient implements SftpClient { } catch (InterruptedException e) { throw (IOException) new InterruptedIOException().initCause(e); } + this.channel.onClose(new Runnable() { + public void run() { + synchronized (messages) { + closing = true; + messages.notifyAll(); + } + } + }); init(); } @@ -202,6 +211,9 @@ public class DefaultSftpClient implements SftpClient { protected Buffer receive(int id) throws IOException { synchronized (messages) { while (true) { + if (closing) { + throw new SshException("Channel has been closed"); + } Buffer buffer = messages.get(id); if (buffer != null) { return buffer; @@ -469,6 +481,7 @@ public class DefaultSftpClient implements SftpClient { public void mkdir(String path) throws IOException { Buffer buffer = new Buffer(); buffer.putString(path); + buffer.putInt(0); checkStatus(receive(send(SSH_FXP_MKDIR, buffer))); } http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/fea5aa33/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java b/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java index e0a82e1..94f50f3 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java @@ -651,6 +651,8 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste } case SSH_FXP_MKDIR: { String path = buffer.getString(); + Map<SshFile.Attribute, Object> attrs = readAttrs(buffer); + log.debug("Received SSH_FXP_MKDIR (path={})", path); // attrs try { @@ -666,6 +668,7 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste } else if (!p.mkdir()) { throw new IOException("Error creating dir " + path); } else { + p.setAttributes(attrs); sendStatus(id, SSH_FX_OK, ""); } } catch (IOException e) { http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/fea5aa33/sshd-core/src/test/java/org/apache/sshd/SftpTest.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/SftpTest.java b/sshd-core/src/test/java/org/apache/sshd/SftpTest.java index c3b03ce..e7cda02 100644 --- a/sshd-core/src/test/java/org/apache/sshd/SftpTest.java +++ b/sshd-core/src/test/java/org/apache/sshd/SftpTest.java @@ -31,6 +31,7 @@ import java.util.Vector; import com.jcraft.jsch.ChannelSftp; import com.jcraft.jsch.JSch; import com.jcraft.jsch.Logger; +import com.jcraft.jsch.UIKeyboardInteractive; import com.jcraft.jsch.UserInfo; import org.apache.sshd.client.SftpClient; import org.apache.sshd.common.NamedFactory; @@ -82,30 +83,7 @@ public class SftpTest { } }); session = sch.getSession("sshd", "localhost", port); - session.setUserInfo(new UserInfo() { - public String getPassphrase() { - return null; - } - - public String getPassword() { - return "sshd"; - } - - public boolean promptPassword(String message) { - return true; - } - - public boolean promptPassphrase(String message) { - return false; - } - - public boolean promptYesNo(String message) { - return true; - } - - public void showMessage(String message) { - } - }); + session.setUserInfo(new SimpleUserInfo("sshd")); session.connect(); } @@ -292,4 +270,39 @@ public class SftpTest { c.disconnect(); } + protected static class SimpleUserInfo implements UserInfo, UIKeyboardInteractive { + private final String password; + + public SimpleUserInfo(String password) { + this.password = password; + } + + public String getPassphrase() { + return null; + } + + public String getPassword() { + return password; + } + + public boolean promptPassword(String message) { + return true; + } + + public boolean promptPassphrase(String message) { + return false; + } + + public boolean promptYesNo(String message) { + return true; + } + + public void showMessage(String message) { + } + + public String[] promptKeyboardInteractive(String destination, String name, String instruction, String[] prompt, boolean[] echo) { + return new String[] { password }; + } + } + }
