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