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