* Makefile: Added new targets for running the tests. Now the generated
[mono.git] / mcs / class / System / System.Net.Sockets / NetworkStream.cs
1 //
2 // System.Net.Sockets.NetworkStream.cs
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //
7 // (C) 2002 Ximian, Inc. http://www.ximian.com
8 //
9
10 using System.IO;
11 using System.Runtime.InteropServices;
12
13 namespace System.Net.Sockets
14 {
15         public class NetworkStream : Stream, IDisposable {
16                 FileAccess access;
17                 Socket socket;
18                 bool owns_socket;
19                 bool readable, writeable;
20                 bool disposed = false;
21                 
22                 public NetworkStream (Socket socket)
23                         : this (socket, FileAccess.ReadWrite, false)
24                 {
25                 }
26
27                 public NetworkStream (Socket socket, bool owns_socket)
28                         : this (socket, FileAccess.ReadWrite, owns_socket)
29                 {
30                 }
31
32                 public NetworkStream (Socket socket, FileAccess access)
33                         : this (socket, access, false)
34                 {
35                 }
36                 
37                 public NetworkStream (Socket socket, FileAccess access, bool owns_socket)
38                 {
39                         if (socket == null)
40                                 throw new ArgumentNullException ("socket is null");
41                         if (!socket.Connected)
42                                 throw new ArgumentException ("Not connected", "socket");
43                         if (socket.SocketType != SocketType.Stream)
44                                 throw new ArgumentException ("Socket is not of type Stream", "socket");
45                         if (!socket.Blocking)
46                                 throw new IOException ();
47                         
48                         this.socket = socket;
49                         this.owns_socket = owns_socket;
50                         this.access = access;
51
52                         readable = CanRead;
53                         writeable = CanWrite;
54                 }
55
56                 public override bool CanRead {
57                         get {
58                                 return access == FileAccess.ReadWrite || access == FileAccess.Read;
59                         }
60                 }
61
62                 public override bool CanSeek {
63                         get {
64                                 // network sockets cant seek.
65                                 return false;
66                         }
67                 }
68
69                 public override bool CanWrite {
70                         get {
71                                 return access == FileAccess.ReadWrite || access == FileAccess.Write;
72                         }
73                 }
74
75                 public virtual bool DataAvailable {
76                         get {
77                                 CheckDisposed ();
78                                 return socket.Available > 0;
79                         }
80                 }
81
82                 public override long Length {
83                         get {
84                                 // Network sockets always throw an exception
85                                 throw new NotSupportedException ();
86                         }
87                 }
88
89                 public override long Position {
90                         get {
91                                 // Network sockets always throw an exception
92                                 throw new NotSupportedException ();
93                         }
94                         
95                         set {
96                                 // Network sockets always throw an exception
97                                 throw new NotSupportedException ();
98                         }
99                 }
100
101                 protected bool Readable {
102                         get {
103                                 return readable;
104                         }
105
106                         set {
107                                 readable = value;
108                         }
109                 }
110
111                 protected Socket Socket {
112                         get {
113                                 return socket;
114                         }
115                 }
116
117                 protected bool Writeable {
118                         get {
119                                 return writeable;
120                         }
121
122                         set {
123                                 writeable = value;
124                         }
125                 }
126
127                 public override IAsyncResult BeginRead (byte [] buffer, int offset, int size,
128                                                         AsyncCallback callback, object state)
129                 {
130                         CheckDisposed ();                               
131                         IAsyncResult retval;
132
133                         if (buffer == null)
134                                 throw new ArgumentNullException ("buffer is null");
135                         int len = buffer.Length;
136                         if(offset<0 || offset>len) {
137                                 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
138                         }
139                         if(size<0 || offset+size>len) {
140                                 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
141                         }
142
143                         try {
144                                 retval = socket.BeginReceive (buffer, offset, size, 0, callback, state);
145                         } catch {
146                                 throw new IOException ("BeginReceive failure");
147                         }
148
149                         return retval;
150                 }
151
152                 public override IAsyncResult BeginWrite (byte [] buffer, int offset, int size,
153                                                         AsyncCallback callback, object state)
154                 {
155                         CheckDisposed ();
156                         IAsyncResult retval;
157
158                         if (buffer == null)
159                                 throw new ArgumentNullException ("buffer is null");
160
161                         int len = buffer.Length;
162                         if(offset<0 || offset>len) {
163                                 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
164                         }
165                         if(size<0 || offset+size>len) {
166                                 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
167                         }
168
169                         try {
170                                 retval = socket.BeginSend (buffer, offset, size, 0, callback, state);
171                         } catch {
172                                 throw new IOException ("BeginWrite failure");
173                         }
174
175                         return retval;
176                 }
177
178                 ~NetworkStream ()
179                 {
180                         Dispose (false);
181                 }
182                 
183                 public override void Close ()
184                 {
185                         ((IDisposable) this).Dispose ();
186                 }
187
188                 protected virtual void Dispose (bool disposing)
189                 {
190                         if (disposed) 
191                                 return;
192                         disposed = true;
193                         
194                         if (owns_socket) {
195                                 Socket s = socket;
196                                 if (s != null)
197                                         s.Close ();
198                         }
199                         socket = null;
200                 }
201
202                 public override int EndRead (IAsyncResult ar)
203                 {
204                         CheckDisposed ();
205                         int res;
206
207                         if (ar == null)
208                                 throw new ArgumentNullException ("async result is null");
209
210                         try {
211                                 res = socket.EndReceive (ar);
212                         } catch (Exception e) {
213                                 throw new IOException ("EndRead failure", e);
214                         }
215                         return res;
216                 }
217
218                 public override void EndWrite (IAsyncResult ar)
219                 {
220                         CheckDisposed ();
221                         if (ar == null)
222                                 throw new ArgumentNullException ("async result is null");
223
224                         try {
225                                 socket.EndSend (ar);
226                         } catch (Exception e) {
227                                 throw new IOException ("EndWrite failure", e);
228                         }
229                 }
230
231                 public override void Flush ()
232                 {
233                         // network streams are non-buffered, this is a no-op
234                 }
235
236                 void IDisposable.Dispose ()
237                 {
238                         Dispose (true);
239                         GC.SuppressFinalize (this);
240                 }
241
242                 public override int Read ([In,Out] byte [] buffer, int offset, int size)
243                 {
244                         CheckDisposed ();
245                         int res;
246
247                         if (buffer == null)
248                                 throw new ArgumentNullException ("buffer is null");
249                         if(offset<0 || offset>buffer.Length) {
250                                 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
251                         }
252                         if(size < 0 || offset+size>buffer.Length) {
253                                 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
254                         }
255
256                         try {
257                                 res = socket.Receive (buffer, offset, size, 0);
258                         } catch (Exception e) {
259                                 throw new IOException ("Read failure", e);
260                         }
261                         
262                         return res;
263                 }
264
265                 public override long Seek (long offset, SeekOrigin origin)
266                 {
267                         // NetworkStream objects do not support seeking.
268                         
269                         throw new NotSupportedException ();
270                 }
271
272                 public override void SetLength (long value)
273                 {
274                         // NetworkStream objects do not support SetLength
275                         
276                         throw new NotSupportedException ();
277                 }
278
279                 public override void Write (byte [] buffer, int offset, int size)
280                 {
281                         CheckDisposed ();
282                         if (buffer == null)
283                                 throw new ArgumentNullException ("buffer");
284
285                         if (offset < 0 || offset > buffer.Length)
286                                 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
287
288                         if (size < 0 || size > buffer.Length - offset)
289                                 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
290
291                         try {
292                                 socket.Send (buffer, offset, size, 0);
293                         } catch (Exception e) {
294                                 throw new IOException ("Write failure", e); 
295                         }
296                 }
297                 
298                 private void CheckDisposed ()
299                 {
300                         if (disposed)
301                                 throw new ObjectDisposedException (GetType().FullName);
302                 }               
303              
304         }
305 }