SftpSession
Represents an SFTP session.
using Renci.SshNet.Common;
using Renci.SshNet.Sftp.Requests;
using Renci.SshNet.Sftp.Responses;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Renci.SshNet.Sftp
{
internal sealed class SftpSession : SubsystemSession, ISftpSession, ISubsystemSession, IDisposable
{
internal const int MaximumSupportedVersion = 3;
private const int MinimumSupportedVersion = 0;
private readonly Dictionary<uint, SftpRequest> _requests = new Dictionary<uint, SftpRequest>();
private readonly ISftpResponseFactory _sftpResponseFactory;
private readonly List<byte> _data = new List<byte>(32768);
private readonly Encoding _encoding;
private EventWaitHandle _sftpVersionConfirmed = new AutoResetEvent(false);
private IDictionary<string, string> _supportedExtensions;
private long _requestId;
public string WorkingDirectory { get; set; }
public uint ProtocolVersion { get; set; }
public uint NextRequestId => (uint)Interlocked.Increment(ref _requestId);
public SftpSession(ISession session, int operationTimeout, Encoding encoding, ISftpResponseFactory sftpResponseFactory)
: base(session, "sftp", operationTimeout)
{
_encoding = encoding;
_sftpResponseFactory = sftpResponseFactory;
}
public void ChangeDirectory(string path)
{
string canonicalPath = GetCanonicalPath(path);
byte[] handle = RequestOpenDir(canonicalPath, false);
RequestClose(handle);
WorkingDirectory = canonicalPath;
}
internal void SendMessage(SftpMessage sftpMessage)
{
byte[] bytes = sftpMessage.GetBytes();
SendData(bytes);
}
public string GetCanonicalPath(string path)
{
string fullRemotePath = GetFullRemotePath(path);
string text = string.Empty;
KeyValuePair<string, SftpFileAttributes>[] array = RequestRealPath(fullRemotePath, true);
if (array != null)
text = array[0].Key;
if (!string.IsNullOrEmpty(text))
return text;
if (fullRemotePath.EndsWith("/.", StringComparison.OrdinalIgnoreCase) || fullRemotePath.EndsWith("/..", StringComparison.OrdinalIgnoreCase) || fullRemotePath.Equals("/", StringComparison.OrdinalIgnoreCase) || fullRemotePath.IndexOf('/', StringComparison.OrdinalIgnoreCase) < 0)
return fullRemotePath;
string[] array2 = fullRemotePath.Split('/', StringSplitOptions.None);
string text2 = string.Join('/', array2, 0, array2.Length - 1);
if (string.IsNullOrEmpty(text2))
text2 = "/";
array = RequestRealPath(text2, true);
if (array != null)
text = array[0].Key;
if (string.IsNullOrEmpty(text))
return fullRemotePath;
string arg = string.Empty;
if (text[text.Length - 1] != '/')
arg = "/";
return string.Format(CultureInfo.InvariantCulture, "{0}{1}{2}", text, arg, array2[array2.Length - 1]);
}
[AsyncStateMachine(typeof(<GetCanonicalPathAsync>d__23))]
public Task<string> GetCanonicalPathAsync(string path, CancellationToken cancellationToken)
{
<GetCanonicalPathAsync>d__23 stateMachine = default(<GetCanonicalPathAsync>d__23);
stateMachine.<>t__builder = AsyncTaskMethodBuilder<string>.Create();
stateMachine.<>4__this = this;
stateMachine.path = path;
stateMachine.cancellationToken = cancellationToken;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
public ISftpFileReader CreateFileReader(byte[] handle, ISftpSession sftpSession, uint chunkSize, int maxPendingReads, long? fileSize)
{
return new SftpFileReader(handle, sftpSession, chunkSize, maxPendingReads, fileSize);
}
internal string GetFullRemotePath(string path)
{
string result = path;
if (!string.IsNullOrEmpty(path) && path[0] != '/' && WorkingDirectory != null)
result = ((WorkingDirectory[WorkingDirectory.Length - 1] != '/') ? (WorkingDirectory + "/" + path) : (WorkingDirectory + path));
return result;
}
protected override void OnChannelOpen()
{
SendMessage(new SftpInitRequest(3));
WaitOnHandle(_sftpVersionConfirmed, base.OperationTimeout);
if (ProtocolVersion > 3)
throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Server SFTP version {0} is not supported.", ProtocolVersion));
WorkingDirectory = RequestRealPath(".", false)[0].Key;
}
protected override void OnDataReceived(byte[] data)
{
int num = 0;
int num2 = data.Length;
if (_data.Count == 0) {
while (num2 >= 5) {
int num3 = (data[num] << 24) | (data[num + 1] << 16) | (data[num + 2] << 8) | data[num + 3];
int num4 = num3 + 4;
if (num2 < num4)
break;
if (!TryLoadSftpMessage(data, num + 4, num3))
return;
num2 -= num4;
num += num4;
}
if (num2 != 0) {
if (num > 0) {
byte[] array = new byte[num2];
Buffer.BlockCopy(data, num, array, 0, num2);
_data.AddRange(array);
} else
_data.AddRange(data);
}
} else {
_data.AddRange(data);
while (_data.Count >= 5) {
int num5 = (_data[0] << 24) | (_data[1] << 16) | (_data[2] << 8) | _data[3];
int num6 = num5 + 4;
if (_data.Count < num6)
break;
byte[] array2 = new byte[num5];
_data.CopyTo(4, array2, 0, num5);
if (_data.Count == num6)
_data.Clear();
else
_data.RemoveRange(0, num6);
if (!TryLoadSftpMessage(array2, 0, num5))
break;
}
}
}
private bool TryLoadSftpMessage(byte[] packetData, int offset, int count)
{
SftpMessage sftpMessage = _sftpResponseFactory.Create(ProtocolVersion, packetData[offset], _encoding);
sftpMessage.Load(packetData, offset + 1, count - 1);
try {
SftpVersionResponse sftpVersionResponse = sftpMessage as SftpVersionResponse;
if (sftpVersionResponse != null) {
ProtocolVersion = sftpVersionResponse.Version;
_supportedExtensions = sftpVersionResponse.Extentions;
_sftpVersionConfirmed.Set();
} else
HandleResponse(sftpMessage as SftpResponse);
return true;
} catch (Exception error) {
RaiseError(error);
return false;
}
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing) {
EventWaitHandle sftpVersionConfirmed = _sftpVersionConfirmed;
if (sftpVersionConfirmed != null) {
_sftpVersionConfirmed = null;
sftpVersionConfirmed.Dispose();
}
}
}
private void SendRequest(SftpRequest request)
{
lock (_requests) {
_requests.Add(request.RequestId, request);
}
SendMessage(request);
}
public byte[] RequestOpen(string path, Flags flags, bool nullOnError = false)
{
byte[] handle = null;
SshException exception = null;
AutoResetEvent wait = new AutoResetEvent(false);
try {
SftpOpenRequest request = new SftpOpenRequest(ProtocolVersion, NextRequestId, path, _encoding, flags, delegate(SftpHandleResponse response) {
handle = response.Handle;
wait.Set();
}, delegate(SftpStatusResponse response) {
exception = GetSftpException(response);
wait.Set();
});
SendRequest(request);
WaitOnHandle(wait, base.OperationTimeout);
} finally {
if (wait != null)
((IDisposable)wait).Dispose();
}
if (!nullOnError && exception != null)
throw exception;
return handle;
}
[AsyncStateMachine(typeof(<RequestOpenAsync>d__32))]
public Task<byte[]> RequestOpenAsync(string path, Flags flags, CancellationToken cancellationToken)
{
<RequestOpenAsync>d__32 stateMachine = default(<RequestOpenAsync>d__32);
stateMachine.<>t__builder = AsyncTaskMethodBuilder<byte[]>.Create();
stateMachine.<>4__this = this;
stateMachine.path = path;
stateMachine.flags = flags;
stateMachine.cancellationToken = cancellationToken;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
public SftpOpenAsyncResult BeginOpen(string path, Flags flags, AsyncCallback callback, object state)
{
SftpOpenAsyncResult asyncResult = new SftpOpenAsyncResult(callback, state);
SftpOpenRequest request = new SftpOpenRequest(ProtocolVersion, NextRequestId, path, _encoding, flags, delegate(SftpHandleResponse response) {
asyncResult.SetAsCompleted(response.Handle, false);
}, delegate(SftpStatusResponse response) {
asyncResult.SetAsCompleted(GetSftpException(response), false);
});
SendRequest(request);
return asyncResult;
}
public byte[] EndOpen(SftpOpenAsyncResult asyncResult)
{
if (asyncResult == null)
throw new ArgumentNullException("asyncResult");
if (asyncResult.EndInvokeCalled)
throw new InvalidOperationException("EndOpen has already been called.");
if (asyncResult.IsCompleted)
return asyncResult.EndInvoke();
using (WaitHandle waitHandle = asyncResult.AsyncWaitHandle) {
WaitOnHandle(waitHandle, base.OperationTimeout);
return asyncResult.EndInvoke();
}
}
public void RequestClose(byte[] handle)
{
SshException exception = null;
AutoResetEvent wait = new AutoResetEvent(false);
try {
SftpCloseRequest request = new SftpCloseRequest(ProtocolVersion, NextRequestId, handle, delegate(SftpStatusResponse response) {
exception = GetSftpException(response);
wait.Set();
});
SendRequest(request);
WaitOnHandle(wait, base.OperationTimeout);
} finally {
if (wait != null)
((IDisposable)wait).Dispose();
}
if (exception != null)
throw exception;
}
[AsyncStateMachine(typeof(<RequestCloseAsync>d__36))]
public Task RequestCloseAsync(byte[] handle, CancellationToken cancellationToken)
{
<RequestCloseAsync>d__36 stateMachine = default(<RequestCloseAsync>d__36);
stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create();
stateMachine.<>4__this = this;
stateMachine.handle = handle;
stateMachine.cancellationToken = cancellationToken;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
public SftpCloseAsyncResult BeginClose(byte[] handle, AsyncCallback callback, object state)
{
SftpCloseAsyncResult asyncResult = new SftpCloseAsyncResult(callback, state);
SftpCloseRequest request = new SftpCloseRequest(ProtocolVersion, NextRequestId, handle, delegate(SftpStatusResponse response) {
asyncResult.SetAsCompleted(GetSftpException(response), false);
});
SendRequest(request);
return asyncResult;
}
public void EndClose(SftpCloseAsyncResult asyncResult)
{
if (asyncResult == null)
throw new ArgumentNullException("asyncResult");
if (asyncResult.EndInvokeCalled)
throw new InvalidOperationException("EndClose has already been called.");
if (asyncResult.IsCompleted)
asyncResult.EndInvoke();
else {
using (WaitHandle waitHandle = asyncResult.AsyncWaitHandle) {
WaitOnHandle(waitHandle, base.OperationTimeout);
asyncResult.EndInvoke();
}
}
}
public SftpReadAsyncResult BeginRead(byte[] handle, ulong offset, uint length, AsyncCallback callback, object state)
{
SftpReadAsyncResult asyncResult = new SftpReadAsyncResult(callback, state);
SftpReadRequest request = new SftpReadRequest(ProtocolVersion, NextRequestId, handle, offset, length, delegate(SftpDataResponse response) {
asyncResult.SetAsCompleted(response.Data, false);
}, delegate(SftpStatusResponse response) {
if (response.StatusCode != StatusCodes.Eof)
asyncResult.SetAsCompleted(GetSftpException(response), false);
else
asyncResult.SetAsCompleted(Array.Empty<byte>(), false);
});
SendRequest(request);
return asyncResult;
}
public byte[] EndRead(SftpReadAsyncResult asyncResult)
{
if (asyncResult == null)
throw new ArgumentNullException("asyncResult");
if (asyncResult.EndInvokeCalled)
throw new InvalidOperationException("EndRead has already been called.");
if (asyncResult.IsCompleted)
return asyncResult.EndInvoke();
using (WaitHandle waitHandle = asyncResult.AsyncWaitHandle) {
WaitOnHandle(waitHandle, base.OperationTimeout);
return asyncResult.EndInvoke();
}
}
public byte[] RequestRead(byte[] handle, ulong offset, uint length)
{
SshException exception = null;
byte[] data = null;
AutoResetEvent wait = new AutoResetEvent(false);
try {
SftpReadRequest request = new SftpReadRequest(ProtocolVersion, NextRequestId, handle, offset, length, delegate(SftpDataResponse response) {
data = response.Data;
wait.Set();
}, delegate(SftpStatusResponse response) {
if (response.StatusCode != StatusCodes.Eof)
exception = GetSftpException(response);
else
data = Array.Empty<byte>();
wait.Set();
});
SendRequest(request);
WaitOnHandle(wait, base.OperationTimeout);
} finally {
if (wait != null)
((IDisposable)wait).Dispose();
}
if (exception != null)
throw exception;
return data;
}
[AsyncStateMachine(typeof(<RequestReadAsync>d__42))]
public Task<byte[]> RequestReadAsync(byte[] handle, ulong offset, uint length, CancellationToken cancellationToken)
{
<RequestReadAsync>d__42 stateMachine = default(<RequestReadAsync>d__42);
stateMachine.<>t__builder = AsyncTaskMethodBuilder<byte[]>.Create();
stateMachine.<>4__this = this;
stateMachine.handle = handle;
stateMachine.offset = offset;
stateMachine.length = length;
stateMachine.cancellationToken = cancellationToken;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
public void RequestWrite(byte[] handle, ulong serverOffset, byte[] data, int offset, int length, AutoResetEvent wait, Action<SftpStatusResponse> writeCompleted = null)
{
SshException exception = null;
SftpWriteRequest request = new SftpWriteRequest(ProtocolVersion, NextRequestId, handle, serverOffset, data, offset, length, delegate(SftpStatusResponse response) {
writeCompleted?.Invoke(response);
exception = GetSftpException(response);
if (wait != null)
wait.Set();
});
SendRequest(request);
if (wait != null)
WaitOnHandle(wait, base.OperationTimeout);
if (exception != null)
throw exception;
}
[AsyncStateMachine(typeof(<RequestWriteAsync>d__44))]
public Task RequestWriteAsync(byte[] handle, ulong serverOffset, byte[] data, int offset, int length, CancellationToken cancellationToken)
{
<RequestWriteAsync>d__44 stateMachine = default(<RequestWriteAsync>d__44);
stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create();
stateMachine.<>4__this = this;
stateMachine.handle = handle;
stateMachine.serverOffset = serverOffset;
stateMachine.data = data;
stateMachine.offset = offset;
stateMachine.length = length;
stateMachine.cancellationToken = cancellationToken;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
public SftpFileAttributes RequestLStat(string path)
{
SshException exception = null;
SftpFileAttributes attributes = null;
AutoResetEvent wait = new AutoResetEvent(false);
try {
SftpLStatRequest request = new SftpLStatRequest(ProtocolVersion, NextRequestId, path, _encoding, delegate(SftpAttrsResponse response) {
attributes = response.Attributes;
wait.Set();
}, delegate(SftpStatusResponse response) {
exception = GetSftpException(response);
wait.Set();
});
SendRequest(request);
WaitOnHandle(wait, base.OperationTimeout);
} finally {
if (wait != null)
((IDisposable)wait).Dispose();
}
if (exception != null)
throw exception;
return attributes;
}
public SFtpStatAsyncResult BeginLStat(string path, AsyncCallback callback, object state)
{
SFtpStatAsyncResult asyncResult = new SFtpStatAsyncResult(callback, state);
SftpLStatRequest request = new SftpLStatRequest(ProtocolVersion, NextRequestId, path, _encoding, delegate(SftpAttrsResponse response) {
asyncResult.SetAsCompleted(response.Attributes, false);
}, delegate(SftpStatusResponse response) {
asyncResult.SetAsCompleted(GetSftpException(response), false);
});
SendRequest(request);
return asyncResult;
}
public SftpFileAttributes EndLStat(SFtpStatAsyncResult asyncResult)
{
if (asyncResult == null)
throw new ArgumentNullException("asyncResult");
if (asyncResult.EndInvokeCalled)
throw new InvalidOperationException("EndLStat has already been called.");
if (asyncResult.IsCompleted)
return asyncResult.EndInvoke();
using (WaitHandle waitHandle = asyncResult.AsyncWaitHandle) {
WaitOnHandle(waitHandle, base.OperationTimeout);
return asyncResult.EndInvoke();
}
}
public SftpFileAttributes RequestFStat(byte[] handle, bool nullOnError)
{
SshException exception = null;
SftpFileAttributes attributes = null;
AutoResetEvent wait = new AutoResetEvent(false);
try {
SftpFStatRequest request = new SftpFStatRequest(ProtocolVersion, NextRequestId, handle, delegate(SftpAttrsResponse response) {
attributes = response.Attributes;
wait.Set();
}, delegate(SftpStatusResponse response) {
exception = GetSftpException(response);
wait.Set();
});
SendRequest(request);
WaitOnHandle(wait, base.OperationTimeout);
} finally {
if (wait != null)
((IDisposable)wait).Dispose();
}
if (!nullOnError && exception != null)
throw exception;
return attributes;
}
[AsyncStateMachine(typeof(<RequestFStatAsync>d__49))]
public Task<SftpFileAttributes> RequestFStatAsync(byte[] handle, CancellationToken cancellationToken)
{
<RequestFStatAsync>d__49 stateMachine = default(<RequestFStatAsync>d__49);
stateMachine.<>t__builder = AsyncTaskMethodBuilder<SftpFileAttributes>.Create();
stateMachine.<>4__this = this;
stateMachine.handle = handle;
stateMachine.cancellationToken = cancellationToken;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
public void RequestSetStat(string path, SftpFileAttributes attributes)
{
SshException exception = null;
AutoResetEvent wait = new AutoResetEvent(false);
try {
SftpSetStatRequest request = new SftpSetStatRequest(ProtocolVersion, NextRequestId, path, _encoding, attributes, delegate(SftpStatusResponse response) {
exception = GetSftpException(response);
wait.Set();
});
SendRequest(request);
WaitOnHandle(wait, base.OperationTimeout);
} finally {
if (wait != null)
((IDisposable)wait).Dispose();
}
if (exception != null)
throw exception;
}
public void RequestFSetStat(byte[] handle, SftpFileAttributes attributes)
{
SshException exception = null;
AutoResetEvent wait = new AutoResetEvent(false);
try {
SftpFSetStatRequest request = new SftpFSetStatRequest(ProtocolVersion, NextRequestId, handle, attributes, delegate(SftpStatusResponse response) {
exception = GetSftpException(response);
wait.Set();
});
SendRequest(request);
WaitOnHandle(wait, base.OperationTimeout);
} finally {
if (wait != null)
((IDisposable)wait).Dispose();
}
if (exception != null)
throw exception;
}
public byte[] RequestOpenDir(string path, bool nullOnError = false)
{
SshException exception = null;
byte[] handle = null;
AutoResetEvent wait = new AutoResetEvent(false);
try {
SftpOpenDirRequest request = new SftpOpenDirRequest(ProtocolVersion, NextRequestId, path, _encoding, delegate(SftpHandleResponse response) {
handle = response.Handle;
wait.Set();
}, delegate(SftpStatusResponse response) {
exception = GetSftpException(response);
wait.Set();
});
SendRequest(request);
WaitOnHandle(wait, base.OperationTimeout);
} finally {
if (wait != null)
((IDisposable)wait).Dispose();
}
if (!nullOnError && exception != null)
throw exception;
return handle;
}
[AsyncStateMachine(typeof(<RequestOpenDirAsync>d__53))]
public Task<byte[]> RequestOpenDirAsync(string path, CancellationToken cancellationToken)
{
<RequestOpenDirAsync>d__53 stateMachine = default(<RequestOpenDirAsync>d__53);
stateMachine.<>t__builder = AsyncTaskMethodBuilder<byte[]>.Create();
stateMachine.<>4__this = this;
stateMachine.path = path;
stateMachine.cancellationToken = cancellationToken;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
public KeyValuePair<string, SftpFileAttributes>[] RequestReadDir(byte[] handle)
{
SshException exception = null;
KeyValuePair<string, SftpFileAttributes>[] result = null;
AutoResetEvent wait = new AutoResetEvent(false);
try {
SftpReadDirRequest request = new SftpReadDirRequest(ProtocolVersion, NextRequestId, handle, delegate(SftpNameResponse response) {
result = response.Files;
wait.Set();
}, delegate(SftpStatusResponse response) {
if (response.StatusCode != StatusCodes.Eof)
exception = GetSftpException(response);
wait.Set();
});
SendRequest(request);
WaitOnHandle(wait, base.OperationTimeout);
} finally {
if (wait != null)
((IDisposable)wait).Dispose();
}
if (exception != null)
throw exception;
return result;
}
[AsyncStateMachine(typeof(<RequestReadDirAsync>d__55))]
public Task<KeyValuePair<string, SftpFileAttributes>[]> RequestReadDirAsync(byte[] handle, CancellationToken cancellationToken)
{
<RequestReadDirAsync>d__55 stateMachine = default(<RequestReadDirAsync>d__55);
stateMachine.<>t__builder = AsyncTaskMethodBuilder<KeyValuePair<string, SftpFileAttributes>[]>.Create();
stateMachine.<>4__this = this;
stateMachine.handle = handle;
stateMachine.cancellationToken = cancellationToken;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
public void RequestRemove(string path)
{
SshException exception = null;
AutoResetEvent wait = new AutoResetEvent(false);
try {
SftpRemoveRequest request = new SftpRemoveRequest(ProtocolVersion, NextRequestId, path, _encoding, delegate(SftpStatusResponse response) {
exception = GetSftpException(response);
wait.Set();
});
SendRequest(request);
WaitOnHandle(wait, base.OperationTimeout);
} finally {
if (wait != null)
((IDisposable)wait).Dispose();
}
if (exception != null)
throw exception;
}
[AsyncStateMachine(typeof(<RequestRemoveAsync>d__57))]
public Task RequestRemoveAsync(string path, CancellationToken cancellationToken)
{
<RequestRemoveAsync>d__57 stateMachine = default(<RequestRemoveAsync>d__57);
stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create();
stateMachine.<>4__this = this;
stateMachine.path = path;
stateMachine.cancellationToken = cancellationToken;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
public void RequestMkDir(string path)
{
SshException exception = null;
AutoResetEvent wait = new AutoResetEvent(false);
try {
SftpMkDirRequest request = new SftpMkDirRequest(ProtocolVersion, NextRequestId, path, _encoding, delegate(SftpStatusResponse response) {
exception = GetSftpException(response);
wait.Set();
});
SendRequest(request);
WaitOnHandle(wait, base.OperationTimeout);
} finally {
if (wait != null)
((IDisposable)wait).Dispose();
}
if (exception != null)
throw exception;
}
public void RequestRmDir(string path)
{
SshException exception = null;
AutoResetEvent wait = new AutoResetEvent(false);
try {
SftpRmDirRequest request = new SftpRmDirRequest(ProtocolVersion, NextRequestId, path, _encoding, delegate(SftpStatusResponse response) {
exception = GetSftpException(response);
wait.Set();
});
SendRequest(request);
WaitOnHandle(wait, base.OperationTimeout);
} finally {
if (wait != null)
((IDisposable)wait).Dispose();
}
if (exception != null)
throw exception;
}
internal KeyValuePair<string, SftpFileAttributes>[] RequestRealPath(string path, bool nullOnError = false)
{
SshException exception = null;
KeyValuePair<string, SftpFileAttributes>[] result = null;
AutoResetEvent wait = new AutoResetEvent(false);
try {
SftpRealPathRequest request = new SftpRealPathRequest(ProtocolVersion, NextRequestId, path, _encoding, delegate(SftpNameResponse response) {
result = response.Files;
wait.Set();
}, delegate(SftpStatusResponse response) {
exception = GetSftpException(response);
wait.Set();
});
SendRequest(request);
WaitOnHandle(wait, base.OperationTimeout);
} finally {
if (wait != null)
((IDisposable)wait).Dispose();
}
if (!nullOnError && exception != null)
throw exception;
return result;
}
[AsyncStateMachine(typeof(<RequestRealPathAsync>d__61))]
internal Task<KeyValuePair<string, SftpFileAttributes>[]> RequestRealPathAsync(string path, bool nullOnError, CancellationToken cancellationToken)
{
<RequestRealPathAsync>d__61 stateMachine = default(<RequestRealPathAsync>d__61);
stateMachine.<>t__builder = AsyncTaskMethodBuilder<KeyValuePair<string, SftpFileAttributes>[]>.Create();
stateMachine.<>4__this = this;
stateMachine.path = path;
stateMachine.nullOnError = nullOnError;
stateMachine.cancellationToken = cancellationToken;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
public SftpRealPathAsyncResult BeginRealPath(string path, AsyncCallback callback, object state)
{
SftpRealPathAsyncResult asyncResult = new SftpRealPathAsyncResult(callback, state);
SftpRealPathRequest request = new SftpRealPathRequest(ProtocolVersion, NextRequestId, path, _encoding, delegate(SftpNameResponse response) {
asyncResult.SetAsCompleted(response.Files[0].Key, false);
}, delegate(SftpStatusResponse response) {
asyncResult.SetAsCompleted(GetSftpException(response), false);
});
SendRequest(request);
return asyncResult;
}
public string EndRealPath(SftpRealPathAsyncResult asyncResult)
{
if (asyncResult == null)
throw new ArgumentNullException("asyncResult");
if (asyncResult.EndInvokeCalled)
throw new InvalidOperationException("EndRealPath has already been called.");
if (asyncResult.IsCompleted)
return asyncResult.EndInvoke();
using (WaitHandle waitHandle = asyncResult.AsyncWaitHandle) {
WaitOnHandle(waitHandle, base.OperationTimeout);
return asyncResult.EndInvoke();
}
}
public SftpFileAttributes RequestStat(string path, bool nullOnError = false)
{
SshException exception = null;
SftpFileAttributes attributes = null;
AutoResetEvent wait = new AutoResetEvent(false);
try {
SftpStatRequest request = new SftpStatRequest(ProtocolVersion, NextRequestId, path, _encoding, delegate(SftpAttrsResponse response) {
attributes = response.Attributes;
wait.Set();
}, delegate(SftpStatusResponse response) {
exception = GetSftpException(response);
wait.Set();
});
SendRequest(request);
WaitOnHandle(wait, base.OperationTimeout);
} finally {
if (wait != null)
((IDisposable)wait).Dispose();
}
if (!nullOnError && exception != null)
throw exception;
return attributes;
}
public SFtpStatAsyncResult BeginStat(string path, AsyncCallback callback, object state)
{
SFtpStatAsyncResult asyncResult = new SFtpStatAsyncResult(callback, state);
SftpStatRequest request = new SftpStatRequest(ProtocolVersion, NextRequestId, path, _encoding, delegate(SftpAttrsResponse response) {
asyncResult.SetAsCompleted(response.Attributes, false);
}, delegate(SftpStatusResponse response) {
asyncResult.SetAsCompleted(GetSftpException(response), false);
});
SendRequest(request);
return asyncResult;
}
public SftpFileAttributes EndStat(SFtpStatAsyncResult asyncResult)
{
if (asyncResult == null)
throw new ArgumentNullException("asyncResult");
if (asyncResult.EndInvokeCalled)
throw new InvalidOperationException("EndStat has already been called.");
if (asyncResult.IsCompleted)
return asyncResult.EndInvoke();
using (WaitHandle waitHandle = asyncResult.AsyncWaitHandle) {
WaitOnHandle(waitHandle, base.OperationTimeout);
return asyncResult.EndInvoke();
}
}
public void RequestRename(string oldPath, string newPath)
{
if (ProtocolVersion < 2)
throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "SSH_FXP_RENAME operation is not supported in {0} version that server operates in.", ProtocolVersion));
SshException exception = null;
AutoResetEvent wait = new AutoResetEvent(false);
try {
SftpRenameRequest request = new SftpRenameRequest(ProtocolVersion, NextRequestId, oldPath, newPath, _encoding, delegate(SftpStatusResponse response) {
exception = GetSftpException(response);
wait.Set();
});
SendRequest(request);
WaitOnHandle(wait, base.OperationTimeout);
} finally {
if (wait != null)
((IDisposable)wait).Dispose();
}
if (exception != null)
throw exception;
}
[AsyncStateMachine(typeof(<RequestRenameAsync>d__68))]
public Task RequestRenameAsync(string oldPath, string newPath, CancellationToken cancellationToken)
{
<RequestRenameAsync>d__68 stateMachine = default(<RequestRenameAsync>d__68);
stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create();
stateMachine.<>4__this = this;
stateMachine.oldPath = oldPath;
stateMachine.newPath = newPath;
stateMachine.cancellationToken = cancellationToken;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
internal KeyValuePair<string, SftpFileAttributes>[] RequestReadLink(string path, bool nullOnError = false)
{
if (ProtocolVersion < 3)
throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "SSH_FXP_READLINK operation is not supported in {0} version that server operates in.", ProtocolVersion));
SshException exception = null;
KeyValuePair<string, SftpFileAttributes>[] result = null;
AutoResetEvent wait = new AutoResetEvent(false);
try {
SftpReadLinkRequest request = new SftpReadLinkRequest(ProtocolVersion, NextRequestId, path, _encoding, delegate(SftpNameResponse response) {
result = response.Files;
wait.Set();
}, delegate(SftpStatusResponse response) {
exception = GetSftpException(response);
wait.Set();
});
SendRequest(request);
WaitOnHandle(wait, base.OperationTimeout);
} finally {
if (wait != null)
((IDisposable)wait).Dispose();
}
if (!nullOnError && exception != null)
throw exception;
return result;
}
public void RequestSymLink(string linkpath, string targetpath)
{
if (ProtocolVersion < 3)
throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "SSH_FXP_SYMLINK operation is not supported in {0} version that server operates in.", ProtocolVersion));
SshException exception = null;
AutoResetEvent wait = new AutoResetEvent(false);
try {
SftpSymLinkRequest request = new SftpSymLinkRequest(ProtocolVersion, NextRequestId, linkpath, targetpath, _encoding, delegate(SftpStatusResponse response) {
exception = GetSftpException(response);
wait.Set();
});
SendRequest(request);
WaitOnHandle(wait, base.OperationTimeout);
} finally {
if (wait != null)
((IDisposable)wait).Dispose();
}
if (exception != null)
throw exception;
}
public void RequestPosixRename(string oldPath, string newPath)
{
if (ProtocolVersion < 3)
throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "SSH_FXP_EXTENDED operation is not supported in {0} version that server operates in.", ProtocolVersion));
SshException exception = null;
AutoResetEvent wait = new AutoResetEvent(false);
try {
PosixRenameRequest posixRenameRequest = new PosixRenameRequest(ProtocolVersion, NextRequestId, oldPath, newPath, _encoding, delegate(SftpStatusResponse response) {
exception = GetSftpException(response);
wait.Set();
});
if (!_supportedExtensions.ContainsKey(posixRenameRequest.Name))
throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Extension method {0} currently not supported by the server.", posixRenameRequest.Name));
SendRequest(posixRenameRequest);
WaitOnHandle(wait, base.OperationTimeout);
} finally {
if (wait != null)
((IDisposable)wait).Dispose();
}
if (exception != null)
throw exception;
}
public SftpFileSystemInformation RequestStatVfs(string path, bool nullOnError = false)
{
if (ProtocolVersion < 3)
throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "SSH_FXP_EXTENDED operation is not supported in {0} version that server operates in.", ProtocolVersion));
SshException exception = null;
SftpFileSystemInformation information = null;
AutoResetEvent wait = new AutoResetEvent(false);
try {
StatVfsRequest statVfsRequest = new StatVfsRequest(ProtocolVersion, NextRequestId, path, _encoding, delegate(SftpExtendedReplyResponse response) {
information = response.GetReply<StatVfsReplyInfo>().Information;
wait.Set();
}, delegate(SftpStatusResponse response) {
exception = GetSftpException(response);
wait.Set();
});
if (!_supportedExtensions.ContainsKey(statVfsRequest.Name))
throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Extension method {0} currently not supported by the server.", statVfsRequest.Name));
SendRequest(statVfsRequest);
WaitOnHandle(wait, base.OperationTimeout);
} finally {
if (wait != null)
((IDisposable)wait).Dispose();
}
if (!nullOnError && exception != null)
throw exception;
return information;
}
[AsyncStateMachine(typeof(<RequestStatVfsAsync>d__73))]
public Task<SftpFileSystemInformation> RequestStatVfsAsync(string path, CancellationToken cancellationToken)
{
<RequestStatVfsAsync>d__73 stateMachine = default(<RequestStatVfsAsync>d__73);
stateMachine.<>t__builder = AsyncTaskMethodBuilder<SftpFileSystemInformation>.Create();
stateMachine.<>4__this = this;
stateMachine.path = path;
stateMachine.cancellationToken = cancellationToken;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
internal SftpFileSystemInformation RequestFStatVfs(byte[] handle, bool nullOnError = false)
{
if (ProtocolVersion < 3)
throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "SSH_FXP_EXTENDED operation is not supported in {0} version that server operates in.", ProtocolVersion));
SshException exception = null;
SftpFileSystemInformation information = null;
AutoResetEvent wait = new AutoResetEvent(false);
try {
FStatVfsRequest fStatVfsRequest = new FStatVfsRequest(ProtocolVersion, NextRequestId, handle, delegate(SftpExtendedReplyResponse response) {
information = response.GetReply<StatVfsReplyInfo>().Information;
wait.Set();
}, delegate(SftpStatusResponse response) {
exception = GetSftpException(response);
wait.Set();
});
if (!_supportedExtensions.ContainsKey(fStatVfsRequest.Name))
throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Extension method {0} currently not supported by the server.", fStatVfsRequest.Name));
SendRequest(fStatVfsRequest);
WaitOnHandle(wait, base.OperationTimeout);
} finally {
if (wait != null)
((IDisposable)wait).Dispose();
}
if (!nullOnError && exception != null)
throw exception;
return information;
}
internal void HardLink(string oldPath, string newPath)
{
if (ProtocolVersion < 3)
throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "SSH_FXP_EXTENDED operation is not supported in {0} version that server operates in.", ProtocolVersion));
SshException exception = null;
AutoResetEvent wait = new AutoResetEvent(false);
try {
HardLinkRequest hardLinkRequest = new HardLinkRequest(ProtocolVersion, NextRequestId, oldPath, newPath, delegate(SftpStatusResponse response) {
exception = GetSftpException(response);
wait.Set();
});
if (!_supportedExtensions.ContainsKey(hardLinkRequest.Name))
throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Extension method {0} currently not supported by the server.", hardLinkRequest.Name));
SendRequest(hardLinkRequest);
WaitOnHandle(wait, base.OperationTimeout);
} finally {
if (wait != null)
((IDisposable)wait).Dispose();
}
if (exception != null)
throw exception;
}
public uint CalculateOptimalReadLength(uint bufferSize)
{
uint localPacketSize = base.Channel.LocalPacketSize;
return Math.Min(bufferSize, localPacketSize) - 13;
}
public uint CalculateOptimalWriteLength(uint bufferSize, byte[] handle)
{
uint num = (uint)(25 + handle.Length);
uint remotePacketSize = base.Channel.RemotePacketSize;
return Math.Min(bufferSize, remotePacketSize) - num;
}
private static SshException GetSftpException(SftpStatusResponse response)
{
switch (response.StatusCode) {
case StatusCodes.Ok:
return null;
case StatusCodes.PermissionDenied:
return new SftpPermissionDeniedException(response.ErrorMessage);
case StatusCodes.NoSuchFile:
return new SftpPathNotFoundException(response.ErrorMessage);
default:
return new SshException(response.ErrorMessage);
}
}
private void HandleResponse(SftpResponse response)
{
SftpRequest value;
lock (_requests) {
_requests.TryGetValue(response.ResponseId, out value);
if (value != null)
_requests.Remove(response.ResponseId);
}
if (value == null)
throw new InvalidOperationException("Invalid response.");
value.Complete(response);
}
}
}