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 };
+        }
+    }
+
 }

Reply via email to