//****************************************************************************************************** // FtpDataStream.cs - Gbtc // // Copyright © 2012, Grid Protection Alliance. All Rights Reserved. // // Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See // the NOTICE file distributed with this work for additional information regarding copyright ownership. // The GPA licenses this file to you under the MIT License (MIT), the "License"; you may // not use this file except in compliance with the License. You may obtain a copy of the License at: // // http://www.opensource.org/licenses/MIT // // Unless agreed to in writing, the subject software distributed under the License is distributed on an // "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the // License for the specific language governing permissions and limitations. // // Code Modification History: // ---------------------------------------------------------------------------------------------------- // 05/22/2003 - J. Ritchie Carroll // Generated original version of source code. // 09/14/2009 - Stephen C. Wills // Added new header and license agreement. // 12/17/2012 - Starlynn Danyelle Gilliam // Modified Header. // //****************************************************************************************************** #region [ Contributor License Agreements ] //******************************************************************************************************* // // Code based on the following project: // http://www.codeproject.com/KB/IP/net_ftp_upload.aspx // // Copyright Alex Kwok & Uwe Keim // // The Code Project Open License (CPOL): // http://www.codeproject.com/info/cpol10.aspx // //******************************************************************************************************* #endregion using System.IO; using System.Net.Sockets; namespace GSF.Net.Ftp { /// /// FTP data stream. /// public class FtpDataStream : Stream { #region [ Members ] // Fields private readonly FtpControlChannel m_ctrl; private readonly FtpSessionConnected m_session; private TcpClient m_tcpClient; private readonly Stream m_stream; private bool m_userAbort; #endregion #region [ Constructors ] internal FtpDataStream(FtpControlChannel ctrl, TcpClient client) { m_session = ctrl.Session; m_ctrl = ctrl; m_tcpClient = client; m_stream = client.GetStream(); m_stream.ReadTimeout = ctrl.Timeout; m_stream.WriteTimeout = ctrl.Timeout; TryBeginDataTransfer(); } #endregion #region [ Properties ] internal bool IsClosed { get { return ((object)m_tcpClient == null); } } internal FtpControlChannel ControlChannel { get { return m_ctrl; } } /// /// Gets a value indicating whether the current stream supports reading. /// /// /// true if the stream supports reading; otherwise, false. /// public override bool CanRead { get { return m_stream.CanRead; } } /// /// Gets a value indicating whether the current stream supports seeking. /// /// /// true if the stream supports seeking; otherwise, false. /// public override bool CanSeek { get { return m_stream.CanSeek; } } /// /// Gets a value indicating whether the current stream supports writing. /// /// /// true if the stream supports writing; otherwise, false. /// public override bool CanWrite { get { return m_stream.CanWrite; } } /// /// Gets the length in bytes of the stream. /// /// /// A long value representing the length of the stream in bytes. /// /// Stream does not support seeking. /// Methods were called after the stream was closed. public override long Length { get { return m_stream.Length; } } /// /// Gets or sets the position within the current stream. /// /// /// The current position within the stream. /// /// An I/O error occurs. /// Stream does not support seeking. /// Methods were called after the stream was closed. public override long Position { get { return m_stream.Position; } set { m_stream.Position = value; } } #endregion #region [ Methods ] /// /// Closes the FTP stream and releases any resources associated with the stream. /// public override void Close() { Close(false); } internal void Close(bool error) { if (!IsClosed) { CloseConnection(); if (!error) m_ctrl.RefreshResponse(); m_ctrl.Session.EndDataTransfer(); } } internal void Abort() { m_userAbort = true; } private void CloseConnection() { m_stream.Close(); m_tcpClient.Close(); m_tcpClient = null; } /// /// Clears all buffers for this stream and causes any buffered data to be written to the underlying device. /// /// An I/O error occurs. public override void Flush() { m_stream.Flush(); } /// /// Sets the position within the current stream. /// /// A byte offset relative to the origin parameter. /// /// A value of type indicating the reference /// point used to obtain the new position. /// /// The new position within the current stream. /// An I/O error occurs. /// Stream does not support seeking. /// Methods were called after the stream was closed. public override long Seek(long offset, SeekOrigin origin) { return m_stream.Seek(offset, origin); } /// /// Reads a sequence of bytes from the current stream and advances the /// position within the stream by the number of bytes read. /// /// /// An array of bytes. When this method returns, the /// contains the specified byte array with the values between /// and ( + - 1) /// replaced by the bytes read from the current source. /// /// The zero-based byte offset in at which to begin /// storing the data read from the current stream. /// /// /// The maximum number of bytes to be read from the current stream. /// /// /// The total number of bytes read into the . This can be less than the /// number of bytes requested if that many bytes are not currently available, or zero (0) if the /// end of the stream has been reached. /// public override int Read(byte[] buffer, int offset, int count) { if (m_userAbort) throw new FtpUserAbortException(); return m_stream.Read(buffer, offset, count); } /// /// When overridden in a derived class, writes a sequence of bytes to the current stream and advances the current position /// within this stream by the number of bytes written. /// /// /// An array of bytes. When this method returns, the /// contains the specified byte array with the values between /// and ( + - 1) /// replaced by the bytes read from the current source. /// /// The zero-based byte offset in at which to begin /// storing the data read from the current stream. /// /// /// The maximum number of bytes to be read from the current stream. /// public override void Write(byte[] buffer, int offset, int count) { if (m_userAbort) throw new FtpUserAbortException(); m_stream.Write(buffer, offset, count); } /// /// Reads a byte from the stream and advances the position within the stream /// by one byte, or returns -1 if at the end of the stream. /// /// /// The unsigned byte cast to an Int32, or -1 if at the end of the stream. /// public override int ReadByte() { if (m_userAbort) throw new FtpUserAbortException(); return m_stream.ReadByte(); } /// /// Writes a byte to the current position in the stream and advances the position /// within the stream by one byte. /// /// The byte to write to the stream. public override void WriteByte(byte b) { if (m_userAbort) throw new FtpUserAbortException(); m_stream.WriteByte(b); } /// /// Sets the length of the current stream. /// /// The desired length of the current stream in bytes. public override void SetLength(long len) { m_stream.SetLength(len); } private void TryBeginDataTransfer() { try { m_session.BeginDataTransfer(this); } catch { CloseConnection(); throw; } } #endregion } }