Merge branch 'master' into msbuilddll2
[mono.git] / mcs / class / System / System.Net.Sockets / NetworkStream.cs
index c7ec9b71636880bd3da034955a62707285a52df7..f358c4dbbc399654319507f7ad65da186dd9835f 100644 (file)
@@ -3,8 +3,10 @@
 //
 // Author:
 //   Miguel de Icaza (miguel@ximian.com)
+//   Sridhar Kulkarni <sridharkulkarni@gmail.com>
 //
 // (C) 2002 Ximian, Inc. http://www.ximian.com
+// Copyright (C) 2002-2006 Novell, Inc.  http://www.novell.com
 //
 
 //
 
 using System.IO;
 using System.Runtime.InteropServices;
+#if !NET_2_1 || MOBILE
+using System.Timers;
+using System.Threading;
+#endif
 
 namespace System.Net.Sockets
 {
@@ -45,8 +51,8 @@ namespace System.Net.Sockets
                {
                }
 
-               public NetworkStream (Socket socket, bool owns_socket)
-                       : this (socket, FileAccess.ReadWrite, owns_socket)
+               public NetworkStream (Socket socket, bool ownsSocket)
+                       : this (socket, FileAccess.ReadWrite, ownsSocket)
                {
                }
 
@@ -55,19 +61,19 @@ namespace System.Net.Sockets
                {
                }
                
-               public NetworkStream (Socket socket, FileAccess access, bool owns_socket)
+               public NetworkStream (Socket socket, FileAccess access, bool ownsSocket)
                {
                        if (socket == null)
                                throw new ArgumentNullException ("socket is null");
-                       if (!socket.Connected)
-                               throw new ArgumentException ("Not connected", "socket");
                        if (socket.SocketType != SocketType.Stream)
                                throw new ArgumentException ("Socket is not of type Stream", "socket");
+                       if (!socket.Connected)
+                               throw new IOException ("Not connected");
                        if (!socket.Blocking)
                                throw new IOException ("Operation not allowed on a non-blocking socket.");
                        
                        this.socket = socket;
-                       this.owns_socket = owns_socket;
+                       this.owns_socket = ownsSocket;
                        this.access = access;
 
                        readable = CanRead;
@@ -87,6 +93,13 @@ namespace System.Net.Sockets
                        }
                }
 
+               public override bool CanTimeout
+               {
+                       get {
+                               return(true);
+                       }
+               }
+
                public override bool CanWrite {
                        get {
                                return access == FileAccess.ReadWrite || access == FileAccess.Write;
@@ -129,6 +142,26 @@ namespace System.Net.Sockets
                        }
                }
 
+#if !NET_2_1 || MOBILE
+#if TARGET_JVM
+               [MonoNotSupported ("Not supported since Socket.ReceiveTimeout is not supported")]
+#endif
+               public override int ReadTimeout
+               {
+                       get {
+                               int r = socket.ReceiveTimeout;
+                               return (r <= 0) ? Timeout.Infinite : r;
+                       }
+                       set {
+                               if (value <= 0 && value != Timeout.Infinite) {
+                                       throw new ArgumentOutOfRangeException ("value", "The value specified is less than or equal to zero and is not Infinite.");
+                               }
+                               
+                               socket.ReceiveTimeout = value;
+                       }
+               }
+#endif
+
                protected Socket Socket {
                        get {
                                return socket;
@@ -145,6 +178,26 @@ namespace System.Net.Sockets
                        }
                }
 
+#if !NET_2_1 || MOBILE
+#if TARGET_JVM
+               [MonoNotSupported ("Not supported since Socket.SendTimeout is not supported")]
+#endif
+               public override int WriteTimeout
+               {
+                       get {
+                               int r = socket.SendTimeout;
+                               return (r <= 0) ? Timeout.Infinite : r;
+                       }
+                       set {
+                               if (value <= 0 && value != Timeout.Infinite) {
+                                       throw new ArgumentOutOfRangeException ("value", "The value specified is less than or equal to zero and is not Infinite");
+                               }
+                               
+                               socket.SendTimeout = value;
+                       }
+               }
+#endif
+
                public override IAsyncResult BeginRead (byte [] buffer, int offset, int size,
                                                        AsyncCallback callback, object state)
                {
@@ -161,8 +214,14 @@ namespace System.Net.Sockets
                                throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
                        }
 
+                       Socket s = socket;
+
+                       if (s == null) {
+                               throw new IOException("Connection closed");
+                       }
+
                        try {
-                               retval = socket.BeginReceive (buffer, offset, size, 0, callback, state);
+                               retval = s.BeginReceive (buffer, offset, size, 0, callback, state);
                        } catch (Exception e) {
                                throw new IOException ("BeginReceive failure", e);
                        }
@@ -187,8 +246,14 @@ namespace System.Net.Sockets
                                throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
                        }
 
+                       Socket s = socket;
+
+                       if (s == null) {
+                               throw new IOException("Connection closed");
+                       }
+
                        try {
-                               retval = socket.BeginSend (buffer, offset, size, 0, callback, state);
+                               retval = s.BeginSend (buffer, offset, size, 0, callback, state);
                        } catch {
                                throw new IOException ("BeginWrite failure");
                        }
@@ -201,18 +266,31 @@ namespace System.Net.Sockets
                        Dispose (false);
                }
                
-               public override void Close ()
+
+#if !NET_2_1 || MOBILE
+               public void Close (int timeout)
                {
-                       ((IDisposable) this).Dispose ();
+                       if (timeout < -1) {
+                               throw new ArgumentOutOfRangeException ("timeout", "timeout is less than -1");
+                       }
+                       
+                       System.Timers.Timer close_timer = new System.Timers.Timer ();
+                       close_timer.Elapsed += new ElapsedEventHandler (OnTimeoutClose);
+                       /* NB timeout is in milliseconds here, cf
+                        * seconds in Socket.Close(int)
+                        */
+                       close_timer.Interval = timeout;
+                       close_timer.AutoReset = false;
+                       close_timer.Enabled = true;
+               }
+               
+               private void OnTimeoutClose (object source, ElapsedEventArgs e)
+               {
+                       this.Close ();
                }
-
-               protected
-#if NET_2_0
-               override
-#else
-               virtual
 #endif
-               void Dispose (bool disposing)
+
+               protected override void Dispose (bool disposing)
                {
                        if (disposed) 
                                return;
@@ -224,6 +302,10 @@ namespace System.Net.Sockets
                                        s.Close ();
                        }
                        socket = null;
+                       access = 0;
+
+                       if (disposing)
+                               GC.SuppressFinalize (this);
                }
 
                public override int EndRead (IAsyncResult ar)
@@ -234,8 +316,14 @@ namespace System.Net.Sockets
                        if (ar == null)
                                throw new ArgumentNullException ("async result is null");
 
+                       Socket s = socket;
+
+                       if (s == null) {
+                               throw new IOException("Connection closed");
+                       }
+
                        try {
-                               res = socket.EndReceive (ar);
+                               res = s.EndReceive (ar);
                        } catch (Exception e) {
                                throw new IOException ("EndRead failure", e);
                        }
@@ -248,8 +336,14 @@ namespace System.Net.Sockets
                        if (ar == null)
                                throw new ArgumentNullException ("async result is null");
 
+                       Socket s = socket;
+
+                       if (s == null) {
+                               throw new IOException("Connection closed");
+                       }
+
                        try {
-                               socket.EndSend (ar);
+                               s.EndSend (ar);
                        } catch (Exception e) {
                                throw new IOException ("EndWrite failure", e);
                        }
@@ -260,12 +354,6 @@ namespace System.Net.Sockets
                        // network streams are non-buffered, this is a no-op
                }
 
-               void IDisposable.Dispose ()
-               {
-                       Dispose (true);
-                       GC.SuppressFinalize (this);
-               }
-
                public override int Read ([In,Out] byte [] buffer, int offset, int size)
                {
                        CheckDisposed ();
@@ -280,8 +368,14 @@ namespace System.Net.Sockets
                                throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
                        }
 
+                       Socket s = socket;
+
+                       if (s == null) {
+                               throw new IOException("Connection closed");
+                       }
+
                        try {
-                               res = socket.Receive (buffer, offset, size, 0);
+                               res = s.Receive (buffer, offset, size, 0);
                        } catch (Exception e) {
                                throw new IOException ("Read failure", e);
                        }
@@ -315,10 +409,16 @@ namespace System.Net.Sockets
                        if (size < 0 || size > buffer.Length - offset)
                                throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
 
+                       Socket s = socket;
+
+                       if (s == null) {
+                               throw new IOException("Connection closed");
+                       }
+
                        try {
                                int count = 0;
                                while (size - count > 0) {
-                                       count += socket.Send (buffer, offset + count, size - count, 0);
+                                       count += s.Send (buffer, offset + count, size - count, 0);
                                }
                        } catch (Exception e) {
                                throw new IOException ("Write failure", e);