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 2018/04/19 15:07:57 UTC

[1/5] mina-sshd git commit: [SSHD-812] Small refactoring of the process method [Forced Update!]

Repository: mina-sshd
Updated Branches:
  refs/heads/master 91592c0f1 -> e07479f73 (forced update)


[SSHD-812] Small refactoring of the process method


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

Branch: refs/heads/master
Commit: 75e7513ad73fe150d7add11a86a822e7660c16e3
Parents: ec9c0d8
Author: Guillaume Nodet <gn...@apache.org>
Authored: Thu Apr 19 10:49:14 2018 +0200
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Thu Apr 19 17:07:26 2018 +0200

----------------------------------------------------------------------
 .../server/subsystem/sftp/SftpSubsystem.java    | 25 +++++++++++++++-----
 1 file changed, 19 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/75e7513a/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
----------------------------------------------------------------------
diff --git a/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java b/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
index 3743477..e07ee83 100644
--- a/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
+++ b/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
@@ -298,6 +298,13 @@ public class SftpSubsystem
         }
     }
 
+    /**
+     * Process an SFTP command.
+     * If the command throws an exception, the channel will be closed.
+     *
+     * @param buffer the buffer to process
+     * @throws IOException if anything wrong happens
+     */
     @Override
     protected void process(Buffer buffer) throws IOException {
         int length = buffer.getInt();
@@ -307,7 +314,10 @@ public class SftpSubsystem
             log.debug("process({})[length={}, type={}, id={}] processing",
                       getServerSession(), length, SftpConstants.getCommandMessageName(type), id);
         }
+        doProcess(buffer, length, type, id);
+    }
 
+    protected void doProcess(Buffer buffer, int length, int type, int id) throws IOException {
         switch (type) {
             case SftpConstants.SSH_FXP_INIT:
                 doInit(buffer, id);
@@ -379,12 +389,8 @@ public class SftpSubsystem
                 doExtended(buffer, id);
                 break;
             default:
-            {
-                String name = SftpConstants.getCommandMessageName(type);
-                log.warn("process({})[length={}, type={}, id={}] unknown command",
-                         getServerSession(), length, name, id);
-                sendStatus(BufferUtils.clear(buffer), id, SftpConstants.SSH_FX_OP_UNSUPPORTED, "Command " + name + " is unsupported or not implemented");
-            }
+                doUnsupported(buffer, length, type, id);
+                break;
         }
 
         if (type != SftpConstants.SSH_FXP_INIT) {
@@ -392,6 +398,13 @@ public class SftpSubsystem
         }
     }
 
+    protected void doUnsupported(Buffer buffer, int length, int type, int id) throws IOException {
+        String name = SftpConstants.getCommandMessageName(type);
+        log.warn("process({})[length={}, type={}, id={}] unknown command",
+                 getServerSession(), length, name, id);
+        sendStatus(BufferUtils.clear(buffer), id, SftpConstants.SSH_FX_OP_UNSUPPORTED, "Command " + name + " is unsupported or not implemented");
+    }
+
     @Override
     protected void executeExtendedCommand(Buffer buffer, int id, String extension) throws IOException {
         switch (extension) {


[5/5] mina-sshd git commit: [SSHD-812] Make SftpSubsystem an AsyncCommand

Posted by gn...@apache.org.
[SSHD-812] Make SftpSubsystem an AsyncCommand


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

Branch: refs/heads/master
Commit: e07479f73966aee22be285ba3fc7e7d7ac3e9aea
Parents: 6bed356
Author: Guillaume Nodet <gn...@apache.org>
Authored: Thu Apr 19 17:03:59 2018 +0200
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Thu Apr 19 17:07:41 2018 +0200

----------------------------------------------------------------------
 .../server/subsystem/sftp/SftpSubsystem.java    | 112 ++++++++++++++-----
 1 file changed, 83 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e07479f7/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
----------------------------------------------------------------------
diff --git a/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java b/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
index ab1794e..ba73695 100644
--- a/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
+++ b/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
@@ -39,15 +39,20 @@ import java.util.Iterator;
 import java.util.Map;
 import java.util.Objects;
 import java.util.TreeMap;
+import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.sshd.common.Factory;
 import org.apache.sshd.common.FactoryManager;
+import org.apache.sshd.common.channel.BufferedIoOutputStream;
 import org.apache.sshd.common.digest.BuiltinDigests;
 import org.apache.sshd.common.digest.DigestFactory;
 import org.apache.sshd.common.file.FileSystemAware;
+import org.apache.sshd.common.io.IoInputStream;
+import org.apache.sshd.common.io.IoOutputStream;
 import org.apache.sshd.common.random.Random;
 import org.apache.sshd.common.subsystem.sftp.SftpConstants;
 import org.apache.sshd.common.subsystem.sftp.SftpHelper;
@@ -59,10 +64,14 @@ import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
 import org.apache.sshd.common.util.io.IoUtils;
 import org.apache.sshd.common.util.threads.ExecutorServiceCarrier;
 import org.apache.sshd.common.util.threads.ThreadUtils;
+import org.apache.sshd.server.AsyncCommand;
+import org.apache.sshd.server.ChannelSessionAware;
 import org.apache.sshd.server.Command;
 import org.apache.sshd.server.Environment;
 import org.apache.sshd.server.ExitCallback;
 import org.apache.sshd.server.SessionAware;
+import org.apache.sshd.server.channel.ChannelDataReceiver;
+import org.apache.sshd.server.channel.ChannelSession;
 import org.apache.sshd.server.session.ServerSession;
 
 /**
@@ -72,7 +81,8 @@ import org.apache.sshd.server.session.ServerSession;
  */
 public class SftpSubsystem
         extends AbstractSftpSubsystemHelper
-        implements Command, Runnable, SessionAware, FileSystemAware, ExecutorServiceCarrier {
+        implements Command, Runnable, SessionAware, FileSystemAware, ExecutorServiceCarrier,
+                    AsyncCommand, ChannelSessionAware, ChannelDataReceiver {
 
     /**
      * Properties key for the maximum of available open handles per session.
@@ -111,10 +121,11 @@ public class SftpSubsystem
     public static final String MAX_READDIR_DATA_SIZE_PROP = "sftp-max-readdir-data-size";
     public static final int DEFAULT_MAX_READDIR_DATA_SIZE = 16 * 1024;
 
+    protected static final Buffer CLOSE = new ByteArrayBuffer(null, 0, 0);
+
     protected ExitCallback callback;
-    protected InputStream in;
-    protected OutputStream out;
-    protected OutputStream err;
+    protected IoOutputStream out;
+    protected IoOutputStream err;
     protected Environment env;
     protected Random randomizer;
     protected int fileHandleSize = DEFAULT_FILE_HANDLE_SIZE;
@@ -127,11 +138,14 @@ public class SftpSubsystem
     protected int version;
     protected final Map<String, byte[]> extensions = new TreeMap<>(Comparator.naturalOrder());
     protected final Map<String, Handle> handles = new HashMap<>();
+    protected final Buffer buffer = new ByteArrayBuffer(1024);
+    protected final BlockingQueue<Buffer> requests = new LinkedBlockingQueue<>();
 
-    private ServerSession serverSession;
-    private final AtomicBoolean closed = new AtomicBoolean(false);
-    private ExecutorService executorService;
-    private boolean shutdownOnExit;
+    protected ServerSession serverSession;
+    protected ChannelSession channelSession;
+    protected final AtomicBoolean closed = new AtomicBoolean(false);
+    protected ExecutorService executorService;
+    protected boolean shutdownOnExit;
 
     /**
      * @param executorService The {@link ExecutorService} to be used by
@@ -207,6 +221,12 @@ public class SftpSubsystem
     }
 
     @Override
+    public void setChannelSession(ChannelSession session) {
+        this.channelSession = session;
+        session.setDataReceiver(this);
+    }
+
+    @Override
     public void setFileSystem(FileSystem fileSystem) {
         if (fileSystem != this.fileSystem) {
             this.fileSystem = fileSystem;
@@ -225,16 +245,31 @@ public class SftpSubsystem
 
     @Override
     public void setInputStream(InputStream in) {
-        this.in = in;
+        // Do nothing
     }
 
     @Override
     public void setOutputStream(OutputStream out) {
-        this.out = out;
+        // Do nothing
     }
 
     @Override
     public void setErrorStream(OutputStream err) {
+        // Do nothing
+    }
+
+    @Override
+    public void setIoInputStream(IoInputStream in) {
+        // Do nothing
+    }
+
+    @Override
+    public void setIoOutputStream(IoOutputStream out) {
+        this.out = new BufferedIoOutputStream("sftp out buffer", out);
+    }
+
+    @Override
+    public void setIoErrorStream(IoOutputStream err) {
         this.err = err;
     }
 
@@ -251,27 +286,40 @@ public class SftpSubsystem
     }
 
     @Override
+    public int data(ChannelSession channel, byte[] buf, int start, int len) throws IOException {
+        buffer.compact();
+        buffer.putRawBytes(buf, start, len);
+        while (buffer.available() >= Integer.BYTES) {
+            int rpos = buffer.rpos();
+            int msglen = buffer.getInt();
+            if (buffer.available() >= msglen) {
+                Buffer b = new ByteArrayBuffer(msglen + Integer.BYTES + Long.SIZE /* a bit extra */, false);
+                b.putInt(msglen);
+                b.putRawBytes(buffer.array(), buffer.rpos(), msglen);
+                requests.add(b);
+                buffer.rpos(rpos + msglen + Integer.BYTES);
+            } else {
+                buffer.rpos(rpos);
+                break;
+            }
+        }
+        return 0;
+    }
+
+    @Override
     public void run() {
         try {
-            for (long count = 1L;; count++) {
-                int length = BufferUtils.readInt(in, workBuf, 0, workBuf.length);
-                ValidateUtils.checkTrue(length >= (Integer.BYTES + 1 /* command */), "Bad length to read: %d", length);
-
-                Buffer buffer = new ByteArrayBuffer(length + Integer.BYTES + Long.SIZE /* a bit extra */, false);
-                buffer.putInt(length);
-                for (int remainLen = length; remainLen > 0;) {
-                    int l = in.read(buffer.array(), buffer.wpos(), remainLen);
-                    if (l < 0) {
-                        throw new IllegalArgumentException("Premature EOF at buffer #" + count + " while read length=" + length + " and remain=" + remainLen);
-                    }
-                    buffer.wpos(buffer.wpos() + l);
-                    remainLen -= l;
+            while (true) {
+                Buffer buffer = requests.take();
+                if (buffer == CLOSE) {
+                    break;
                 }
-
+                int len = buffer.available();
                 process(buffer);
+                channelSession.getLocalWindow().consumeAndCheck(len);
             }
         } catch (Throwable t) {
-            if ((!closed.get()) && (!(t instanceof EOFException))) { // Ignore
+            if (!closed.get()) { // Ignore
                 log.error("run({}) {} caught in SFTP subsystem: {}",
                           getServerSession(), t.getClass().getSimpleName(), t.getMessage());
                 if (log.isDebugEnabled()) {
@@ -296,6 +344,13 @@ public class SftpSubsystem
         }
     }
 
+    @Override
+    public void close() throws IOException {
+        requests.clear();
+        requests.add(CLOSE);
+    }
+
+    @Override
     protected void doProcess(Buffer buffer, int length, int type, int id) throws IOException {
         super.doProcess(buffer, length, type, id);
         if (type != SftpConstants.SSH_FXP_INIT) {
@@ -873,15 +928,14 @@ public class SftpSubsystem
     @Override
     protected Buffer prepareReply(Buffer buffer) {
         buffer.clear();
+        buffer.putInt(0);
         return buffer;
     }
 
     @Override
     protected void send(Buffer buffer) throws IOException {
-        int len = buffer.available();
-        BufferUtils.writeInt(out, len, workBuf, 0, workBuf.length);
-        out.write(buffer.array(), buffer.rpos(), len);
-        out.flush();
+        BufferUtils.updateLengthPlaceholder(buffer, 0);
+        out.writePacket(buffer);
     }
 
     @Override


[2/5] mina-sshd git commit: [SSHD-812] Move process() to AbstractSftpSubsystemHelper

Posted by gn...@apache.org.
[SSHD-812] Move process() to AbstractSftpSubsystemHelper


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

Branch: refs/heads/master
Commit: ef237380c5e84a79a77d67410e88a5036a18686d
Parents: 75e7513
Author: Guillaume Nodet <gn...@apache.org>
Authored: Thu Apr 19 11:05:06 2018 +0200
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Thu Apr 19 17:07:31 2018 +0200

----------------------------------------------------------------------
 .../sftp/AbstractSftpSubsystemHelper.java       | 113 ++++++++++++++++++-
 .../server/subsystem/sftp/SftpSubsystem.java    | 105 +----------------
 2 files changed, 113 insertions(+), 105 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ef237380/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/AbstractSftpSubsystemHelper.java
----------------------------------------------------------------------
diff --git a/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/AbstractSftpSubsystemHelper.java b/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/AbstractSftpSubsystemHelper.java
index 08213ee..f3946d4 100644
--- a/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/AbstractSftpSubsystemHelper.java
+++ b/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/AbstractSftpSubsystemHelper.java
@@ -239,8 +239,6 @@ public abstract class AbstractSftpSubsystemHelper
         return errorStatusDataHandler;
     }
 
-    protected abstract void process(Buffer buffer) throws IOException;
-
     /**
      * @param buffer   The {@link Buffer} holding the request
      * @param id       The request id
@@ -319,6 +317,117 @@ public abstract class AbstractSftpSubsystemHelper
         return available;
     }
 
+    /**
+     * Process an SFTP command.
+     * If the command throws an exception, the channel will be closed.
+     *
+     * @param buffer the buffer to process
+     * @throws IOException if anything wrong happens
+     */
+    protected void process(Buffer buffer) throws IOException {
+        int length = buffer.getInt();
+        int type = buffer.getUByte();
+        int id = buffer.getInt();
+        if (log.isDebugEnabled()) {
+            log.debug("process({})[length={}, type={}, id={}] processing",
+                    getServerSession(), length, SftpConstants.getCommandMessageName(type), id);
+        }
+        doProcess(buffer, length, type, id);
+    }
+
+    protected void doProcess(Buffer buffer, int length, int type, int id) throws IOException {
+        switch (type) {
+            case SftpConstants.SSH_FXP_INIT:
+                doInit(buffer, id);
+                break;
+            case SftpConstants.SSH_FXP_OPEN:
+                doOpen(buffer, id);
+                break;
+            case SftpConstants.SSH_FXP_CLOSE:
+                doClose(buffer, id);
+                break;
+            case SftpConstants.SSH_FXP_READ:
+                doRead(buffer, id);
+                break;
+            case SftpConstants.SSH_FXP_WRITE:
+                doWrite(buffer, id);
+                break;
+            case SftpConstants.SSH_FXP_LSTAT:
+                doLStat(buffer, id);
+                break;
+            case SftpConstants.SSH_FXP_FSTAT:
+                doFStat(buffer, id);
+                break;
+            case SftpConstants.SSH_FXP_SETSTAT:
+                doSetStat(buffer, id);
+                break;
+            case SftpConstants.SSH_FXP_FSETSTAT:
+                doFSetStat(buffer, id);
+                break;
+            case SftpConstants.SSH_FXP_OPENDIR:
+                doOpenDir(buffer, id);
+                break;
+            case SftpConstants.SSH_FXP_READDIR:
+                doReadDir(buffer, id);
+                break;
+            case SftpConstants.SSH_FXP_REMOVE:
+                doRemove(buffer, id);
+                break;
+            case SftpConstants.SSH_FXP_MKDIR:
+                doMakeDirectory(buffer, id);
+                break;
+            case SftpConstants.SSH_FXP_RMDIR:
+                doRemoveDirectory(buffer, id);
+                break;
+            case SftpConstants.SSH_FXP_REALPATH:
+                doRealPath(buffer, id);
+                break;
+            case SftpConstants.SSH_FXP_STAT:
+                doStat(buffer, id);
+                break;
+            case SftpConstants.SSH_FXP_RENAME:
+                doRename(buffer, id);
+                break;
+            case SftpConstants.SSH_FXP_READLINK:
+                doReadLink(buffer, id);
+                break;
+            case SftpConstants.SSH_FXP_SYMLINK:
+                doSymLink(buffer, id);
+                break;
+            case SftpConstants.SSH_FXP_LINK:
+                doLink(buffer, id);
+                break;
+            case SftpConstants.SSH_FXP_BLOCK:
+                doBlock(buffer, id);
+                break;
+            case SftpConstants.SSH_FXP_UNBLOCK:
+                doUnblock(buffer, id);
+                break;
+            case SftpConstants.SSH_FXP_EXTENDED:
+                doExtended(buffer, id);
+                break;
+            default:
+                doUnsupported(buffer, length, type, id);
+                break;
+        }
+    }
+
+    protected void doUnsupported(Buffer buffer, int length, int type, int id) throws IOException {
+        String name = SftpConstants.getCommandMessageName(type);
+        log.warn("process({})[length={}, type={}, id={}] unknown command",
+                getServerSession(), length, name, id);
+        sendStatus(BufferUtils.clear(buffer), id, SftpConstants.SSH_FX_OP_UNSUPPORTED, "Command " + name + " is unsupported or not implemented");
+    }
+
+    protected abstract void doInit(Buffer buffer, int id) throws IOException;
+
+    protected void doVersionSelect(Buffer buffer, int id) throws IOException {
+        String proposed = buffer.getString();
+        doVersionSelect(buffer, id, proposed);
+    }
+
+    protected abstract void doVersionSelect(Buffer buffer, int id, String proposed) throws IOException;
+
     protected void doOpen(Buffer buffer, int id) throws IOException {
         String path = buffer.getString();
         /*

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ef237380/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
----------------------------------------------------------------------
diff --git a/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java b/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
index e07ee83..8abfba8 100644
--- a/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
+++ b/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
@@ -298,113 +298,13 @@ public class SftpSubsystem
         }
     }
 
-    /**
-     * Process an SFTP command.
-     * If the command throws an exception, the channel will be closed.
-     *
-     * @param buffer the buffer to process
-     * @throws IOException if anything wrong happens
-     */
-    @Override
-    protected void process(Buffer buffer) throws IOException {
-        int length = buffer.getInt();
-        int type = buffer.getUByte();
-        int id = buffer.getInt();
-        if (log.isDebugEnabled()) {
-            log.debug("process({})[length={}, type={}, id={}] processing",
-                      getServerSession(), length, SftpConstants.getCommandMessageName(type), id);
-        }
-        doProcess(buffer, length, type, id);
-    }
-
     protected void doProcess(Buffer buffer, int length, int type, int id) throws IOException {
-        switch (type) {
-            case SftpConstants.SSH_FXP_INIT:
-                doInit(buffer, id);
-                break;
-            case SftpConstants.SSH_FXP_OPEN:
-                doOpen(buffer, id);
-                break;
-            case SftpConstants.SSH_FXP_CLOSE:
-                doClose(buffer, id);
-                break;
-            case SftpConstants.SSH_FXP_READ:
-                doRead(buffer, id);
-                break;
-            case SftpConstants.SSH_FXP_WRITE:
-                doWrite(buffer, id);
-                break;
-            case SftpConstants.SSH_FXP_LSTAT:
-                doLStat(buffer, id);
-                break;
-            case SftpConstants.SSH_FXP_FSTAT:
-                doFStat(buffer, id);
-                break;
-            case SftpConstants.SSH_FXP_SETSTAT:
-                doSetStat(buffer, id);
-                break;
-            case SftpConstants.SSH_FXP_FSETSTAT:
-                doFSetStat(buffer, id);
-                break;
-            case SftpConstants.SSH_FXP_OPENDIR:
-                doOpenDir(buffer, id);
-                break;
-            case SftpConstants.SSH_FXP_READDIR:
-                doReadDir(buffer, id);
-                break;
-            case SftpConstants.SSH_FXP_REMOVE:
-                doRemove(buffer, id);
-                break;
-            case SftpConstants.SSH_FXP_MKDIR:
-                doMakeDirectory(buffer, id);
-                break;
-            case SftpConstants.SSH_FXP_RMDIR:
-                doRemoveDirectory(buffer, id);
-                break;
-            case SftpConstants.SSH_FXP_REALPATH:
-                doRealPath(buffer, id);
-                break;
-            case SftpConstants.SSH_FXP_STAT:
-                doStat(buffer, id);
-                break;
-            case SftpConstants.SSH_FXP_RENAME:
-                doRename(buffer, id);
-                break;
-            case SftpConstants.SSH_FXP_READLINK:
-                doReadLink(buffer, id);
-                break;
-            case SftpConstants.SSH_FXP_SYMLINK:
-                doSymLink(buffer, id);
-                break;
-            case SftpConstants.SSH_FXP_LINK:
-                doLink(buffer, id);
-                break;
-            case SftpConstants.SSH_FXP_BLOCK:
-                doBlock(buffer, id);
-                break;
-            case SftpConstants.SSH_FXP_UNBLOCK:
-                doUnblock(buffer, id);
-                break;
-            case SftpConstants.SSH_FXP_EXTENDED:
-                doExtended(buffer, id);
-                break;
-            default:
-                doUnsupported(buffer, length, type, id);
-                break;
-        }
-
+        super.doProcess(buffer, length, type, id);
         if (type != SftpConstants.SSH_FXP_INIT) {
             requestsCount++;
         }
     }
 
-    protected void doUnsupported(Buffer buffer, int length, int type, int id) throws IOException {
-        String name = SftpConstants.getCommandMessageName(type);
-        log.warn("process({})[length={}, type={}, id={}] unknown command",
-                 getServerSession(), length, name, id);
-        sendStatus(BufferUtils.clear(buffer), id, SftpConstants.SSH_FX_OP_UNSUPPORTED, "Command " + name + " is unsupported or not implemented");
-    }
-
     @Override
     protected void executeExtendedCommand(Buffer buffer, int id, String extension) throws IOException {
         switch (extension) {
@@ -606,8 +506,7 @@ public class SftpSubsystem
         return doMD5Hash(id, path, startOffset, effectiveLength, quickCheckHash);
     }
 
-    protected void doVersionSelect(Buffer buffer, int id) throws IOException {
-        String proposed = buffer.getString();
+    protected void doVersionSelect(Buffer buffer, int id, String proposed) throws IOException {
         ServerSession session = getServerSession();
         /*
          * The 'version-select' MUST be the first request from the client to the


[3/5] mina-sshd git commit: [SSHD-812] Move executeExtendedCommand to AbstractSftpSubsystemHelper

Posted by gn...@apache.org.
[SSHD-812] Move executeExtendedCommand to AbstractSftpSubsystemHelper


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

Branch: refs/heads/master
Commit: bb378250bdddb2e0a2cf30c5942394c70dc40783
Parents: ef23738
Author: Guillaume Nodet <gn...@apache.org>
Authored: Tue Apr 17 09:39:33 2018 +0200
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Thu Apr 19 17:07:34 2018 +0200

----------------------------------------------------------------------
 .../sftp/AbstractSftpSubsystemHelper.java       | 44 +++++++++++++++++++-
 .../server/subsystem/sftp/SftpSubsystem.java    | 43 -------------------
 2 files changed, 43 insertions(+), 44 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/bb378250/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/AbstractSftpSubsystemHelper.java
----------------------------------------------------------------------
diff --git a/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/AbstractSftpSubsystemHelper.java b/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/AbstractSftpSubsystemHelper.java
index f3946d4..6814ef5 100644
--- a/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/AbstractSftpSubsystemHelper.java
+++ b/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/AbstractSftpSubsystemHelper.java
@@ -1563,7 +1563,49 @@ public abstract class AbstractSftpSubsystemHelper
      * @param extension The extension name
      * @throws IOException If failed to execute the extension
      */
-    protected abstract void executeExtendedCommand(Buffer buffer, int id, String extension) throws IOException;
+    protected void executeExtendedCommand(Buffer buffer, int id, String extension) throws IOException {
+        switch (extension) {
+            case SftpConstants.EXT_TEXT_SEEK:
+                doTextSeek(buffer, id);
+                break;
+            case SftpConstants.EXT_VERSION_SELECT:
+                doVersionSelect(buffer, id);
+                break;
+            case SftpConstants.EXT_COPY_FILE:
+                doCopyFile(buffer, id);
+                break;
+            case SftpConstants.EXT_COPY_DATA:
+                doCopyData(buffer, id);
+                break;
+            case SftpConstants.EXT_MD5_HASH:
+            case SftpConstants.EXT_MD5_HASH_HANDLE:
+                doMD5Hash(buffer, id, extension);
+                break;
+            case SftpConstants.EXT_CHECK_FILE_HANDLE:
+            case SftpConstants.EXT_CHECK_FILE_NAME:
+                doCheckFileHash(buffer, id, extension);
+                break;
+            case FsyncExtensionParser.NAME:
+                doOpenSSHFsync(buffer, id);
+                break;
+            case SftpConstants.EXT_SPACE_AVAILABLE:
+                doSpaceAvailable(buffer, id);
+                break;
+            case HardLinkExtensionParser.NAME:
+                doOpenSSHHardLink(buffer, id);
+                break;
+            default:
+                doUnsupportedExtension(buffer, id, extension);
+                break;
+        }
+    }
+
+    protected void doUnsupportedExtension(Buffer buffer, int id, String extension) throws IOException {
+        if (log.isDebugEnabled()) {
+            log.debug("executeExtendedCommand({}) received unsupported SSH_FXP_EXTENDED({})", getServerSession(), extension);
+        }
+        sendStatus(buffer, id, SftpConstants.SSH_FX_OP_UNSUPPORTED, "Command SSH_FXP_EXTENDED(" + extension + ") is unsupported or not implemented");
+    }
 
     protected void appendExtensions(Buffer buffer, String supportedVersions) {
         appendVersionsExtension(buffer, supportedVersions);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/bb378250/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
----------------------------------------------------------------------
diff --git a/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java b/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
index 8abfba8..8979909 100644
--- a/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
+++ b/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
@@ -51,8 +51,6 @@ import org.apache.sshd.common.file.FileSystemAware;
 import org.apache.sshd.common.random.Random;
 import org.apache.sshd.common.subsystem.sftp.SftpConstants;
 import org.apache.sshd.common.subsystem.sftp.SftpHelper;
-import org.apache.sshd.common.subsystem.sftp.extensions.openssh.FsyncExtensionParser;
-import org.apache.sshd.common.subsystem.sftp.extensions.openssh.HardLinkExtensionParser;
 import org.apache.sshd.common.util.GenericUtils;
 import org.apache.sshd.common.util.ValidateUtils;
 import org.apache.sshd.common.util.buffer.Buffer;
@@ -306,47 +304,6 @@ public class SftpSubsystem
     }
 
     @Override
-    protected void executeExtendedCommand(Buffer buffer, int id, String extension) throws IOException {
-        switch (extension) {
-            case SftpConstants.EXT_TEXT_SEEK:
-                doTextSeek(buffer, id);
-                break;
-            case SftpConstants.EXT_VERSION_SELECT:
-                doVersionSelect(buffer, id);
-                break;
-            case SftpConstants.EXT_COPY_FILE:
-                doCopyFile(buffer, id);
-                break;
-            case SftpConstants.EXT_COPY_DATA:
-                doCopyData(buffer, id);
-                break;
-            case SftpConstants.EXT_MD5_HASH:
-            case SftpConstants.EXT_MD5_HASH_HANDLE:
-                doMD5Hash(buffer, id, extension);
-                break;
-            case SftpConstants.EXT_CHECK_FILE_HANDLE:
-            case SftpConstants.EXT_CHECK_FILE_NAME:
-                doCheckFileHash(buffer, id, extension);
-                break;
-            case FsyncExtensionParser.NAME:
-                doOpenSSHFsync(buffer, id);
-                break;
-            case SftpConstants.EXT_SPACE_AVAILABLE:
-                doSpaceAvailable(buffer, id);
-                break;
-            case HardLinkExtensionParser.NAME:
-                doOpenSSHHardLink(buffer, id);
-                break;
-            default:
-                if (log.isDebugEnabled()) {
-                    log.debug("executeExtendedCommand({}) received unsupported SSH_FXP_EXTENDED({})", getServerSession(), extension);
-                }
-                sendStatus(BufferUtils.clear(buffer), id, SftpConstants.SSH_FX_OP_UNSUPPORTED, "Command SSH_FXP_EXTENDED(" + extension + ") is unsupported or not implemented");
-                break;
-        }
-    }
-
-    @Override
     protected void createLink(int id, String existingPath, String linkPath, boolean symLink) throws IOException {
         Path link = resolveFile(linkPath);
         Path existing = fileSystem.getPath(existingPath);


[4/5] mina-sshd git commit: [SSHD-812] Introduce a prepareReply method

Posted by gn...@apache.org.
[SSHD-812] Introduce a prepareReply method


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

Branch: refs/heads/master
Commit: 6bed356ad40452a385ef8df5c263cd388d870981
Parents: bb37825
Author: Guillaume Nodet <gn...@apache.org>
Authored: Thu Apr 19 10:39:26 2018 +0200
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Thu Apr 19 17:07:38 2018 +0200

----------------------------------------------------------------------
 .../sftp/AbstractSftpSubsystemHelper.java       | 118 ++++++++++---------
 .../server/subsystem/sftp/SftpSubsystem.java    |  22 ++--
 .../openssh/helpers/OpenSSHExtensionsTest.java  |   2 +-
 3 files changed, 75 insertions(+), 67 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6bed356a/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/AbstractSftpSubsystemHelper.java
----------------------------------------------------------------------
diff --git a/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/AbstractSftpSubsystemHelper.java b/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/AbstractSftpSubsystemHelper.java
index 6814ef5..bd3335c 100644
--- a/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/AbstractSftpSubsystemHelper.java
+++ b/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/AbstractSftpSubsystemHelper.java
@@ -310,7 +310,7 @@ public abstract class AbstractSftpSubsystemHelper
         }
 
         if ((proposed < low) || (proposed > hig)) {
-            sendStatus(BufferUtils.clear(buffer), id, failureOpcode, "Proposed version (" + proposed + ") not in supported range: " + available);
+            sendStatus(prepareReply(buffer), id, failureOpcode, "Proposed version (" + proposed + ") not in supported range: " + available);
             return null;
         }
 
@@ -416,7 +416,7 @@ public abstract class AbstractSftpSubsystemHelper
         String name = SftpConstants.getCommandMessageName(type);
         log.warn("process({})[length={}, type={}, id={}] unknown command",
                 getServerSession(), length, name, id);
-        sendStatus(BufferUtils.clear(buffer), id, SftpConstants.SSH_FX_OP_UNSUPPORTED, "Command " + name + " is unsupported or not implemented");
+        sendStatus(prepareReply(buffer), id, SftpConstants.SSH_FX_OP_UNSUPPORTED, "Command " + name + " is unsupported or not implemented");
     }
 
     protected abstract void doInit(Buffer buffer, int id) throws IOException;
@@ -488,11 +488,11 @@ public abstract class AbstractSftpSubsystemHelper
         try {
             handle = doOpen(id, path, pflags, access, attrs);
         } catch (IOException | RuntimeException e) {
-            sendStatus(BufferUtils.clear(buffer), id, e, SftpConstants.SSH_FXP_OPEN, path);
+            sendStatus(prepareReply(buffer), id, e, SftpConstants.SSH_FXP_OPEN, path);
             return;
         }
 
-        sendHandle(BufferUtils.clear(buffer), id, handle);
+        sendHandle(prepareReply(buffer), id, handle);
     }
 
     /**
@@ -511,11 +511,11 @@ public abstract class AbstractSftpSubsystemHelper
         try {
             doClose(id, handle);
         } catch (IOException | RuntimeException e) {
-            sendStatus(BufferUtils.clear(buffer), id, e, SftpConstants.SSH_FXP_CLOSE, handle);
+            sendStatus(prepareReply(buffer), id, e, SftpConstants.SSH_FXP_CLOSE, handle);
             return;
         }
 
-        sendStatus(BufferUtils.clear(buffer), id, SftpConstants.SSH_FX_OK, "", "");
+        sendStatus(prepareReply(buffer), id, SftpConstants.SSH_FX_OK, "", "");
     }
 
     protected abstract void doClose(int id, String handle) throws IOException;
@@ -535,7 +535,7 @@ public abstract class AbstractSftpSubsystemHelper
         try {
             ValidateUtils.checkTrue(readLen >= 0, "Illegal requested read length: %d", readLen);
 
-            buffer.clear();
+            buffer = prepareReply(buffer);
             buffer.ensureCapacity(readLen + Long.SIZE /* the header */, IntUnaryOperator.identity());
 
             buffer.putByte((byte) SftpConstants.SSH_FXP_DATA);
@@ -551,7 +551,7 @@ public abstract class AbstractSftpSubsystemHelper
             buffer.wpos(startPos + len);
             BufferUtils.updateLengthPlaceholder(buffer, lenPos, len);
         } catch (IOException | RuntimeException e) {
-            sendStatus(BufferUtils.clear(buffer), id, e, SftpConstants.SSH_FXP_READ, handle, offset, requestedLength);
+            sendStatus(prepareReply(buffer), id, e, SftpConstants.SSH_FXP_READ, handle, offset, requestedLength);
             return;
         }
 
@@ -567,11 +567,11 @@ public abstract class AbstractSftpSubsystemHelper
         try {
             doWrite(id, handle, offset, length, buffer.array(), buffer.rpos(), buffer.available());
         } catch (IOException | RuntimeException e) {
-            sendStatus(BufferUtils.clear(buffer), id, e, SftpConstants.SSH_FXP_WRITE, handle, offset, length);
+            sendStatus(prepareReply(buffer), id, e, SftpConstants.SSH_FXP_WRITE, handle, offset, length);
             return;
         }
 
-        sendStatus(BufferUtils.clear(buffer), id, SftpConstants.SSH_FX_OK, "");
+        sendStatus(prepareReply(buffer), id, SftpConstants.SSH_FX_OK, "");
     }
 
     protected abstract void doWrite(int id, String handle, long offset, int length, byte[] data, int doff, int remaining) throws IOException;
@@ -588,11 +588,11 @@ public abstract class AbstractSftpSubsystemHelper
         try {
             attrs = doLStat(id, path, flags);
         } catch (IOException | RuntimeException e) {
-            sendStatus(BufferUtils.clear(buffer), id, e, SftpConstants.SSH_FXP_LSTAT, path, flags);
+            sendStatus(prepareReply(buffer), id, e, SftpConstants.SSH_FXP_LSTAT, path, flags);
             return;
         }
 
-        sendAttrs(BufferUtils.clear(buffer), id, attrs);
+        sendAttrs(prepareReply(buffer), id, attrs);
     }
 
     protected Map<String, Object> doLStat(int id, String path, int flags) throws IOException {
@@ -615,11 +615,11 @@ public abstract class AbstractSftpSubsystemHelper
         try {
             doSetStat(id, path, attrs);
         } catch (IOException | RuntimeException e) {
-            sendStatus(BufferUtils.clear(buffer), id, e, SftpConstants.SSH_FXP_SETSTAT, path);
+            sendStatus(prepareReply(buffer), id, e, SftpConstants.SSH_FXP_SETSTAT, path);
             return;
         }
 
-        sendStatus(BufferUtils.clear(buffer), id, SftpConstants.SSH_FX_OK, "");
+        sendStatus(prepareReply(buffer), id, SftpConstants.SSH_FX_OK, "");
     }
 
     protected void doSetStat(int id, String path, Map<String, ?> attrs) throws IOException {
@@ -643,11 +643,11 @@ public abstract class AbstractSftpSubsystemHelper
         try {
             attrs = doFStat(id, handle, flags);
         } catch (IOException | RuntimeException e) {
-            sendStatus(BufferUtils.clear(buffer), id, e, SftpConstants.SSH_FXP_FSTAT, handle, flags);
+            sendStatus(prepareReply(buffer), id, e, SftpConstants.SSH_FXP_FSTAT, handle, flags);
             return;
         }
 
-        sendAttrs(BufferUtils.clear(buffer), id, attrs);
+        sendAttrs(prepareReply(buffer), id, attrs);
     }
 
     protected abstract Map<String, Object> doFStat(int id, String handle, int flags) throws IOException;
@@ -658,11 +658,11 @@ public abstract class AbstractSftpSubsystemHelper
         try {
             doFSetStat(id, handle, attrs);
         } catch (IOException | RuntimeException e) {
-            sendStatus(BufferUtils.clear(buffer), id, e, SftpConstants.SSH_FXP_FSETSTAT, handle, attrs);
+            sendStatus(prepareReply(buffer), id, e, SftpConstants.SSH_FXP_FSETSTAT, handle, attrs);
             return;
         }
 
-        sendStatus(BufferUtils.clear(buffer), id, SftpConstants.SSH_FX_OK, "");
+        sendStatus(prepareReply(buffer), id, SftpConstants.SSH_FX_OK, "");
     }
 
     protected abstract void doFSetStat(int id, String handle, Map<String, ?> attrs) throws IOException;
@@ -682,11 +682,11 @@ public abstract class AbstractSftpSubsystemHelper
                 getPathResolutionLinkOption(SftpConstants.SSH_FXP_OPENDIR, "", p);
             handle = doOpenDir(id, path, p, options);
         } catch (IOException | RuntimeException e) {
-            sendStatus(BufferUtils.clear(buffer), id, e, SftpConstants.SSH_FXP_OPENDIR, path);
+            sendStatus(prepareReply(buffer), id, e, SftpConstants.SSH_FXP_OPENDIR, path);
             return;
         }
 
-        sendHandle(BufferUtils.clear(buffer), id, handle);
+        sendHandle(prepareReply(buffer), id, handle);
     }
 
     protected abstract String doOpenDir(int id, String path, Path p, LinkOption... options) throws IOException;
@@ -706,11 +706,11 @@ public abstract class AbstractSftpSubsystemHelper
 
             doLink(id, targetPath, linkPath, symLink);
         } catch (IOException | RuntimeException e) {
-            sendStatus(BufferUtils.clear(buffer), id, e, SftpConstants.SSH_FXP_LINK, targetPath, linkPath, symLink);
+            sendStatus(prepareReply(buffer), id, e, SftpConstants.SSH_FXP_LINK, targetPath, linkPath, symLink);
             return;
         }
 
-        sendStatus(BufferUtils.clear(buffer), id, SftpConstants.SSH_FX_OK, "");
+        sendStatus(prepareReply(buffer), id, SftpConstants.SSH_FX_OK, "");
     }
 
     protected void doLink(int id, String targetPath, String linkPath, boolean symLink) throws IOException {
@@ -727,11 +727,11 @@ public abstract class AbstractSftpSubsystemHelper
             }
             doSymLink(id, targetPath, linkPath);
         } catch (IOException | RuntimeException e) {
-            sendStatus(BufferUtils.clear(buffer), id, e, SftpConstants.SSH_FXP_SYMLINK, targetPath, linkPath);
+            sendStatus(prepareReply(buffer), id, e, SftpConstants.SSH_FXP_SYMLINK, targetPath, linkPath);
             return;
         }
 
-        sendStatus(BufferUtils.clear(buffer), id, SftpConstants.SSH_FX_OK, "");
+        sendStatus(prepareReply(buffer), id, SftpConstants.SSH_FX_OK, "");
     }
 
     protected void doSymLink(int id, String targetPath, String linkPath) throws IOException {
@@ -748,11 +748,11 @@ public abstract class AbstractSftpSubsystemHelper
         try {
             doOpenSSHHardLink(id, srcFile, dstFile);
         } catch (IOException | RuntimeException e) {
-            sendStatus(BufferUtils.clear(buffer), id, e, SftpConstants.SSH_FXP_EXTENDED, HardLinkExtensionParser.NAME, srcFile, dstFile);
+            sendStatus(prepareReply(buffer), id, e, SftpConstants.SSH_FXP_EXTENDED, HardLinkExtensionParser.NAME, srcFile, dstFile);
             return;
         }
 
-        sendStatus(BufferUtils.clear(buffer), id, SftpConstants.SSH_FX_OK, "");
+        sendStatus(prepareReply(buffer), id, SftpConstants.SSH_FX_OK, "");
     }
 
     protected void doOpenSSHHardLink(int id, String srcFile, String dstFile) throws IOException {
@@ -770,11 +770,11 @@ public abstract class AbstractSftpSubsystemHelper
         try {
             info = doSpaceAvailable(id, path);
         } catch (IOException | RuntimeException e) {
-            sendStatus(BufferUtils.clear(buffer), id, e, SftpConstants.SSH_FXP_EXTENDED, SftpConstants.EXT_SPACE_AVAILABLE, path);
+            sendStatus(prepareReply(buffer), id, e, SftpConstants.SSH_FXP_EXTENDED, SftpConstants.EXT_SPACE_AVAILABLE, path);
             return;
         }
 
-        buffer.clear();
+        buffer = prepareReply(buffer);
         buffer.putByte((byte) SftpConstants.SSH_FXP_EXTENDED_REPLY);
         buffer.putInt(id);
         SpaceAvailableExtensionInfo.encode(buffer, info);
@@ -803,11 +803,11 @@ public abstract class AbstractSftpSubsystemHelper
             // TODO : implement text-seek - see https://tools.ietf.org/html/draft-ietf-secsh-filexfer-03#section-6.3
             doTextSeek(id, handle, line);
         } catch (IOException | RuntimeException e) {
-            sendStatus(BufferUtils.clear(buffer), id, e, SftpConstants.SSH_FXP_EXTENDED, SftpConstants.EXT_TEXT_SEEK, handle, line);
+            sendStatus(prepareReply(buffer), id, e, SftpConstants.SSH_FXP_EXTENDED, SftpConstants.EXT_TEXT_SEEK, handle, line);
             return;
         }
 
-        sendStatus(BufferUtils.clear(buffer), id, SftpConstants.SSH_FX_OK, "");
+        sendStatus(prepareReply(buffer), id, SftpConstants.SSH_FX_OK, "");
     }
 
     protected abstract void doTextSeek(int id, String handle, long line) throws IOException;
@@ -818,11 +818,11 @@ public abstract class AbstractSftpSubsystemHelper
         try {
             doOpenSSHFsync(id, handle);
         } catch (IOException | RuntimeException e) {
-            sendStatus(BufferUtils.clear(buffer), id, e, SftpConstants.SSH_FXP_EXTENDED, FsyncExtensionParser.NAME, handle);
+            sendStatus(prepareReply(buffer), id, e, SftpConstants.SSH_FXP_EXTENDED, FsyncExtensionParser.NAME, handle);
             return;
         }
 
-        sendStatus(BufferUtils.clear(buffer), id, SftpConstants.SSH_FX_OK, "");
+        sendStatus(prepareReply(buffer), id, SftpConstants.SSH_FX_OK, "");
     }
 
     protected abstract void doOpenSSHFsync(int id, String handle) throws IOException;
@@ -835,13 +835,13 @@ public abstract class AbstractSftpSubsystemHelper
         long length = buffer.getLong();
         int blockSize = buffer.getInt();
         try {
-            buffer.clear();
+            buffer = prepareReply(buffer);
             buffer.putByte((byte) SftpConstants.SSH_FXP_EXTENDED_REPLY);
             buffer.putInt(id);
             buffer.putString(SftpConstants.EXT_CHECK_FILE);
             doCheckFileHash(id, targetType, target, Arrays.asList(algos), startOffset, length, blockSize, buffer);
         } catch (Exception e) {
-            sendStatus(BufferUtils.clear(buffer), id, e,
+            sendStatus(prepareReply(buffer), id, e,
                 SftpConstants.SSH_FXP_EXTENDED, targetType, target, algList, startOffset, length, blockSize);
             return;
         }
@@ -953,12 +953,12 @@ public abstract class AbstractSftpSubsystemHelper
             }
 
         } catch (Exception e) {
-            sendStatus(BufferUtils.clear(buffer), id, e,
+            sendStatus(prepareReply(buffer), id, e,
                 SftpConstants.SSH_FXP_EXTENDED, targetType, target, startOffset, length, quickCheckHash);
             return;
         }
 
-        buffer.clear();
+        buffer = prepareReply(buffer);
         buffer.putByte((byte) SftpConstants.SSH_FXP_EXTENDED_REPLY);
         buffer.putInt(id);
         buffer.putString(targetType);
@@ -1085,11 +1085,11 @@ public abstract class AbstractSftpSubsystemHelper
             }
             l = doReadLink(id, path);
         } catch (IOException | RuntimeException e) {
-            sendStatus(BufferUtils.clear(buffer), id, e, SftpConstants.SSH_FXP_READLINK, path);
+            sendStatus(prepareReply(buffer), id, e, SftpConstants.SSH_FXP_READLINK, path);
             return;
         }
 
-        sendLink(BufferUtils.clear(buffer), id, l);
+        sendLink(prepareReply(buffer), id, l);
     }
 
     protected String doReadLink(int id, String path) throws IOException {
@@ -1113,11 +1113,11 @@ public abstract class AbstractSftpSubsystemHelper
         try {
             doRename(id, oldPath, newPath, flags);
         } catch (IOException | RuntimeException e) {
-            sendStatus(BufferUtils.clear(buffer), id, e, SftpConstants.SSH_FXP_RENAME, oldPath, newPath, flags);
+            sendStatus(prepareReply(buffer), id, e, SftpConstants.SSH_FXP_RENAME, oldPath, newPath, flags);
             return;
         }
 
-        sendStatus(BufferUtils.clear(buffer), id, SftpConstants.SSH_FX_OK, "");
+        sendStatus(prepareReply(buffer), id, SftpConstants.SSH_FX_OK, "");
     }
 
     protected void doRename(int id, String oldPath, String newPath, int flags) throws IOException {
@@ -1166,13 +1166,13 @@ public abstract class AbstractSftpSubsystemHelper
         try {
             doCopyData(id, readHandle, readOffset, readLength, writeHandle, writeOffset);
         } catch (IOException | RuntimeException e) {
-            sendStatus(BufferUtils.clear(buffer), id, e,
+            sendStatus(prepareReply(buffer), id, e,
                 SftpConstants.SSH_FXP_EXTENDED, SftpConstants.EXT_COPY_DATA,
                 readHandle, readOffset, readLength, writeHandle, writeOffset);
             return;
         }
 
-        sendStatus(BufferUtils.clear(buffer), id, SftpConstants.SSH_FX_OK, "");
+        sendStatus(prepareReply(buffer), id, SftpConstants.SSH_FX_OK, "");
     }
 
     protected abstract void doCopyData(int id, String readHandle, long readOffset, long readLength, String writeHandle, long writeOffset) throws IOException;
@@ -1186,12 +1186,12 @@ public abstract class AbstractSftpSubsystemHelper
         try {
             doCopyFile(id, srcFile, dstFile, overwriteDestination);
         } catch (IOException | RuntimeException e) {
-            sendStatus(BufferUtils.clear(buffer), id, e,
+            sendStatus(prepareReply(buffer), id, e,
                 SftpConstants.SSH_FXP_EXTENDED, SftpConstants.EXT_COPY_FILE, srcFile, dstFile, overwriteDestination);
             return;
         }
 
-        sendStatus(BufferUtils.clear(buffer), id, SftpConstants.SSH_FX_OK, "");
+        sendStatus(prepareReply(buffer), id, SftpConstants.SSH_FX_OK, "");
     }
 
     protected void doCopyFile(int id, String srcFile, String dstFile, boolean overwriteDestination) throws IOException {
@@ -1222,11 +1222,11 @@ public abstract class AbstractSftpSubsystemHelper
         try {
             doBlock(id, handle, offset, length, mask);
         } catch (IOException | RuntimeException e) {
-            sendStatus(BufferUtils.clear(buffer), id, e, SftpConstants.SSH_FXP_BLOCK, handle, offset, length, mask);
+            sendStatus(prepareReply(buffer), id, e, SftpConstants.SSH_FXP_BLOCK, handle, offset, length, mask);
             return;
         }
 
-        sendStatus(BufferUtils.clear(buffer), id, SftpConstants.SSH_FX_OK, "");
+        sendStatus(prepareReply(buffer), id, SftpConstants.SSH_FX_OK, "");
     }
 
     protected abstract void doBlock(int id, String handle, long offset, long length, int mask) throws IOException;
@@ -1238,11 +1238,11 @@ public abstract class AbstractSftpSubsystemHelper
         try {
             doUnblock(id, handle, offset, length);
         } catch (IOException | RuntimeException e) {
-            sendStatus(BufferUtils.clear(buffer), id, e, SftpConstants.SSH_FXP_UNBLOCK, handle, offset, length);
+            sendStatus(prepareReply(buffer), id, e, SftpConstants.SSH_FXP_UNBLOCK, handle, offset, length);
             return;
         }
 
-        sendStatus(BufferUtils.clear(buffer), id, SftpConstants.SSH_FX_OK, "");
+        sendStatus(prepareReply(buffer), id, SftpConstants.SSH_FX_OK, "");
     }
 
     protected abstract void doUnblock(int id, String handle, long offset, long length) throws IOException;
@@ -1259,11 +1259,11 @@ public abstract class AbstractSftpSubsystemHelper
         try {
             attrs = doStat(id, path, flags);
         } catch (IOException | RuntimeException e) {
-            sendStatus(BufferUtils.clear(buffer), id, e, SftpConstants.SSH_FXP_STAT, path, flags);
+            sendStatus(prepareReply(buffer), id, e, SftpConstants.SSH_FXP_STAT, path, flags);
             return;
         }
 
-        sendAttrs(BufferUtils.clear(buffer), id, attrs);
+        sendAttrs(prepareReply(buffer), id, attrs);
     }
 
     protected Map<String, Object> doStat(int id, String path, int flags) throws IOException {
@@ -1376,11 +1376,11 @@ public abstract class AbstractSftpSubsystemHelper
                 }
             }
         } catch (IOException | RuntimeException e) {
-            sendStatus(BufferUtils.clear(buffer), id, e, SftpConstants.SSH_FXP_REALPATH, path);
+            sendStatus(prepareReply(buffer), id, e, SftpConstants.SSH_FXP_REALPATH, path);
             return;
         }
 
-        sendPath(BufferUtils.clear(buffer), id, result.getKey(), attrs);
+        sendPath(prepareReply(buffer), id, result.getKey(), attrs);
     }
 
     protected SimpleImmutableEntry<Path, Boolean> doRealPathV6(
@@ -1431,11 +1431,11 @@ public abstract class AbstractSftpSubsystemHelper
         try {
             doRemoveDirectory(id, path, IoUtils.getLinkOptions(false));
         } catch (IOException | RuntimeException e) {
-            sendStatus(BufferUtils.clear(buffer), id, e, SftpConstants.SSH_FXP_RMDIR, path);
+            sendStatus(prepareReply(buffer), id, e, SftpConstants.SSH_FXP_RMDIR, path);
             return;
         }
 
-        sendStatus(BufferUtils.clear(buffer), id, SftpConstants.SSH_FX_OK, "");
+        sendStatus(prepareReply(buffer), id, SftpConstants.SSH_FX_OK, "");
     }
 
     protected void doRemoveDirectory(int id, String path, LinkOption... options) throws IOException {
@@ -1477,11 +1477,11 @@ public abstract class AbstractSftpSubsystemHelper
         try {
             doMakeDirectory(id, path, attrs, IoUtils.getLinkOptions(false));
         } catch (IOException | RuntimeException e) {
-            sendStatus(BufferUtils.clear(buffer), id, e, SftpConstants.SSH_FXP_MKDIR, path, attrs);
+            sendStatus(prepareReply(buffer), id, e, SftpConstants.SSH_FXP_MKDIR, path, attrs);
             return;
         }
 
-        sendStatus(BufferUtils.clear(buffer), id, SftpConstants.SSH_FX_OK, "");
+        sendStatus(prepareReply(buffer), id, SftpConstants.SSH_FX_OK, "");
     }
 
     protected void doMakeDirectory(int id, String path, Map<String, ?> attrs, LinkOption... options) throws IOException {
@@ -1526,11 +1526,11 @@ public abstract class AbstractSftpSubsystemHelper
              */
             doRemove(id, path, IoUtils.getLinkOptions(false));
         } catch (IOException | RuntimeException e) {
-            sendStatus(BufferUtils.clear(buffer), id, e, SftpConstants.SSH_FXP_REMOVE, path);
+            sendStatus(prepareReply(buffer), id, e, SftpConstants.SSH_FXP_REMOVE, path);
             return;
         }
 
-        sendStatus(BufferUtils.clear(buffer), id, SftpConstants.SSH_FX_OK, "");
+        sendStatus(prepareReply(buffer), id, SftpConstants.SSH_FX_OK, "");
     }
 
     protected void doRemove(int id, String path, LinkOption... options) throws IOException {
@@ -2696,6 +2696,8 @@ public abstract class AbstractSftpSubsystemHelper
         send(buffer);
     }
 
+    protected abstract Buffer prepareReply(Buffer buffer);
+
     protected abstract void send(Buffer buffer) throws IOException;
 
     protected Path resolveNormalizedLocation(String remotePath) throws IOException, InvalidPathException {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6bed356a/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
----------------------------------------------------------------------
diff --git a/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java b/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
index 8979909..ab1794e 100644
--- a/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
+++ b/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
@@ -471,7 +471,7 @@ public class SftpSubsystem
          * channel.
          */
         if (requestsCount > 0L) {
-            sendStatus(BufferUtils.clear(buffer), id,
+            sendStatus(prepareReply(buffer), id,
                        SftpConstants.SSH_FX_FAILURE,
                        "Version selection not the 1st request for proposal = " + proposed);
             session.close(true);
@@ -488,9 +488,9 @@ public class SftpSubsystem
         }
         if (result) {
             version = Integer.parseInt(proposed);
-            sendStatus(BufferUtils.clear(buffer), id, SftpConstants.SSH_FX_OK, "");
+            sendStatus(prepareReply(buffer), id, SftpConstants.SSH_FX_OK, "");
         } else {
-            sendStatus(BufferUtils.clear(buffer), id, SftpConstants.SSH_FX_FAILURE, "Unsupported version " + proposed);
+            sendStatus(prepareReply(buffer), id, SftpConstants.SSH_FX_FAILURE, "Unsupported version " + proposed);
             session.close(true);
         }
     }
@@ -625,7 +625,7 @@ public class SftpSubsystem
         try {
             DirectoryHandle dh = validateHandle(handle, h, DirectoryHandle.class);
             if (dh.isDone()) {
-                sendStatus(BufferUtils.clear(buffer), id, SftpConstants.SSH_FX_EOF, "Directory reading is done");
+                sendStatus(prepareReply(buffer), id, SftpConstants.SSH_FX_EOF, "Directory reading is done");
                 return;
             }
 
@@ -650,7 +650,7 @@ public class SftpSubsystem
                 // Send only a few files at a time to not create packets of a too
                 // large size or have a timeout to occur.
 
-                reply = BufferUtils.clear(buffer);
+                reply = prepareReply(buffer);
                 reply.putByte((byte) SftpConstants.SSH_FXP_NAME);
                 reply.putInt(id);
 
@@ -673,13 +673,13 @@ public class SftpSubsystem
             } else {
                 // empty directory
                 dh.markDone();
-                sendStatus(BufferUtils.clear(buffer), id, SftpConstants.SSH_FX_EOF, "Empty directory");
+                sendStatus(prepareReply(buffer), id, SftpConstants.SSH_FX_EOF, "Empty directory");
                 return;
             }
 
             Objects.requireNonNull(reply, "No reply buffer created");
         } catch (IOException | RuntimeException e) {
-            sendStatus(BufferUtils.clear(buffer), id, e, SftpConstants.SSH_FXP_READDIR, handle);
+            sendStatus(prepareReply(buffer), id, e, SftpConstants.SSH_FXP_READDIR, handle);
             return;
         }
 
@@ -858,7 +858,7 @@ public class SftpSubsystem
             extensions.put(name, data);
         }
 
-        buffer.clear();
+        buffer = prepareReply(buffer);
 
         buffer.putByte((byte) SftpConstants.SSH_FXP_VERSION);
         buffer.putInt(version);
@@ -871,6 +871,12 @@ public class SftpSubsystem
     }
 
     @Override
+    protected Buffer prepareReply(Buffer buffer) {
+        buffer.clear();
+        return buffer;
+    }
+
+    @Override
     protected void send(Buffer buffer) throws IOException {
         int len = buffer.available();
         BufferUtils.writeInt(out, len, workBuf, 0, workBuf.length);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6bed356a/sshd-sftp/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/openssh/helpers/OpenSSHExtensionsTest.java
----------------------------------------------------------------------
diff --git a/sshd-sftp/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/openssh/helpers/OpenSSHExtensionsTest.java b/sshd-sftp/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/openssh/helpers/OpenSSHExtensionsTest.java
index ac8ed34..1e35b5a 100644
--- a/sshd-sftp/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/openssh/helpers/OpenSSHExtensionsTest.java
+++ b/sshd-sftp/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/openssh/helpers/OpenSSHExtensionsTest.java
@@ -151,7 +151,7 @@ public class OpenSSHExtensionsTest extends AbstractSftpClientTestSupport {
                                 throw new StreamCorruptedException("executeExtendedCommand(" + extension + ") previous not null: " + prev);
                             }
 
-                            buffer.clear();
+                            buffer = prepareReply(buffer);
                             buffer.putByte((byte) SftpConstants.SSH_FXP_EXTENDED_REPLY);
                             buffer.putInt(id);
                             OpenSSHStatExtensionInfo.encode(buffer, expected);