FtpDataStream.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. //
  2. // System.Net.FtpDataStream.cs
  3. //
  4. // Authors:
  5. // Carlos Alberto Cortez ([email protected])
  6. //
  7. // (c) Copyright 2006 Novell, Inc. (http://www.novell.com)
  8. //
  9. using System;
  10. using System.IO;
  11. using System.Net.Sockets;
  12. using System.Runtime.Remoting.Messaging;
  13. using System.Threading;
  14. using System.Net;
  15. #if NET_2_0
  16. namespace System.Net
  17. {
  18. class FtpDataStream : Stream, IDisposable
  19. {
  20. FtpWebRequest request;
  21. NetworkStream networkStream;
  22. bool disposed;
  23. bool isRead;
  24. int totalRead;
  25. int contentLength;
  26. ManualResetEvent closewh;
  27. internal FtpDataStream (FtpWebRequest request, Socket socket, bool isRead)
  28. {
  29. if (request == null)
  30. throw new ArgumentNullException ("request");
  31. if (socket == null)
  32. throw new ArgumentNullException ("socket");
  33. if (!socket.Connected)
  34. throw new ArgumentException ("socket");
  35. this.request = request;
  36. this.contentLength = socket.Available;
  37. this.networkStream = new NetworkStream (socket, true);
  38. this.isRead = isRead;
  39. if (request.EnableSsl) {
  40. FtpWebRequest.ChangeToSSLSocket (ref networkStream);
  41. }
  42. closewh = new ManualResetEvent (false);
  43. }
  44. public override bool CanRead {
  45. get {
  46. return isRead;
  47. }
  48. }
  49. public override bool CanWrite {
  50. get {
  51. return !isRead;
  52. }
  53. }
  54. public override bool CanSeek {
  55. get {
  56. return false;
  57. }
  58. }
  59. public override long Length {
  60. get {
  61. throw new NotSupportedException ();
  62. }
  63. }
  64. public override long Position {
  65. get {
  66. throw new NotSupportedException ();
  67. }
  68. set {
  69. throw new NotSupportedException ();
  70. }
  71. }
  72. internal NetworkStream NetworkStream {
  73. get {
  74. CheckDisposed ();
  75. return networkStream;
  76. }
  77. }
  78. public override void Close ()
  79. {
  80. if (!disposed) {
  81. networkStream.Close ();
  82. request.SetTransferCompleted ();
  83. ((IDisposable) this).Dispose ();
  84. }
  85. }
  86. public override void Flush ()
  87. {
  88. // Do nothing.
  89. }
  90. public override long Seek (long offset, SeekOrigin origin)
  91. {
  92. throw new NotSupportedException ();
  93. }
  94. public override void SetLength (long value)
  95. {
  96. throw new NotSupportedException ();
  97. }
  98. int ReadInternal (byte [] buffer, int offset, int size)
  99. {
  100. int nbytes;
  101. request.CheckIfAborted ();
  102. try {
  103. // Probably it would be better to have the socket here
  104. nbytes = networkStream.Read (buffer, offset, size);
  105. } catch (IOException) {
  106. throw new ProtocolViolationException ("Server commited a protocol violation");
  107. }
  108. totalRead += nbytes;
  109. if (nbytes == 0) {
  110. contentLength = totalRead;
  111. request.SetTransferCompleted ();
  112. networkStream.Close ();
  113. }
  114. return nbytes;
  115. }
  116. public override IAsyncResult BeginRead (byte [] buffer, int offset, int size, AsyncCallback cb, object state)
  117. {
  118. CheckDisposed ();
  119. if (!isRead)
  120. throw new NotSupportedException ();
  121. if (buffer == null)
  122. throw new ArgumentNullException ("buffer");
  123. if (offset < 0 || offset > buffer.Length)
  124. throw new ArgumentOutOfRangeException ("offset");
  125. if (size < 0 || size > buffer.Length - offset)
  126. throw new ArgumentOutOfRangeException ("offset+size");
  127. ReadDelegate del = ReadInternal;
  128. return del.BeginInvoke (buffer, offset, size, cb, state);
  129. }
  130. public override int EndRead (IAsyncResult asyncResult)
  131. {
  132. if (asyncResult == null)
  133. throw new ArgumentNullException ("asyncResult");
  134. AsyncResult ar = asyncResult as AsyncResult;
  135. if (ar == null)
  136. throw new ArgumentException ("Invalid asyncResult", "asyncResult");
  137. ReadDelegate del = ar.AsyncDelegate as ReadDelegate;
  138. if (del == null)
  139. throw new ArgumentException ("Invalid asyncResult", "asyncResult");
  140. return del.EndInvoke (asyncResult);
  141. }
  142. public override int Read (byte [] buffer, int offset, int size)
  143. {
  144. request.CheckIfAborted ();
  145. IAsyncResult ar = BeginRead (buffer, offset, size, null, null);
  146. if (!ar.IsCompleted && !ar.AsyncWaitHandle.WaitOne (request.ReadWriteTimeout, false))
  147. throw new WebException ("Read timed out.", WebExceptionStatus.Timeout);
  148. return EndRead (ar);
  149. }
  150. delegate void WriteDelegate (byte [] buffer, int offset, int size);
  151. void WriteInternal (byte [] buffer, int offset, int size)
  152. {
  153. request.CheckIfAborted ();
  154. try {
  155. networkStream.Write (buffer, offset, size);
  156. } catch (IOException) {
  157. throw new ProtocolViolationException ();
  158. }
  159. }
  160. public override IAsyncResult BeginWrite (byte [] buffer, int offset, int size, AsyncCallback cb, object state)
  161. {
  162. CheckDisposed ();
  163. if (isRead)
  164. throw new NotSupportedException ();
  165. if (buffer == null)
  166. throw new ArgumentNullException ("buffer");
  167. if (offset < 0 || offset > buffer.Length)
  168. throw new ArgumentOutOfRangeException ("offset");
  169. if (size < 0 || size > buffer.Length - offset)
  170. throw new ArgumentOutOfRangeException ("offset+size");
  171. WriteDelegate del = WriteInternal;
  172. return del.BeginInvoke (buffer, offset, size, cb, state);
  173. }
  174. public override void EndWrite (IAsyncResult asyncResult)
  175. {
  176. if (asyncResult == null)
  177. throw new ArgumentNullException ("asyncResult");
  178. AsyncResult ar = asyncResult as AsyncResult;
  179. if (ar == null)
  180. throw new ArgumentException ("Invalid asyncResult.", "asyncResult");
  181. WriteDelegate del = ar.AsyncDelegate as WriteDelegate;
  182. if (del == null)
  183. throw new ArgumentException ("Invalid asyncResult.", "asyncResult");
  184. del.EndInvoke (asyncResult);
  185. }
  186. public override void Write (byte [] buffer, int offset, int size)
  187. {
  188. request.CheckIfAborted ();
  189. IAsyncResult ar = BeginWrite (buffer, offset, size, null, null);
  190. if (!ar.IsCompleted && !ar.AsyncWaitHandle.WaitOne (request.ReadWriteTimeout, false))
  191. throw new WebException ("Read timed out.", WebExceptionStatus.Timeout);
  192. EndWrite (ar);
  193. }
  194. ~FtpDataStream ()
  195. {
  196. Dispose (false);
  197. }
  198. void IDisposable.Dispose ()
  199. {
  200. Dispose (true);
  201. GC.SuppressFinalize (this);
  202. }
  203. protected override void Dispose (bool disposing)
  204. {
  205. if (disposed)
  206. return;
  207. disposed = true;
  208. networkStream.Close ();
  209. networkStream = null;
  210. closewh.Set ();
  211. }
  212. void CheckDisposed ()
  213. {
  214. if (disposed)
  215. throw new ObjectDisposedException (GetType ().FullName);
  216. }
  217. delegate int ReadDelegate (byte [] buffer, int offset, int size);
  218. // We need to know whether the stream has been closed
  219. internal ManualResetEvent CloseWaitHandle {
  220. get {
  221. return closewh;
  222. }
  223. }
  224. }
  225. }
  226. #endif