|  | @@ -0,0 +1,580 @@
 | 
											
												
													
														|  | 
 |  | +using System;
 | 
											
												
													
														|  | 
 |  | +using System.Collections.Generic;
 | 
											
												
													
														|  | 
 |  | +using System.IO;
 | 
											
												
													
														|  | 
 |  | +using System.Linq;
 | 
											
												
													
														|  | 
 |  | +using System.Text;
 | 
											
												
													
														|  | 
 |  | +using System.Threading;
 | 
											
												
													
														|  | 
 |  | +using Renci.SshClient.Common;
 | 
											
												
													
														|  | 
 |  | +using Renci.SshClient.Messages.Sftp;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +namespace Renci.SshClient.Channels
 | 
											
												
													
														|  | 
 |  | +{
 | 
											
												
													
														|  | 
 |  | +    //  TODO:   Add Begin* and End* methods for async calls
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    internal class ChannelSessionSftp : ChannelSession
 | 
											
												
													
														|  | 
 |  | +    {
 | 
											
												
													
														|  | 
 |  | +        private EventWaitHandle _channelRequestSuccessWaitHandle = new AutoResetEvent(false);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        private EventWaitHandle _responseMessageReceivedWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        private uint _requestId;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        private SftpMessage _responseMessage;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        private string _remoteCurrentDir;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        private string _localCurentDir;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        private StringBuilder _packetData;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        //  TODO:   Repalce with SFTP specific async class if needed
 | 
											
												
													
														|  | 
 |  | +        private CommandAsyncResult _asyncResult;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        public ChannelSessionSftp()
 | 
											
												
													
														|  | 
 |  | +            : base()
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        public override void Open()
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            base.Open();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            //  Send channel command request
 | 
											
												
													
														|  | 
 |  | +            this.SendSubsystemRequest("sftp");
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            this.WaitHandle(this._channelRequestSuccessWaitHandle);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            this.SendMessage(new InitMessage
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                Version = 3,
 | 
											
												
													
														|  | 
 |  | +            });
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            var versionMessage = this.ReceiveMessage<VersionMessage>();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            if (versionMessage == null)
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                throw new InvalidOperationException("Version message expected.");
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            if (versionMessage.Version != 3)
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                throw new NotSupportedException(string.Format("Server SFTP version {0} is not supported.", versionMessage.Version));
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            //  Get default current directories
 | 
											
												
													
														|  | 
 |  | +            var files = this.GetRealPath(".");
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            this._remoteCurrentDir = files.First().Name;
 | 
											
												
													
														|  | 
 |  | +            this._localCurentDir = Directory.GetCurrentDirectory();
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        public void UploadFile(Stream source, string destination)
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            this.Open();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            string handle = string.Empty;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            try
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                handle = this.OpenRemoteFile(destination, Flags.Write | Flags.CreateNewOrOpen | Flags.Truncate);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +                var buffer = new byte[1024];
 | 
											
												
													
														|  | 
 |  | +                ulong offset = 0;
 | 
											
												
													
														|  | 
 |  | +                var bytesRead = 0;
 | 
											
												
													
														|  | 
 |  | +                while ((bytesRead = source.Read(buffer, 0, buffer.Length)) > 0)
 | 
											
												
													
														|  | 
 |  | +                {
 | 
											
												
													
														|  | 
 |  | +                    this.RemoteWrite(handle, offset, buffer.Take(bytesRead).GetSshString());
 | 
											
												
													
														|  | 
 |  | +                    offset += (ulong)buffer.Length;
 | 
											
												
													
														|  | 
 |  | +                }
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +            finally
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                if (!string.IsNullOrEmpty(handle))
 | 
											
												
													
														|  | 
 |  | +                    this.CloseRemoteHandle(handle);
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            this.Close();
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        internal void DownloadFile(string fileName, Stream destination)
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            this.Open();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            string handle = string.Empty;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            try
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                handle = this.OpenRemoteFile(fileName, Flags.Read);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +                ulong offset = 0;
 | 
											
												
													
														|  | 
 |  | +                uint bufferSize = 1024;
 | 
											
												
													
														|  | 
 |  | +                string data;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +                while ((data = this.RemoteRead(handle, offset, bufferSize)) != null)
 | 
											
												
													
														|  | 
 |  | +                {
 | 
											
												
													
														|  | 
 |  | +                    var fileData = data.GetSshBytes().ToArray();
 | 
											
												
													
														|  | 
 |  | +                    destination.Write(fileData, 0, fileData.Length);
 | 
											
												
													
														|  | 
 |  | +                    destination.Flush();
 | 
											
												
													
														|  | 
 |  | +                    offset += (ulong)fileData.Length;
 | 
											
												
													
														|  | 
 |  | +                }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +            finally
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                if (!string.IsNullOrEmpty(handle))
 | 
											
												
													
														|  | 
 |  | +                    this.CloseRemoteHandle(handle);
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            this.Close();
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        public void CreateDirectory(string directoryName)
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            this.Open();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            this.CreateRemoteDirectory(directoryName);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            this.Close();
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        public void RemoveDirectory(string directoryName)
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            this.Open();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            this.RemoveRemoteDirectory(directoryName);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            this.Close();
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        public void RemoveFile(string fileName)
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            this.Open();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            this.RemoveRemoteFile(fileName);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            this.Close();
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        public void RenameFile(string oldFileName, string newFileName)
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            this.Open();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            this.RenameRemoteFile(oldFileName, newFileName);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            this.Close();
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        public IEnumerable<FtpFileInfo> ListDirectory(string path)
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            //  Open channel
 | 
											
												
													
														|  | 
 |  | +            this.Open();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            string handle = string.Empty;
 | 
											
												
													
														|  | 
 |  | +            IEnumerable<FtpFileInfo> files = null;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            try
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                //  Open directory
 | 
											
												
													
														|  | 
 |  | +                handle = this.OpenRemoteDirectory(path);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +                //  Read directory data
 | 
											
												
													
														|  | 
 |  | +                files = this.ReadRemoteDirectory(handle);
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +            finally
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                //  Close directory
 | 
											
												
													
														|  | 
 |  | +                if (!string.IsNullOrEmpty(handle))
 | 
											
												
													
														|  | 
 |  | +                    this.CloseRemoteHandle(handle);
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            //  Read directory
 | 
											
												
													
														|  | 
 |  | +            this.Close();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            return files;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        protected override void OnSuccess()
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            base.OnSuccess();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            this._channelRequestSuccessWaitHandle.Set();
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        protected override void OnData(string data)
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            base.OnData(data);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            if (this._packetData == null)
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                var packetLength = (uint)(data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +                this._packetData = new StringBuilder((int)packetLength, (int)packetLength);
 | 
											
												
													
														|  | 
 |  | +                this._packetData.Append(data.GetSshBytes().Skip(4).GetSshString());
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +            else
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                this._packetData.Append(data);
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            if (this._packetData.Length < this._packetData.MaxCapacity)
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                //  Wait for more packet data
 | 
											
												
													
														|  | 
 |  | +                return;
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            dynamic sftpMessage = SftpMessage.Load(this._packetData.ToString().GetSshBytes());
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            this._packetData = null;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            if (sftpMessage.RequestId != null)
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                if (sftpMessage.RequestId != this._requestId)
 | 
											
												
													
														|  | 
 |  | +                {
 | 
											
												
													
														|  | 
 |  | +                    throw new InvalidOperationException("Invalid request id.");
 | 
											
												
													
														|  | 
 |  | +                }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +                this._requestId++;
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            this._responseMessage = sftpMessage;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            this._responseMessageReceivedWaitHandle.Set();
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        private T ReceiveMessage<T>() where T : SftpMessage
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            var message = this.ReceiveMessage() as T;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            if (message == null)
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                throw new InvalidOperationException(string.Format("Message of type '{0}' expected in this context.", typeof(T).Name));
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +            return message;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        private SftpMessage ReceiveMessage()
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            this.WaitHandle(this._responseMessageReceivedWaitHandle);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            var statusMessage = this._responseMessage as StatusMessage;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            if (statusMessage != null)
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                //  Handle error status messages
 | 
											
												
													
														|  | 
 |  | +                switch (statusMessage.StatusCode)
 | 
											
												
													
														|  | 
 |  | +                {
 | 
											
												
													
														|  | 
 |  | +                    case StatusCodes.Ok:
 | 
											
												
													
														|  | 
 |  | +                        break;
 | 
											
												
													
														|  | 
 |  | +                    case StatusCodes.Eof:
 | 
											
												
													
														|  | 
 |  | +                        break;
 | 
											
												
													
														|  | 
 |  | +                    case StatusCodes.NoSuchFile:
 | 
											
												
													
														|  | 
 |  | +                        throw new FileNotFoundException("File or directory not found on the remote server.");
 | 
											
												
													
														|  | 
 |  | +                    case StatusCodes.PermissionDenied:
 | 
											
												
													
														|  | 
 |  | +                        throw new NotImplementedException();
 | 
											
												
													
														|  | 
 |  | +                    case StatusCodes.Failure:
 | 
											
												
													
														|  | 
 |  | +                        throw new InvalidOperationException("Operation failed.");
 | 
											
												
													
														|  | 
 |  | +                    case StatusCodes.BadMessage:
 | 
											
												
													
														|  | 
 |  | +                        throw new NotImplementedException();
 | 
											
												
													
														|  | 
 |  | +                    case StatusCodes.NoConnection:
 | 
											
												
													
														|  | 
 |  | +                        throw new NotImplementedException();
 | 
											
												
													
														|  | 
 |  | +                    case StatusCodes.ConnectionLost:
 | 
											
												
													
														|  | 
 |  | +                        throw new NotImplementedException();
 | 
											
												
													
														|  | 
 |  | +                    case StatusCodes.OperationUnsupported:
 | 
											
												
													
														|  | 
 |  | +                        throw new NotSupportedException("Operation is not supported.");
 | 
											
												
													
														|  | 
 |  | +                    default:
 | 
											
												
													
														|  | 
 |  | +                        break;
 | 
											
												
													
														|  | 
 |  | +                }
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            return this._responseMessage;
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        private void SendMessage(SftpMessage sftpMessage)
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            sftpMessage.RequestId = this._requestId;
 | 
											
												
													
														|  | 
 |  | +            var message = new SftpDataMessage
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                LocalChannelNumber = this.RemoteChannelNumber,
 | 
											
												
													
														|  | 
 |  | +                Message = sftpMessage,
 | 
											
												
													
														|  | 
 |  | +            };
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            this.SendMessage(message);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            this._responseMessageReceivedWaitHandle.Reset();
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        private string OpenRemoteFile(string fileName, Flags flags)
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            this.SendMessage(new OpenMessage
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                Filename = fileName,
 | 
											
												
													
														|  | 
 |  | +                Flags = flags,
 | 
											
												
													
														|  | 
 |  | +            });
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            var handleMessage = this.ReceiveMessage<HandleMessage>();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            return handleMessage.Handle;
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        private string RemoteRead(string handle, ulong offset, uint length)
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            this.SendMessage(new ReadMessage
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                Handle = handle,
 | 
											
												
													
														|  | 
 |  | +                Offset = offset,
 | 
											
												
													
														|  | 
 |  | +                Length = length,
 | 
											
												
													
														|  | 
 |  | +            });
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            var message = this.ReceiveMessage();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            var statusMessage = message as StatusMessage;
 | 
											
												
													
														|  | 
 |  | +            var dataMessage = message as DataMessage;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            if (statusMessage != null)
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                if (statusMessage.StatusCode == StatusCodes.Eof)
 | 
											
												
													
														|  | 
 |  | +                {
 | 
											
												
													
														|  | 
 |  | +                    return null;
 | 
											
												
													
														|  | 
 |  | +                }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +                throw new InvalidOperationException("Invalid status code.");
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +            else if (dataMessage != null)
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                if (this._asyncResult != null)
 | 
											
												
													
														|  | 
 |  | +                {
 | 
											
												
													
														|  | 
 |  | +                    this._asyncResult.BytesReceived += dataMessage.Data.Length;
 | 
											
												
													
														|  | 
 |  | +                }
 | 
											
												
													
														|  | 
 |  | +                return dataMessage.Data;
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +            else
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                throw new InvalidOperationException(string.Format("Message type '{0}' is not valid in this context.", message.SftpMessageType));
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        private void RemoteWrite(string handle, ulong offset, string data)
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            this.SendMessage(new WriteMessage
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                Handle = handle,
 | 
											
												
													
														|  | 
 |  | +                Offset = offset,
 | 
											
												
													
														|  | 
 |  | +                Data = data,
 | 
											
												
													
														|  | 
 |  | +            });
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            var message = this.ReceiveMessage<StatusMessage>();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            this.EnsureStatusCode(message, StatusCodes.Ok);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            if (this._asyncResult != null)
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                this._asyncResult.BytesSent += data.Length;
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        private void RemoveRemoteFile(string fileName)
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            this.SendMessage(new RemoveMessage
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                Filename = fileName,
 | 
											
												
													
														|  | 
 |  | +            });
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            var message = this.ReceiveMessage<StatusMessage>();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            this.EnsureStatusCode(message, StatusCodes.Ok);
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        private void RenameRemoteFile(string oldFileName, string newFileName)
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            this.SendMessage(new RenameMessage
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                OldPath = oldFileName,
 | 
											
												
													
														|  | 
 |  | +                NewPath = newFileName,
 | 
											
												
													
														|  | 
 |  | +            });
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            var message = this.ReceiveMessage<StatusMessage>();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            this.EnsureStatusCode(message, StatusCodes.Ok);
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        private void CreateRemoteDirectory(string directoryName)
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            this.SendMessage(new MkDirMessage
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                Path = directoryName,
 | 
											
												
													
														|  | 
 |  | +            });
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            var message = this.ReceiveMessage<StatusMessage>();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            this.EnsureStatusCode(message, StatusCodes.Ok);
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        private void RemoveRemoteDirectory(string directoryName)
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            this.SendMessage(new RmDirMessage
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                Path = directoryName,
 | 
											
												
													
														|  | 
 |  | +            });
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            var message = this.ReceiveMessage<StatusMessage>();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            this.EnsureStatusCode(message, StatusCodes.Ok);
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        private string OpenRemoteDirectory(string path)
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            this.SendMessage(new OpenDirMessage
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                Path = path,
 | 
											
												
													
														|  | 
 |  | +            });
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            var handleMessage = this.ReceiveMessage<HandleMessage>();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            return handleMessage.Handle;
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        private IEnumerable<FtpFileInfo> ReadRemoteDirectory(string handle)
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            this.SendMessage(new ReadDirMessage
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                Handle = handle,
 | 
											
												
													
														|  | 
 |  | +            });
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            var message = this.ReceiveMessage<NameMessage>();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            return message.Files;
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        private void CloseRemoteHandle(string handle)
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            this.SendMessage(new CloseMessage
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                Handle = handle,
 | 
											
												
													
														|  | 
 |  | +            });
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            var status = this.ReceiveMessage<StatusMessage>();
 | 
											
												
													
														|  | 
 |  | +            var attempts = 0;
 | 
											
												
													
														|  | 
 |  | +            //  If close fails wait a litle a try to close it again, in case server flushed data into the file during close
 | 
											
												
													
														|  | 
 |  | +            while (status.StatusCode != StatusCodes.Ok && attempts++ < this.ConnectionInfo.RetryAttempts)
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                Thread.Sleep(50);
 | 
											
												
													
														|  | 
 |  | +                status = this.ReceiveMessage<StatusMessage>();
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            if (status.StatusCode != StatusCodes.Ok)
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                throw new InvalidOperationException(string.Format("File handle cannot be closed after {0} attempts.", attempts));
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        private Attributes GetRemoteFileAttributes(string filename)
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            this.SendMessage(new StatMessage
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                Path = filename,
 | 
											
												
													
														|  | 
 |  | +            });
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            var message = this.ReceiveMessage<AttrsMessage>();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            return message.Attributes;
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        private Attributes GetRemoteLinkFileAttributes(string filename)
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            this.SendMessage(new LStatMessage
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                Path = filename,
 | 
											
												
													
														|  | 
 |  | +            });
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            var message = this.ReceiveMessage<AttrsMessage>();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            return message.Attributes;
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        private Attributes GetRemoteOpenFileAttributes(string handle)
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            this.SendMessage(new FStatMessage
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                Handle = handle,
 | 
											
												
													
														|  | 
 |  | +            });
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            var message = this.ReceiveMessage<AttrsMessage>();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            return message.Attributes;
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        private void SetRemoteFileAttributes(string filename, Attributes attributes)
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            this.SendMessage(new SetStatMessage
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                Path = filename,
 | 
											
												
													
														|  | 
 |  | +                Attributes = attributes
 | 
											
												
													
														|  | 
 |  | +            });
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            var message = this.ReceiveMessage<StatusMessage>();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            this.EnsureStatusCode(message, StatusCodes.Ok);
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        private void SetRemoteOpenFileAttributes(string handle, Attributes attributes)
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            this.SendMessage(new FSetStatMessage
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                Handle = handle,
 | 
											
												
													
														|  | 
 |  | +                Attributes = attributes
 | 
											
												
													
														|  | 
 |  | +            });
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            var message = this.ReceiveMessage<StatusMessage>();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            this.EnsureStatusCode(message, StatusCodes.Ok);
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        private IEnumerable<FtpFileInfo> GetRealPath(string path)
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            this.SendMessage(new RealPathMessage
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                Path = path,
 | 
											
												
													
														|  | 
 |  | +            });
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            var message = this.ReceiveMessage<NameMessage>();
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            return message.Files;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        private void EnsureStatusCode(StatusMessage message, StatusCodes code)
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            if (message.StatusCode == code)
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                return;
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +            else
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                throw new InvalidOperationException("Invalid status code.");
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        #region IDisposable Members
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        protected override void OnDisposing()
 | 
											
												
													
														|  | 
 |  | +        {
 | 
											
												
													
														|  | 
 |  | +            // Dispose managed resources.
 | 
											
												
													
														|  | 
 |  | +            if (this._channelRequestSuccessWaitHandle != null)
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                this._channelRequestSuccessWaitHandle.Dispose();
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +            if (this._responseMessageReceivedWaitHandle != null)
 | 
											
												
													
														|  | 
 |  | +            {
 | 
											
												
													
														|  | 
 |  | +                this._responseMessageReceivedWaitHandle.Dispose();
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        #endregion
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +}
 |