2 // System.Net.Sockets.NetworkStream.cs
5 // Miguel de Icaza (miguel@ximian.com)
6 // Sridhar Kulkarni <sridharkulkarni@gmail.com>
8 // (C) 2002 Ximian, Inc. http://www.ximian.com
9 // Copyright (C) 2002-2006 Novell, Inc. http://www.novell.com
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System.Runtime.InteropServices;
35 #if NET_2_0 && !NET_2_1
37 using System.Threading;
40 namespace System.Net.Sockets
42 public class NetworkStream : Stream, IDisposable {
46 bool readable, writeable;
47 bool disposed = false;
49 public NetworkStream (Socket socket)
50 : this (socket, FileAccess.ReadWrite, false)
54 public NetworkStream (Socket socket, bool owns_socket)
55 : this (socket, FileAccess.ReadWrite, owns_socket)
59 public NetworkStream (Socket socket, FileAccess access)
60 : this (socket, access, false)
64 public NetworkStream (Socket socket, FileAccess access, bool owns_socket)
67 throw new ArgumentNullException ("socket is null");
68 if (socket.SocketType != SocketType.Stream)
69 throw new ArgumentException ("Socket is not of type Stream", "socket");
70 if (!socket.Connected)
71 throw new IOException ("Not connected");
73 throw new IOException ("Operation not allowed on a non-blocking socket.");
76 this.owns_socket = owns_socket;
83 public override bool CanRead {
85 return access == FileAccess.ReadWrite || access == FileAccess.Read;
89 public override bool CanSeek {
91 // network sockets cant seek.
97 public override bool CanTimeout
105 public override bool CanWrite {
107 return access == FileAccess.ReadWrite || access == FileAccess.Write;
111 public virtual bool DataAvailable {
114 return socket.Available > 0;
118 public override long Length {
120 // Network sockets always throw an exception
121 throw new NotSupportedException ();
125 public override long Position {
127 // Network sockets always throw an exception
128 throw new NotSupportedException ();
132 // Network sockets always throw an exception
133 throw new NotSupportedException ();
137 protected bool Readable {
147 #if NET_2_0 && !NET_2_1
149 [MonoNotSupported ("Not supported since Socket.ReceiveTimeout is not supported")]
151 public override int ReadTimeout
154 return(socket.ReceiveTimeout);
157 if (value <= 0 && value != Timeout.Infinite) {
158 throw new ArgumentOutOfRangeException ("value", "The value specified is less than or equal to zero and is not Infinite.");
161 socket.ReceiveTimeout = value;
166 protected Socket Socket {
172 protected bool Writeable {
182 #if NET_2_0 && !NET_2_1
184 [MonoNotSupported ("Not supported since Socket.SendTimeout is not supported")]
186 public override int WriteTimeout
189 return(socket.SendTimeout);
192 if (value <= 0 && value != Timeout.Infinite) {
193 throw new ArgumentOutOfRangeException ("value", "The value specified is less than or equal to zero and is not Infinite");
196 socket.SendTimeout = value;
201 public override IAsyncResult BeginRead (byte [] buffer, int offset, int size,
202 AsyncCallback callback, object state)
208 throw new ArgumentNullException ("buffer is null");
209 int len = buffer.Length;
210 if(offset<0 || offset>len) {
211 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
213 if(size<0 || offset+size>len) {
214 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
218 retval = socket.BeginReceive (buffer, offset, size, 0, callback, state);
219 } catch (Exception e) {
220 throw new IOException ("BeginReceive failure", e);
226 public override IAsyncResult BeginWrite (byte [] buffer, int offset, int size,
227 AsyncCallback callback, object state)
233 throw new ArgumentNullException ("buffer is null");
235 int len = buffer.Length;
236 if(offset<0 || offset>len) {
237 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
239 if(size<0 || offset+size>len) {
240 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
244 retval = socket.BeginSend (buffer, offset, size, 0, callback, state);
246 throw new IOException ("BeginWrite failure");
258 public override void Close ()
260 ((IDisposable) this).Dispose ();
264 #if NET_2_0 && !NET_2_1
265 public void Close (int timeout)
268 throw new ArgumentOutOfRangeException ("timeout", "timeout is less than -1");
271 System.Timers.Timer close_timer = new System.Timers.Timer ();
272 close_timer.Elapsed += new ElapsedEventHandler (OnTimeoutClose);
273 /* NB timeout is in milliseconds here, cf
274 * seconds in Socket.Close(int)
276 close_timer.Interval = timeout;
277 close_timer.AutoReset = false;
278 close_timer.Enabled = true;
281 private void OnTimeoutClose (object source, ElapsedEventArgs e)
293 void Dispose (bool disposing)
308 GC.SuppressFinalize (this);
311 public override int EndRead (IAsyncResult ar)
317 throw new ArgumentNullException ("async result is null");
320 res = socket.EndReceive (ar);
321 } catch (Exception e) {
322 throw new IOException ("EndRead failure", e);
327 public override void EndWrite (IAsyncResult ar)
331 throw new ArgumentNullException ("async result is null");
335 } catch (Exception e) {
336 throw new IOException ("EndWrite failure", e);
340 public override void Flush ()
342 // network streams are non-buffered, this is a no-op
346 void IDisposable.Dispose ()
352 public override int Read ([In,Out] byte [] buffer, int offset, int size)
358 throw new ArgumentNullException ("buffer is null");
359 if(offset<0 || offset>buffer.Length) {
360 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
362 if(size < 0 || offset+size>buffer.Length) {
363 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
367 res = socket.Receive (buffer, offset, size, 0);
368 } catch (Exception e) {
369 throw new IOException ("Read failure", e);
375 public override long Seek (long offset, SeekOrigin origin)
377 // NetworkStream objects do not support seeking.
379 throw new NotSupportedException ();
382 public override void SetLength (long value)
384 // NetworkStream objects do not support SetLength
386 throw new NotSupportedException ();
389 public override void Write (byte [] buffer, int offset, int size)
393 throw new ArgumentNullException ("buffer");
395 if (offset < 0 || offset > buffer.Length)
396 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
398 if (size < 0 || size > buffer.Length - offset)
399 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
403 while (size - count > 0) {
404 count += socket.Send (buffer, offset + count, size - count, 0);
406 } catch (Exception e) {
407 throw new IOException ("Write failure", e);
411 private void CheckDisposed ()
414 throw new ObjectDisposedException (GetType().FullName);
418 public void ChangeToSSLSocket()
420 socket.ChangeToSSL();