public class SftpSubsystem extends AbstractSftpSubsystemHelper implements Command, java.lang.Runnable, SessionAware, FileSystemAware, ExecutorServiceCarrier, AsyncCommand, ChannelSessionAware, ChannelDataReceiver
| Modifier and Type | Field and Description |
|---|---|
protected Buffer |
buffer |
protected ExitCallback |
callback |
protected ChannelSession |
channelSession |
protected static Buffer |
CLOSE |
protected java.util.concurrent.atomic.AtomicBoolean |
closed |
static int |
DEFAULT_FILE_HANDLE_ROUNDS |
static int |
DEFAULT_FILE_HANDLE_SIZE |
static int |
DEFAULT_MAX_OPEN_HANDLES |
static int |
DEFAULT_MAX_READDIR_DATA_SIZE |
protected java.nio.file.Path |
defaultDir |
protected Environment |
env |
protected IoOutputStream |
err |
protected CloseableExecutorService |
executorService |
protected java.util.Map<java.lang.String,byte[]> |
extensions |
static java.lang.String |
FILE_HANDLE_SIZE
Size in bytes of the opaque handle value
|
protected int |
fileHandleSize |
protected java.nio.file.FileSystem |
fileSystem |
protected java.util.Map<java.lang.String,Handle> |
handles |
static java.lang.String |
MAX_FILE_HANDLE_RAND_ROUNDS
Max.
|
static int |
MAX_FILE_HANDLE_ROUNDS |
static int |
MAX_FILE_HANDLE_SIZE |
static java.lang.String |
MAX_OPEN_HANDLES_PER_SESSION
Properties key for the maximum of available open handles per session.
|
static java.lang.String |
MAX_READDIR_DATA_SIZE_PROP
Maximum amount of data allocated for listing the contents of a directory in any single invocation of
doReadDir(Buffer, int) |
protected int |
maxFileHandleRounds |
static int |
MIN_FILE_HANDLE_ROUNDS |
static int |
MIN_FILE_HANDLE_SIZE |
protected IoOutputStream |
out |
protected java.util.concurrent.Future<?> |
pendingFuture |
protected Random |
randomizer |
protected java.util.concurrent.BlockingQueue<Buffer> |
requests |
protected java.util.concurrent.atomic.AtomicLong |
requestsCount |
protected ServerSession |
serverSession |
protected int |
version |
protected byte[] |
workBuf |
ACL_SUPPORTED_MASK_PROP, AUTO_FOLLOW_LINKS, CLIENT_EXTENSIONS_PROP, DEFAULT_ACL_SUPPORTED_MASK, DEFAULT_AUTO_FOLLOW_LINKS, DEFAULT_MAX_READDATA_PACKET_LENGTH, DEFAULT_OPEN_SSH_EXTENSIONS, DEFAULT_OPEN_SSH_EXTENSIONS_NAMES, DEFAULT_SUPPORTED_CLIENT_EXTENSIONS, MAX_READDATA_PACKET_LENGTH_PROP, NEWLINE_VALUE, OPENSSH_EXTENSIONS_PROPlogALL_SFTP_IMPL, HIGHER_SFTP_IMPL, LOWER_SFTP_IMPL, SFTP_VERSION, SUPPORTED_SFTP_VERSIONS| Constructor and Description |
|---|
SftpSubsystem(CloseableExecutorService executorService,
UnsupportedAttributePolicy policy,
SftpFileSystemAccessor accessor,
SftpErrorStatusDataHandler errorStatusDataHandler) |
| Modifier and Type | Method and Description |
|---|---|
void |
close() |
protected void |
closeAllHandles() |
protected void |
createLink(int id,
java.lang.String existingPath,
java.lang.String linkPath,
boolean symLink) |
int |
data(ChannelSession channel,
byte[] buf,
int start,
int len)
Called when the server receives additional bytes from the client.
|
void |
destroy(ChannelSession channel)
This method is called by the SSH server to destroy the command because the client has disconnected somehow.
|
protected void |
doBlock(int id,
java.lang.String handle,
long offset,
long length,
int mask) |
protected void |
doCheckFileHash(int id,
java.lang.String targetType,
java.lang.String target,
java.util.Collection<java.lang.String> algos,
long startOffset,
long length,
int blockSize,
Buffer buffer) |
protected void |
doClose(int id,
java.lang.String handle) |
protected void |
doCopyData(int id,
java.lang.String readHandle,
long readOffset,
long readLength,
java.lang.String writeHandle,
long writeOffset) |
protected void |
doFSetStat(int id,
java.lang.String handle,
java.util.Map<java.lang.String,?> attrs) |
protected java.util.Map<java.lang.String,java.lang.Object> |
doFStat(int id,
java.lang.String handle,
int flags) |
protected void |
doInit(Buffer buffer,
int id) |
protected byte[] |
doMD5Hash(int id,
java.lang.String targetType,
java.lang.String target,
long startOffset,
long length,
byte[] quickCheckHash) |
protected java.lang.String |
doOpen(int id,
java.lang.String path,
int pflags,
int access,
java.util.Map<java.lang.String,java.lang.Object> attrs) |
protected java.lang.String |
doOpenDir(int id,
java.lang.String path,
java.nio.file.Path p,
java.nio.file.LinkOption... options) |
protected void |
doOpenSSHFsync(int id,
java.lang.String handle) |
protected void |
doProcess(Buffer buffer,
int length,
int type,
int id) |
protected int |
doRead(int id,
java.lang.String handle,
long offset,
int length,
byte[] data,
int doff) |
protected void |
doReadDir(Buffer buffer,
int id) |
protected void |
doTextSeek(int id,
java.lang.String handle,
long line) |
protected void |
doUnblock(int id,
java.lang.String handle,
long offset,
long length) |
protected void |
doVersionSelect(Buffer buffer,
int id,
java.lang.String proposed) |
protected void |
doWrite(int id,
java.lang.String handle,
long offset,
int length,
byte[] data,
int doff,
int remaining) |
protected java.lang.String |
generateFileHandle(java.nio.file.Path file) |
java.nio.file.Path |
getDefaultDirectory() |
CloseableExecutorService |
getExecutorService() |
ServerSession |
getServerSession() |
int |
getVersion() |
protected Buffer |
prepareReply(Buffer buffer) |
void |
run() |
protected void |
send(Buffer buffer) |
void |
setChannelSession(ChannelSession session)
Receives the channel in which the command is being executed.
|
void |
setErrorStream(java.io.OutputStream err)
Set the error stream that can be used by the shell to write its errors.
|
void |
setExitCallback(ExitCallback callback)
Set the callback that the shell has to call when it is closed.
|
void |
setFileSystem(java.nio.file.FileSystem fileSystem)
Set the file system in which this shell will be executed.
|
void |
setInputStream(java.io.InputStream in)
Set the input stream that can be used by the shell to read input.
|
void |
setIoErrorStream(IoOutputStream err)
Set the error stream that can be used by the shell to write its errors.
|
void |
setIoInputStream(IoInputStream in)
Set the input stream that can be used by the shell to read input.
|
void |
setIoOutputStream(IoOutputStream out)
Set the output stream that can be used by the shell to write its output.
|
void |
setOutputStream(java.io.OutputStream out)
Set the output stream that can be used by the shell to write its output.
|
void |
setSession(ServerSession session) |
void |
start(ChannelSession channel,
Environment env)
Starts the command execution.
|
addMissingAttribute, addSftpEventListener, appendAclSupportedExtension, appendExtensions, appendNewlineExtension, appendOpenSSHExtensions, appendSupported2Extension, appendSupportedExtension, appendVendorIdExtension, appendVersionsExtension, checkVersionCompatibility, doBlock, doCheckFileHash, doCheckFileHash, doClose, doCopyData, doCopyFile, doCopyFile, doCopyFile, doExtended, doFSetStat, doFStat, doLink, doLink, doLStat, doLStat, doMakeDirectory, doMakeDirectory, doMD5Hash, doMD5Hash, doOpen, doOpenDir, doOpenSSHFsync, doOpenSSHHardLink, doOpenSSHHardLink, doRead, doReadDir, doReadLink, doReadLink, doRealPath, doRealPathV345, doRealPathV6, doRemove, doRemove, doRemove, doRemoveDirectory, doRemoveDirectory, doRename, doRename, doRename, doSetAttributes, doSetStat, doSetStat, doSpaceAvailable, doSpaceAvailable, doStat, doStat, doSymLink, doSymLink, doTextSeek, doUnblock, doUnsupported, doUnsupportedExtension, doVersionSelect, doWrite, executeExtendedCommand, getAttributes, getAttributes, getErrorStatusDataHandler, getFileSystemAccessor, getLongName, getLongName, getLongName, getPathResolutionLinkOption, getSftpEventListenerProxy, getShortName, getSupportedClientExtensions, getUnsupportedAttributePolicy, handleReadFileAttributesException, handleSetFileAttributeFailure, handleUnknownStatusFileAttributes, handleUnsupportedAttributes, handleUserPrincipalLookupServiceException, normalize, process, readAttrs, readFileAttributes, removeSftpEventListener, resolveAclSupportedCapabilities, resolveFile, resolveFileAttributes, resolveMissingFileAttributes, resolveMissingFileAttributeValue, resolveNewlineValue, resolveNormalizedLocation, resolveOpenSSHExtensions, resolvePathResolutionFollowLinks, sendAttrs, sendHandle, sendLink, sendPath, sendStatus, sendStatus, sendStatus, setFileAccessControl, setFileAttribute, setFileAttributes, setFileExtensions, setFileOwnership, setFilePermissions, setFileRawViewAttribute, setFileTime, signalOpenFailure, signalRemovalPreConditionFailure, toGroup, toUser, validateHandle, validateProposedVersion, validateRealPath, writeAttrs, writeDirEntrygetSimplifiedLoggerclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitsetFileSystemFactorygetSessiongetSessionContextpublic static final java.lang.String MAX_OPEN_HANDLES_PER_SESSION
public static final int DEFAULT_MAX_OPEN_HANDLES
public static final java.lang.String FILE_HANDLE_SIZE
DEFAULT_FILE_HANDLE_SIZE,
Constant Field Valuespublic static final int MIN_FILE_HANDLE_SIZE
public static final int DEFAULT_FILE_HANDLE_SIZE
public static final int MAX_FILE_HANDLE_SIZE
public static final java.lang.String MAX_FILE_HANDLE_RAND_ROUNDS
public static final int MIN_FILE_HANDLE_ROUNDS
public static final int DEFAULT_FILE_HANDLE_ROUNDS
public static final int MAX_FILE_HANDLE_ROUNDS
public static final java.lang.String MAX_READDIR_DATA_SIZE_PROP
doReadDir(Buffer, int)public static final int DEFAULT_MAX_READDIR_DATA_SIZE
protected static final Buffer CLOSE
protected final java.util.concurrent.atomic.AtomicBoolean closed
protected final java.util.concurrent.atomic.AtomicLong requestsCount
protected final java.util.Map<java.lang.String,byte[]> extensions
protected final java.util.Map<java.lang.String,Handle> handles
protected final Buffer buffer
protected final java.util.concurrent.BlockingQueue<Buffer> requests
protected ExitCallback callback
protected IoOutputStream out
protected IoOutputStream err
protected Environment env
protected Random randomizer
protected int fileHandleSize
protected int maxFileHandleRounds
protected java.util.concurrent.Future<?> pendingFuture
protected byte[] workBuf
protected java.nio.file.FileSystem fileSystem
protected java.nio.file.Path defaultDir
protected int version
protected ServerSession serverSession
protected ChannelSession channelSession
protected CloseableExecutorService executorService
public SftpSubsystem(CloseableExecutorService executorService, UnsupportedAttributePolicy policy, SftpFileSystemAccessor accessor, SftpErrorStatusDataHandler errorStatusDataHandler)
executorService - The CloseableExecutorService to be used by the SftpSubsystem
command when starting execution. If null then a single-threaded ad-hoc
service is used.policy - The UnsupportedAttributePolicy to use if failed to access some local file
attributesaccessor - The SftpFileSystemAccessor to use for opening files and directorieserrorStatusDataHandler - The (never null) SftpErrorStatusDataHandler to use when generating
failed commands error messagesThreadUtils.newSingleThreadExecutor(String)public int getVersion()
getVersion in interface SftpSubsystemEnvironmentpublic java.nio.file.Path getDefaultDirectory()
getDefaultDirectory in interface SftpSubsystemEnvironmentchroot locationpublic CloseableExecutorService getExecutorService()
getExecutorService in interface ExecutorServiceCarrierCloseableExecutorService to usepublic void setSession(ServerSession session)
setSession in interface SessionAwaresession - The ServerSession in which this shell will be executed.public ServerSession getServerSession()
getServerSession in interface ServerSessionHolderServerSession usedpublic void setChannelSession(ChannelSession session)
ChannelSessionAwaresetChannelSession in interface ChannelSessionAwaresession - never nullpublic void setFileSystem(java.nio.file.FileSystem fileSystem)
FileSystemAwaresetFileSystem in interface FileSystemAwarefileSystem - the file systempublic void setExitCallback(ExitCallback callback)
CommandsetExitCallback in interface Commandcallback - The ExitCallback to call when shell is closedpublic void setInputStream(java.io.InputStream in)
CommandsetInputStream in interface Commandin - The InputStream used by the shell to read input.public void setOutputStream(java.io.OutputStream out)
CommandsetOutputStream in interface Commandout - The OutputStream used by the shell to write its outputpublic void setErrorStream(java.io.OutputStream err)
CommandsetErrorStream in interface Commanderr - The OutputStream used by the shell to write its errorspublic void setIoInputStream(IoInputStream in)
AsyncCommandsetIoInputStream in interface AsyncCommandin - The IoInputStream used by the shell to read inputpublic void setIoOutputStream(IoOutputStream out)
AsyncCommandsetIoOutputStream in interface AsyncCommandout - The IoOutputStream used by the shell to write its outputpublic void setIoErrorStream(IoOutputStream err)
AsyncCommandsetIoErrorStream in interface AsyncCommanderr - The IoOutputStream used by the shell to write its errorspublic void start(ChannelSession channel, Environment env) throws java.io.IOException
CommandLifecycleRunnable, and this method should spawn a new thread like:
Thread(this).start();
start in interface CommandLifecyclechannel - The ChannelSession through which the command has been receivedenv - The Environmentjava.io.IOException - If failed to startpublic int data(ChannelSession channel, byte[] buf, int start, int len) throws java.io.IOException
ChannelDataReceiver
Called when the server receives additional bytes from the client. When Closeable.close()-d then indicates EOF -
The client will no longer send us any more data.
SSH channels use the windowing mechanism to perform flow control, much like TCP does. The server gives the client the initial window size, which represents the number of bytes the client can send to the server. As the server receives data, it can send a message to the client to allow it to send more data.
The return value from this method is used to control this behaviour. Intuitively speaking, the callee returns the number of bytes consumed by this method, by the time this method returns. Picture a one-way long bridge (for example Golden Gate Bridge) with toll plazas on both sides. The window size is the maximum number of cars allowed on the bridge. Here we are on the receiving end, so our job here is to count the number of cars as it leaves the bridge, and if enough of them left, we'll signal the sending end that they can let in more cars. The return value of this method counts the number of cars that are leaving in this batch.
In simple cases, where the callee has consumed the bytes before it returns, the return value must be the same value as the 'len' parameter given.
On the other hand, if the callee is queueing up the received bytes somewhere to be consumed later (for example by
another thread), then this method should return 0, for the bytes aren't really consumed yet. And when at some
later point the bytes are actually used, then you'll invoke channel.getLocalWindow().consumeAndCheck(len)
to let the channel know that bytes are consumed.
This behaviour will result in a better flow control, as the server will not allow the SSH client to overflow its buffer. If instead you always return the value passed in the 'len' parameter, the place where you are queueing up bytes may overflow.
In either case, the callee must account for every bytes it receives in this method. Returning 0 and failing to
call back channel.getLocalWindow().consumeAndCheck(len) later will dry up the window size, and eventually
the client will stop sending you any data.
In the SSH protocol, this method invocation is triggered by a SSH_MSG_CHANNEL_DATA message.
data in interface ChannelDataReceiverchannel - The caller to which this ChannelDataReceiver is assigned. Never null.buf - Holds the bytes received. This buffer belongs to the caller, and it might get reused by the
caller as soon as this method returns.start - buf[start] is the first byte that received from the client.len - the length of the bytes received. Can be zero.java.io.IOException - if failed to consume the datapublic void run()
run in interface java.lang.Runnablepublic void close()
throws java.io.IOException
close in interface java.io.Closeableclose in interface java.lang.AutoCloseablejava.io.IOExceptionprotected void doProcess(Buffer buffer, int length, int type, int id) throws java.io.IOException
doProcess in class AbstractSftpSubsystemHelperjava.io.IOExceptionprotected void createLink(int id,
java.lang.String existingPath,
java.lang.String linkPath,
boolean symLink)
throws java.io.IOException
createLink in class AbstractSftpSubsystemHelperjava.io.IOExceptionprotected void doTextSeek(int id,
java.lang.String handle,
long line)
throws java.io.IOException
doTextSeek in class AbstractSftpSubsystemHelperjava.io.IOExceptionprotected void doOpenSSHFsync(int id,
java.lang.String handle)
throws java.io.IOException
doOpenSSHFsync in class AbstractSftpSubsystemHelperjava.io.IOExceptionprotected void doCheckFileHash(int id,
java.lang.String targetType,
java.lang.String target,
java.util.Collection<java.lang.String> algos,
long startOffset,
long length,
int blockSize,
Buffer buffer)
throws java.lang.Exception
doCheckFileHash in class AbstractSftpSubsystemHelperjava.lang.Exceptionprotected byte[] doMD5Hash(int id,
java.lang.String targetType,
java.lang.String target,
long startOffset,
long length,
byte[] quickCheckHash)
throws java.lang.Exception
doMD5Hash in class AbstractSftpSubsystemHelperjava.lang.Exceptionprotected void doVersionSelect(Buffer buffer, int id, java.lang.String proposed) throws java.io.IOException
doVersionSelect in class AbstractSftpSubsystemHelperjava.io.IOExceptionprotected void doBlock(int id,
java.lang.String handle,
long offset,
long length,
int mask)
throws java.io.IOException
doBlock in class AbstractSftpSubsystemHelperjava.io.IOExceptionprotected void doUnblock(int id,
java.lang.String handle,
long offset,
long length)
throws java.io.IOException
doUnblock in class AbstractSftpSubsystemHelperjava.io.IOExceptionprotected void doCopyData(int id,
java.lang.String readHandle,
long readOffset,
long readLength,
java.lang.String writeHandle,
long writeOffset)
throws java.io.IOException
doCopyData in class AbstractSftpSubsystemHelperjava.io.IOExceptionprotected void doReadDir(Buffer buffer, int id) throws java.io.IOException
doReadDir in class AbstractSftpSubsystemHelperjava.io.IOExceptionprotected java.lang.String doOpenDir(int id,
java.lang.String path,
java.nio.file.Path p,
java.nio.file.LinkOption... options)
throws java.io.IOException
doOpenDir in class AbstractSftpSubsystemHelperjava.io.IOExceptionprotected void doFSetStat(int id,
java.lang.String handle,
java.util.Map<java.lang.String,?> attrs)
throws java.io.IOException
doFSetStat in class AbstractSftpSubsystemHelperjava.io.IOExceptionprotected java.util.Map<java.lang.String,java.lang.Object> doFStat(int id,
java.lang.String handle,
int flags)
throws java.io.IOException
doFStat in class AbstractSftpSubsystemHelperjava.io.IOExceptionprotected void doWrite(int id,
java.lang.String handle,
long offset,
int length,
byte[] data,
int doff,
int remaining)
throws java.io.IOException
doWrite in class AbstractSftpSubsystemHelperjava.io.IOExceptionprotected int doRead(int id,
java.lang.String handle,
long offset,
int length,
byte[] data,
int doff)
throws java.io.IOException
doRead in class AbstractSftpSubsystemHelperjava.io.IOExceptionprotected void doClose(int id,
java.lang.String handle)
throws java.io.IOException
doClose in class AbstractSftpSubsystemHelperjava.io.IOExceptionprotected java.lang.String doOpen(int id,
java.lang.String path,
int pflags,
int access,
java.util.Map<java.lang.String,java.lang.Object> attrs)
throws java.io.IOException
doOpen in class AbstractSftpSubsystemHelperid - Request idpath - Pathpflags - Open mode flags - see SSH_FXF_XXX flagsaccess - Access mode flags - see ACE4_XXX flagsattrs - Requested attributesjava.io.IOException - if failed to executeprotected java.lang.String generateFileHandle(java.nio.file.Path file)
throws java.io.IOException
java.io.IOExceptionprotected void doInit(Buffer buffer, int id) throws java.io.IOException
doInit in class AbstractSftpSubsystemHelperjava.io.IOExceptionprotected Buffer prepareReply(Buffer buffer)
prepareReply in class AbstractSftpSubsystemHelperprotected void send(Buffer buffer) throws java.io.IOException
send in class AbstractSftpSubsystemHelperjava.io.IOExceptionpublic void destroy(ChannelSession channel)
CommandLifecycledestroy in interface CommandLifecyclechannel - The ChannelSession through which the command has been receivedprotected void closeAllHandles()