protected void handleDirectoryTransferRequest()

in sshd-scp/src/main/java/org/apache/sshd/scp/client/ScpRemote2RemoteTransferHelper.java [273:373]


    protected void handleDirectoryTransferRequest(
            String srcPath, InputStream srcIn, OutputStream srcOut,
            String dstPath, InputStream dstIn, OutputStream dstOut,
            int depth, ScpTimestampCommandDetails dirTime, String header)
            throws IOException {
        if (header.charAt(0) != ScpReceiveDirCommandDetails.COMMAND_NAME) {
            throw new IllegalArgumentException("Invalid file transfer request: " + header);
        }

        ScpIoUtils.writeLine(dstOut, csOut, header);
        ScpAckInfo ackInfo = transferStatusCode(header, dstIn, srcOut);
        ackInfo.validateCommandStatusCode("[DST@" + depth + "] " + header, "handleDirectoryTransferRequest");

        ScpReceiveDirCommandDetails dirDetails = new ScpReceiveDirCommandDetails(header);
        signalReceivedCommand(dirDetails);

        String dirName = dirDetails.getName();
        // 1st command refers to the first path component of the original source/destination
        String source = (depth == 0) ? srcPath : SelectorUtils.concatPaths(srcPath, dirName, '/');
        String destination = (depth == 0) ? dstPath : SelectorUtils.concatPaths(dstPath, dirName, '/');

        ClientSession srcSession = getSourceSession();
        ClientSession dstSession = getDestinationSession();
        if (listener != null) {
            listener.startDirectDirectoryTransfer(srcSession, source, dstSession, destination, dirTime, dirDetails);
        }

        try {
            for (boolean debugEnabled = log.isDebugEnabled(), dirEndSignal = false;
                 !dirEndSignal;
                 debugEnabled = log.isDebugEnabled()) {
                Object data = receiveNextCmd("handleDirectoryTransferRequest", srcIn);
                if (data instanceof ScpAckInfo) {
                    throw new StreamCorruptedException("Unexpected ACK instead of header: " + data);
                }

                header = (String) data;
                if (debugEnabled) {
                    log.debug("handleDirectoryTransferRequest({})[depth={}] {} => {}: header={}",
                            this, depth, source, destination, header);
                }

                ScpTimestampCommandDetails time = null;
                char cmdName = header.charAt(0);
                if (cmdName == ScpTimestampCommandDetails.COMMAND_NAME) {
                    // Pass along the "T<mtime> 0 <atime> 0" and wait for response
                    time = new ScpTimestampCommandDetails(header);
                    signalReceivedCommand(time);

                    header = transferTimestampCommand(source, srcIn, srcOut, destination, dstIn, dstOut, header);
                    if (debugEnabled) {
                        log.debug("handleDirectoryTransferRequest({})[depth={}] {} => {}: header={}",
                                this, depth, source, destination, header);
                    }
                    cmdName = header.charAt(0);
                }

                switch (cmdName) {
                    case ScpReceiveFileCommandDetails.COMMAND_NAME:
                    case ScpReceiveDirCommandDetails.COMMAND_NAME: {
                        ScpPathCommandDetailsSupport subPathDetails = (cmdName == ScpReceiveFileCommandDetails.COMMAND_NAME)
                                ? new ScpReceiveFileCommandDetails(header)
                                : new ScpReceiveDirCommandDetails(header);
                        String name = subPathDetails.getName();
                        String srcSubPath = SelectorUtils.concatPaths(source, name, '/');
                        String dstSubPath = SelectorUtils.concatPaths(destination, name, '/');
                        if (cmdName == ScpReceiveFileCommandDetails.COMMAND_NAME) {
                            handleFileTransferRequest(srcSubPath, srcIn, srcOut, dstSubPath, dstIn, dstOut, time, header);
                        } else {
                            handleDirectoryTransferRequest(srcSubPath, srcIn, srcOut, dstSubPath, dstIn, dstOut, depth + 1,
                                    time, header);
                        }
                        break;
                    }

                    case ScpDirEndCommandDetails.COMMAND_NAME: {
                        ScpIoUtils.writeLine(dstOut, csOut, header);
                        ackInfo = transferStatusCode(header, dstIn, srcOut);
                        ackInfo.validateCommandStatusCode("[DST@" + depth + "] " + header, "handleDirectoryTransferRequest");

                        ScpDirEndCommandDetails details = ScpDirEndCommandDetails.parse(header);
                        signalReceivedCommand(details);
                        dirEndSignal = true;
                        break;
                    }

                    default:
                        throw new StreamCorruptedException("Unexpected file command: " + header);
                }
            }
        } catch (IOException | RuntimeException | Error e) {
            if (listener != null) {
                listener.endDirectDirectoryTransfer(srcSession, source, dstSession, destination, dirTime, dirDetails, e);
            }
            throw e;
        }

        if (listener != null) {
            listener.endDirectDirectoryTransfer(srcSession, source, dstSession, destination, dirTime, dirDetails, null);
        }
    }