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