The Labs \ Source Viewer \ SSCLI \ System.Net \ FtpDataStream

  1. // ------------------------------------------------------------------------------
  2. // <copyright file="FtpDataStream.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. // ------------------------------------------------------------------------------
  15. //
  16. namespace System.Net
  17. {
  18.    
  19.     using System.IO;
  20.     using System.Net.Sockets;
  21.     using System.Security.Permissions;
  22.    
  23.    
  24.     /// <devdoc>
  25.     /// <para>
  26.     /// The FtpDataStream class implements a data FTP connection,
  27.     /// </para>
  28.     /// </devdoc>
  29.     internal class FtpDataStream : Stream, ICloseEx
  30.     {
  31.        
  32.         private FtpWebRequest m_Request;
  33.         private NetworkStream m_NetworkStream;
  34.         private bool m_Writeable;
  35.         private bool m_Readable;
  36.         private bool m_IsFullyRead = false;
  37.         bool m_Closing = false;
  38.        
  39.        
  40.         internal FtpDataStream(NetworkStream networkStream, FtpWebRequest request, TriState writeOnly)
  41.         {
  42.             GlobalLog.Print("FtpDataStream#" + ValidationHelper.HashString(this) + "::FtpDataStream");
  43.             m_Readable = true;
  44.             m_Writeable = true;
  45.             if (writeOnly == TriState.True) {
  46.                 m_Readable = false;
  47.             }
  48.             else if (writeOnly == TriState.False) {
  49.                 m_Writeable = false;
  50.             }
  51.             m_NetworkStream = networkStream;
  52.             m_Request = request;
  53.         }
  54.        
  55.         protected override void Dispose(bool disposing)
  56.         {
  57.             try {
  58.                 if (disposing)
  59.                     ((ICloseEx)this).CloseEx(CloseExState.Normal);
  60.                 else
  61.                     ((ICloseEx)this).CloseEx(CloseExState.Abort | CloseExState.Silent);
  62.             }
  63.             finally {
  64.                 base.Dispose(disposing);
  65.             }
  66.         }
  67.        
  68.         void ICloseEx.CloseEx(CloseExState closeState)
  69.         {
  70.             GlobalLog.Print("FtpDataStream#" + ValidationHelper.HashString(this) + "::CloseEx, state = " + closeState.ToString());
  71.            
  72.             lock (this) {
  73.                 if (m_Closing == true)
  74.                     return;
  75.                 m_Closing = true;
  76.                 m_Writeable = false;
  77.                 m_Readable = false;
  78.             }
  79.            
  80.             try {
  81.                 try {
  82.                     if ((closeState & CloseExState.Abort) == 0)
  83.                         m_NetworkStream.Close(Socket.DefaultCloseTimeout);
  84.                     else
  85.                         m_NetworkStream.Close(0);
  86.                 }
  87.                 finally {
  88.                     m_Request.DataStreamClosed(closeState);
  89.                 }
  90.             }
  91.             catch (Exception exception) {
  92.                 bool doThrow = true;
  93.                 WebException webException = exception as WebException;
  94.                 if (webException != null) {
  95.                     FtpWebResponse response = webException.Response as FtpWebResponse;
  96.                     if (response != null) {
  97.                         if (!m_IsFullyRead && response.StatusCode == FtpStatusCode.ConnectionClosed)
  98.                             doThrow = false;
  99.                     }
  100.                 }
  101.                
  102.                 if (doThrow)
  103.                     if ((closeState & CloseExState.Silent) == 0)
  104.                         throw;
  105.             }
  106.         }
  107.        
  108.         /// <summary>
  109.         /// <para>Rethrows the exception</para>
  110.         /// </summary>
  111.         private void CheckError()
  112.         {
  113.             if (m_Request.Aborted) {
  114.                 throw new WebException(NetRes.GetWebStatusString("net_requestaborted", WebExceptionStatus.RequestCanceled), WebExceptionStatus.RequestCanceled);
  115.             }
  116.         }
  117.        
  118.        
  119.         /// <devdoc>
  120.         /// <para>Indicates that data can be read from the stream.
  121.         /// </devdoc>
  122.         public override bool CanRead {
  123.             get { return m_Readable; }
  124.         }
  125.        
  126.         /// <devdoc>
  127.         /// <para>Indicates that the stream is seekable</para>
  128.         /// </devdoc>
  129.         public override bool CanSeek {
  130.             get { return m_NetworkStream.CanSeek; }
  131.         }
  132.        
  133.        
  134.         /// <devdoc>
  135.         /// <para>Indicates that the stream is writeable</para>
  136.         /// </devdoc>
  137.         public override bool CanWrite {
  138.             get { return m_Writeable; }
  139.         }
  140.        
  141.         /// <devdoc>
  142.         /// <para>Indicates that the stream is writeable</para>
  143.         /// </devdoc>
  144.         public override long Length {
  145.             get { return m_NetworkStream.Length; }
  146.         }
  147.        
  148.         /// <devdoc>
  149.         /// <para>Gets or sets the position in the stream. Always throws <see cref='NotSupportedException'/>.</para>
  150.         /// </devdoc>
  151.         public override long Position {
  152.             get { return m_NetworkStream.Position; }
  153.            
  154.             set { m_NetworkStream.Position = value; }
  155.         }
  156.        
  157.         /// <devdoc>
  158.         /// <para>Seeks a specific position in the stream.</para>
  159.         /// </devdoc>
  160.         public override long Seek(long offset, SeekOrigin origin)
  161.         {
  162.             CheckError();
  163.             try {
  164.                 return m_NetworkStream.Seek(offset, origin);
  165.             }
  166.             catch {
  167.                 CheckError();
  168.                 throw;
  169.             }
  170.         }
  171.        
  172.        
  173.         /// <devdoc>
  174.         /// <para> Reads data from the stream. </para>
  175.         /// </devdoc>
  176.         public override int Read(byte[] buffer, int offset, int size)
  177.         {
  178.             CheckError();
  179.             int readBytes;
  180.             try {
  181.                 readBytes = m_NetworkStream.Read(buffer, offset, size);
  182.             }
  183.             catch {
  184.                 CheckError();
  185.                 throw;
  186.             }
  187.             if (readBytes == 0) {
  188.                 m_IsFullyRead = true;
  189.                 Close();
  190.             }
  191.             return readBytes;
  192.         }
  193.        
  194.        
  195.         /// <devdoc>
  196.         /// <para>Writes data to the stream.</para>
  197.         /// </devdoc>
  198.         public override void Write(byte[] buffer, int offset, int size)
  199.         {
  200.             CheckError();
  201.             try {
  202.                 m_NetworkStream.Write(buffer, offset, size);
  203.             }
  204.             catch {
  205.                 CheckError();
  206.                 throw;
  207.             }
  208.         }
  209.        
  210.        
  211.         private void AsyncReadCallback(IAsyncResult ar)
  212.         {
  213.             LazyAsyncResult userResult = (LazyAsyncResult)ar.AsyncState;
  214.             try {
  215.                 try {
  216.                     int readBytes = m_NetworkStream.EndRead(ar);
  217.                     if (readBytes == 0) {
  218.                         m_IsFullyRead = true;
  219.                         Close();
  220.                         // This should block for pipeline completion
  221.                     }
  222.                     userResult.InvokeCallback(readBytes);
  223.                 }
  224.                 catch (Exception exception) {
  225.                     // Complete with error. If already completed rethrow on the worker thread
  226.                     if (!userResult.IsCompleted)
  227.                         userResult.InvokeCallback(exception);
  228.                 }
  229.             }
  230.             catch {
  231.             }
  232.         }
  233.        
  234.         /// <devdoc>
  235.         /// <para>
  236.         /// Begins an asychronous read from a stream.
  237.         /// </para>
  238.         /// </devdoc>
  239.         [HostProtection(ExternalThreading = true)]
  240.         public override IAsyncResult BeginRead(byte[] buffer, int offset, int size, AsyncCallback callback, object state)
  241.         {
  242.             CheckError();
  243.             LazyAsyncResult userResult = new LazyAsyncResult(this, state, callback);
  244.             try {
  245.                 m_NetworkStream.BeginRead(buffer, offset, size, new AsyncCallback(AsyncReadCallback), userResult);
  246.             }
  247.             catch {
  248.                 CheckError();
  249.                 throw;
  250.             }
  251.             return userResult;
  252.         }
  253.        
  254.         /// <devdoc>
  255.         /// <para>
  256.         /// Handle the end of an asynchronous read.
  257.         /// </para>
  258.         /// </devdoc>
  259.         public override int EndRead(IAsyncResult ar)
  260.         {
  261.             try {
  262.                 object result = ((LazyAsyncResult)ar).InternalWaitForCompletion();
  263.                
  264.                 if (result is Exception)
  265.                     throw (Exception)result;
  266.                
  267.                 return (int)result;
  268.                
  269.             }
  270.             finally {
  271.                 CheckError();
  272.             }
  273.         }
  274.        
  275.         /// <devdoc>
  276.         /// <para>
  277.         /// Begins an asynchronous write to a stream.
  278.         /// </para>
  279.         /// </devdoc>
  280.         [HostProtection(ExternalThreading = true)]
  281.         public override IAsyncResult BeginWrite(byte[] buffer, int offset, int size, AsyncCallback callback, object state)
  282.         {
  283.             CheckError();
  284.             try {
  285.                 return m_NetworkStream.BeginWrite(buffer, offset, size, callback, state);
  286.             }
  287.             catch {
  288.                 CheckError();
  289.                 throw;
  290.             }
  291.         }
  292.        
  293.         /// <devdoc>
  294.         /// <para>
  295.         /// Handle the end of an asynchronous write.
  296.         /// </para>
  297.         /// </devdoc>
  298.         public override void EndWrite(IAsyncResult asyncResult)
  299.         {
  300.             try {
  301.                 m_NetworkStream.EndWrite(asyncResult);
  302.             }
  303.             finally {
  304.                 CheckError();
  305.             }
  306.         }
  307.        
  308.         /// <devdoc>
  309.         /// <para>
  310.         /// Flushes data from the stream.
  311.         /// </para>
  312.         /// </devdoc>
  313.         public override void Flush()
  314.         {
  315.             m_NetworkStream.Flush();
  316.         }
  317.        
  318.         /// <devdoc>
  319.         /// <para>
  320.         /// Sets the length of the stream. Always throws <see cref='NotSupportedException'/>
  321.         /// .
  322.         /// </para>
  323.         /// </devdoc>
  324.         public override void SetLength(long value)
  325.         {
  326.             m_NetworkStream.SetLength(value);
  327.         }
  328.        
  329.         /// <devdoc>
  330.         /// <para>Indicates whether we can timeout</para>
  331.         /// </devdoc>
  332.         public override bool CanTimeout {
  333.             get { return m_NetworkStream.CanTimeout; }
  334.         }
  335.        
  336.        
  337.         /// <devdoc>
  338.         /// <para>Set/Get ReadTimeout</para>
  339.         /// </devdoc>
  340.         public override int ReadTimeout {
  341.             get { return m_NetworkStream.ReadTimeout; }
  342.             set { m_NetworkStream.ReadTimeout = value; }
  343.         }
  344.        
  345.         /// <devdoc>
  346.         /// <para>Set/Get WriteTimeout</para>
  347.         /// </devdoc>
  348.         public override int WriteTimeout {
  349.             get { return m_NetworkStream.WriteTimeout; }
  350.             set { m_NetworkStream.WriteTimeout = value; }
  351.         }
  352.        
  353.         internal void SetSocketTimeoutOption(SocketShutdown mode, int timeout, bool silent)
  354.         {
  355.             m_NetworkStream.SetSocketTimeoutOption(mode, timeout, silent);
  356.         }
  357.     }
  358. }

Developer Fusion