This is an automated email from the ASF dual-hosted git repository.

lgoldstein pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git


The following commit(s) were added to refs/heads/master by this push:
     new 270caaa  Propagate SCP file transfer ACK data to ScpTransferListener 
before validating it
270caaa is described below

commit 270caaafdbfddfba05f0b8de2ed69b237b557f54
Author: Lyor Goldstein <lgoldst...@apache.org>
AuthorDate: Fri Dec 4 17:34:17 2020 +0200

    Propagate SCP file transfer ACK data to ScpTransferListener before 
validating it
---
 CHANGES.md                                         |  1 +
 .../org/apache/sshd/cli/client/ScpCommandMain.java | 11 ++++++++++-
 .../java/org/apache/sshd/scp/common/ScpHelper.java | 22 +++++++++++++++++-----
 .../sshd/scp/common/ScpTransferEventListener.java  | 19 +++++++++++++++++++
 .../sshd/scp/client/AbstractScpTestSupport.java    | 10 ++++++++++
 5 files changed, 57 insertions(+), 6 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index 0f0d63c..12357d2 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -33,6 +33,7 @@ or `-key-file` command line option.
 * [SSHD-1079](https://issues.apache.org/jira/browse/SSHD-1079) Experimental 
async mode on the local port forwarder
 * [SSHD-1086](https://issues.apache.org/jira/browse/SSHD-1086) Added SFTP 
aware directory scanning helper classes
 * [SSHD-1089](https://issues.apache.org/jira/browse/SSHD-1089) Added wrappers 
for one-time single session usage of SFTP/SCP clients
+* Propagate SCP file transfer ACK data to ScpTransferListener before 
validating it.
 
 ## Behavioral changes and enhancements
 
diff --git 
a/sshd-cli/src/main/java/org/apache/sshd/cli/client/ScpCommandMain.java 
b/sshd-cli/src/main/java/org/apache/sshd/cli/client/ScpCommandMain.java
index cfaf2d8..3990cd9 100644
--- a/sshd-cli/src/main/java/org/apache/sshd/cli/client/ScpCommandMain.java
+++ b/sshd-cli/src/main/java/org/apache/sshd/cli/client/ScpCommandMain.java
@@ -54,6 +54,7 @@ import 
org.apache.sshd.scp.client.ScpRemote2RemoteTransferHelper;
 import org.apache.sshd.scp.client.ScpRemote2RemoteTransferListener;
 import org.apache.sshd.scp.common.ScpLocation;
 import org.apache.sshd.scp.common.ScpTransferEventListener;
+import org.apache.sshd.scp.common.helpers.ScpAckInfo;
 import org.apache.sshd.scp.common.helpers.ScpReceiveDirCommandDetails;
 import org.apache.sshd.scp.common.helpers.ScpReceiveFileCommandDetails;
 import org.apache.sshd.scp.common.helpers.ScpTimestampCommandDetails;
@@ -241,7 +242,7 @@ public class ScpCommandMain extends SshClientCliSupport {
 
     /* 
--------------------------------------------------------------------------------
 */
 
-    @SuppressWarnings("checkstyle:ParameterNumber")
+    @SuppressWarnings({ "checkstyle:ParameterNumber", 
"checkstyle:anoninnerlength" })
     public static void xferLocalToRemote(
             BufferedReader stdin, PrintStream stdout, PrintStream stderr, 
String[] args,
             ScpLocation source, ScpLocation target, Collection<Option> options,
@@ -285,6 +286,14 @@ public class ScpCommandMain extends SshClientCliSupport {
                         logEvent("endFileEvent", session, op, file, length, 
perms, thrown);
                     }
 
+                    @Override
+                    public void handleFileEventAckInfo(
+                            Session session, FileOperation op, Path file, long 
length,
+                            Set<PosixFilePermission> perms, ScpAckInfo ackInfo)
+                            throws IOException {
+                        logEvent("ackInfo(" + ackInfo + ")", session, op, 
file, length, perms, null);
+                    }
+
                     private void logEvent(
                             String name, Session session, FileOperation op, 
Path file, long length,
                             Collection<PosixFilePermission> perms, Throwable 
thrown) {
diff --git a/sshd-scp/src/main/java/org/apache/sshd/scp/common/ScpHelper.java 
b/sshd-scp/src/main/java/org/apache/sshd/scp/common/ScpHelper.java
index 5db850c..a22bdcb 100644
--- a/sshd-scp/src/main/java/org/apache/sshd/scp/common/ScpHelper.java
+++ b/sshd-scp/src/main/java/org/apache/sshd/scp/common/ScpHelper.java
@@ -354,12 +354,13 @@ public class ScpHelper extends AbstractLoggingBean 
implements SessionHolder<Sess
         Session session = getSession();
         String name = details.getName();
         Set<PosixFilePermission> perms = details.getPermissions();
+        Path file;
         try (InputStream is = new LimitInputStream(this.in, length);
              OutputStream os = resolver.resolveTargetStream(session, name, 
length, perms,
                      IoUtils.EMPTY_OPEN_OPTIONS)) {
             sendOk();
 
-            Path file = resolver.getEventListenerFilePath();
+            file = resolver.getEventListenerFilePath();
             listener.startFileEvent(session, FileOperation.RECEIVE, file, 
length, perms);
             try {
                 IoUtils.copy(is, os, bufSize);
@@ -379,7 +380,7 @@ public class ScpHelper extends AbstractLoggingBean 
implements SessionHolder<Sess
         if (debugEnabled) {
             log.debug("receiveStream({})[{}] ACK={}", this, resolver, ackInfo);
         }
-        validateAckReplyCode("receiveStream", resolver, ackInfo);
+        validateFileOperationAckReplyCode(header, session, 
FileOperation.RECEIVE, file, length, perms, ackInfo);
     }
 
     public String readLine() throws IOException {
@@ -564,8 +565,9 @@ public class ScpHelper extends AbstractLoggingBean 
implements SessionHolder<Sess
         validateAckReplyCode(cmd, resolver, ackInfo);
 
         Session session = getSession();
+        Path path;
         try (InputStream in = resolver.resolveSourceStream(session, fileSize, 
perms, IoUtils.EMPTY_OPEN_OPTIONS)) {
-            Path path = resolver.getEventListenerFilePath();
+            path = resolver.getEventListenerFilePath();
             listener.startFileEvent(session, FileOperation.SEND, path, 
fileSize, perms);
             try {
                 IoUtils.copy(in, out, bufSize);
@@ -582,7 +584,8 @@ public class ScpHelper extends AbstractLoggingBean 
implements SessionHolder<Sess
         if (debugEnabled) {
             log.debug("sendStream({})[{}] command='{}' ACK={}", this, 
resolver, cmd, ackInfo);
         }
-        validateAckReplyCode("sendStream", resolver, ackInfo);
+
+        validateFileOperationAckReplyCode(cmd, session, FileOperation.SEND, 
path, fileSize, perms, ackInfo);
     }
 
     protected void validateOperationReadyCode(String command, Object location, 
ScpAckInfo ackInfo)
@@ -590,6 +593,14 @@ public class ScpHelper extends AbstractLoggingBean 
implements SessionHolder<Sess
         validateCommandStatusCode(command, location, ackInfo, false);
     }
 
+    protected void validateFileOperationAckReplyCode(
+            String command, Session session, FileOperation op, Path file,
+            long fileSize, Set<PosixFilePermission> perms, ScpAckInfo ackInfo)
+            throws IOException {
+        listener.handleFileEventAckInfo(session, op, file, fileSize, perms, 
ackInfo);
+        validateAckReplyCode(command, file, ackInfo);
+    }
+
     protected void validateAckReplyCode(String command, Object location, 
ScpAckInfo ackInfo)
             throws IOException {
         validateCommandStatusCode(command, location, ackInfo, false);
@@ -695,7 +706,8 @@ public class ScpHelper extends AbstractLoggingBean 
implements SessionHolder<Sess
         if (debugEnabled) {
             log.debug("sendDir({})[{}] 'E' command ACK={}", this, path, 
ackInfo);
         }
-        validateAckReplyCode(ScpDirEndCommandDetails.HEADER, path, ackInfo);
+
+        validateAckReplyCode(cmd, path, ackInfo);
     }
 
     protected ScpAckInfo sendAcknowledgedCommand(String cmd) throws 
IOException {
diff --git 
a/sshd-scp/src/main/java/org/apache/sshd/scp/common/ScpTransferEventListener.java
 
b/sshd-scp/src/main/java/org/apache/sshd/scp/common/ScpTransferEventListener.java
index dc685f4..2cf9996 100644
--- 
a/sshd-scp/src/main/java/org/apache/sshd/scp/common/ScpTransferEventListener.java
+++ 
b/sshd-scp/src/main/java/org/apache/sshd/scp/common/ScpTransferEventListener.java
@@ -26,6 +26,7 @@ import java.util.Set;
 
 import org.apache.sshd.common.session.Session;
 import org.apache.sshd.common.util.SshdEventListener;
+import org.apache.sshd.scp.common.helpers.ScpAckInfo;
 
 /**
  * Can be registered in order to receive events about SCP transfers
@@ -78,6 +79,24 @@ public interface ScpTransferEventListener extends 
SshdEventListener {
     }
 
     /**
+     * Called after {@link #endFileEvent(Session, FileOperation, Path, long, 
Set, Throwable)} if no exception was thrown
+     * and the peer's ACK was successfully read
+     *
+     * @param  session     The client/server {@link Session} through which the 
transfer is being executed
+     * @param  op          The {@link FileOperation}
+     * @param  file        The <U>local</U> referenced file {@link Path}
+     * @param  length      Size (in bytes) of transferred data
+     * @param  perms       A {@link Set} of {@link PosixFilePermission}s to be 
applied once transfer is complete
+     * @param  ackInfo     The {@link ScpAckInfo} received after a file 
transfer - <U>before</U> validating it
+     * @throws IOException If failed to handle the event
+     */
+    default void handleFileEventAckInfo(
+            Session session, FileOperation op, Path file, long length, 
Set<PosixFilePermission> perms, ScpAckInfo ackInfo)
+            throws IOException {
+        // ignored
+    }
+
+    /**
      * @param  session     The client/server {@link Session} through which the 
transfer is being executed
      * @param  op          The {@link FileOperation}
      * @param  file        The <U>local</U> referenced folder {@link Path}
diff --git 
a/sshd-scp/src/test/java/org/apache/sshd/scp/client/AbstractScpTestSupport.java 
b/sshd-scp/src/test/java/org/apache/sshd/scp/client/AbstractScpTestSupport.java
index 317e1f5..80bd14c 100644
--- 
a/sshd-scp/src/test/java/org/apache/sshd/scp/client/AbstractScpTestSupport.java
+++ 
b/sshd-scp/src/test/java/org/apache/sshd/scp/client/AbstractScpTestSupport.java
@@ -32,6 +32,7 @@ import org.apache.sshd.common.file.FileSystemFactory;
 import org.apache.sshd.common.file.virtualfs.VirtualFileSystemFactory;
 import org.apache.sshd.common.session.Session;
 import org.apache.sshd.scp.common.ScpTransferEventListener;
+import org.apache.sshd.scp.common.helpers.ScpAckInfo;
 import org.apache.sshd.scp.server.ScpCommandFactory;
 import org.apache.sshd.server.SshServer;
 import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
@@ -45,6 +46,7 @@ import org.junit.Before;
  * @author <a href="mailto:d...@mina.apache.org";>Apache MINA SSHD Project</a>
  */
 public abstract class AbstractScpTestSupport extends BaseTestSupport {
+    @SuppressWarnings("checkstyle:anoninnerlength")
     protected static final ScpTransferEventListener DEBUG_LISTENER = new 
ScpTransferEventListener() {
         @Override
         public void startFolderEvent(
@@ -70,6 +72,14 @@ public abstract class AbstractScpTestSupport extends 
BaseTestSupport {
             logEvent("endFileEvent", s, op, file, true, length, perms, thrown);
         }
 
+        @Override
+        public void handleFileEventAckInfo(
+                Session session, FileOperation op, Path file, long length,
+                Set<PosixFilePermission> perms, ScpAckInfo ackInfo)
+                throws IOException {
+            logEvent("ackInfo(" + ackInfo + ")", session, op, file, true, 
length, perms, null);
+        }
+
         private void logEvent(
                 String type, Session s, FileOperation op, Path path, boolean 
isFile,
                 long length, Collection<PosixFilePermission> perms, Throwable 
t) {

Reply via email to