Merge pull request #601 from knocte/sock_improvements
[mono.git] / mcs / class / System / System.Net.Sockets / Socket.cs
index 52b9a5013f2700deef747ba731ca614392771a3d..a453d70e43fa9043f3e0ffd85690e57974f9b99e 100644 (file)
@@ -11,7 +11,6 @@
 //    http://www.myelin.co.nz
 // (c) 2004-2011 Novell, Inc. (http://www.novell.com)
 //
-
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -45,9 +44,7 @@ using System.IO;
 using System.Net.Configuration;
 using System.Text;
 using System.Timers;
-#if !MOONLIGHT
 using System.Net.NetworkInformation;
-#endif
 
 namespace System.Net.Sockets 
 {
@@ -55,6 +52,9 @@ namespace System.Net.Sockets
        {
                private bool islistening;
                private bool useoverlappedIO;
+               private const int SOCKET_CLOSED = 10004;
+
+               private static readonly string timeout_exc_msg = "A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond";
 
                static void AddSockets (List<Socket> sockets, IList list, string name)
                {
@@ -498,7 +498,6 @@ namespace System.Net.Sockets
                        }
                }
 
-#if !MOONLIGHT
                public bool AcceptAsync (SocketAsyncEventArgs e)
                {
                        // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
@@ -532,7 +531,6 @@ namespace System.Net.Sockets
                                socket_pool_queue (Worker.Dispatcher, w.result);
                        return true;
                }
-#endif
                // Creates a new system socket, returning the handle
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                private extern static IntPtr Accept_internal(IntPtr sock, out int error, bool blocking);
@@ -543,21 +541,19 @@ namespace System.Net.Sockets
 
                        int error = 0;
                        IntPtr sock = (IntPtr) (-1);
-                       blocking_thread = Thread.CurrentThread;
                        try {
+                               RegisterForBlockingSyscall ();
                                sock = Accept_internal(socket, out error, blocking);
-                       } catch (ThreadAbortException) {
-                               if (disposed) {
-                                       Thread.ResetAbort ();
-                                       error = (int) SocketError.Interrupted;
-                               }
                        } finally {
-                               blocking_thread = null;
+                               UnRegisterForBlockingSyscall ();
+                       }
+
+                       if (error != 0) {
+                               if (closed)
+                                       error = SOCKET_CLOSED;
+                               throw new SocketException(error);
                        }
 
-                       if (error != 0)
-                               throw new SocketException (error);
-                       
                        Socket accepted = new Socket(this.AddressFamily, this.SocketType,
                                this.ProtocolType, sock);
 
@@ -573,21 +569,19 @@ namespace System.Net.Sockets
                        
                        int error = 0;
                        IntPtr sock = (IntPtr)(-1);
-                       blocking_thread = Thread.CurrentThread;
                        
                        try {
+                               RegisterForBlockingSyscall ();
                                sock = Accept_internal (socket, out error, blocking);
-                       } catch (ThreadAbortException) {
-                               if (disposed) {
-                                       Thread.ResetAbort ();
-                                       error = (int)SocketError.Interrupted;
-                               }
                        } finally {
-                               blocking_thread = null;
+                               UnRegisterForBlockingSyscall ();
                        }
                        
-                       if (error != 0)
+                       if (error != 0) {
+                               if (closed)
+                                       error = SOCKET_CLOSED;
                                throw new SocketException (error);
+                       }
                        
                        acceptSocket.address_family = this.AddressFamily;
                        acceptSocket.socket_type = this.SocketType;
@@ -756,8 +750,8 @@ namespace System.Net.Sockets
                        if (offset > buffer.Length)
                                throw new ArgumentOutOfRangeException ("offset", "offset must be <= buffer.Length");
 
-                       if (size < 0)
-                               throw new ArgumentOutOfRangeException ("size", "size must be >= 0")
+                       if (size < 0)                          
+                               throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
                                
                        if (size > buffer.Length - offset)
                                throw new ArgumentOutOfRangeException ("size", "size must be <= buffer.Length - offset");
@@ -1061,7 +1055,10 @@ namespace System.Net.Sockets
                                throw new FileNotFoundException ();
 
                        SendFileHandler d = new SendFileHandler (SendFile);
-                       return new SendFileAsyncResult (d, d.BeginInvoke (fileName, preBuffer, postBuffer, flags, callback, state));
+                       return new SendFileAsyncResult (d, d.BeginInvoke (fileName, preBuffer, postBuffer, flags, ar => {
+                               SendFileAsyncResult sfar = new SendFileAsyncResult (d, ar);
+                               callback (sfar);
+                       }, state));
                }
 
                public IAsyncResult BeginSendTo(byte[] buffer, int offset,
@@ -1176,7 +1173,6 @@ namespace System.Net.Sockets
                        Connect (addresses, port);
                }
 
-#if !MOONLIGHT
                public bool DisconnectAsync (SocketAsyncEventArgs e)
                {
                        // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
@@ -1188,7 +1184,6 @@ namespace System.Net.Sockets
                        socket_pool_queue (Worker.Dispatcher, e.Worker.result);
                        return true;
                }
-#endif
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                extern static void Disconnect_internal(IntPtr sock, bool reuse, out int error);
@@ -1299,7 +1294,6 @@ namespace System.Net.Sockets
                        req.CheckIfThrowDelayedException();
                }
 
-#if !MOONLIGHT
                public void EndDisconnect (IAsyncResult asyncResult)
                {
                        if (disposed && closed)
@@ -1319,7 +1313,6 @@ namespace System.Net.Sockets
 
                        req.CheckIfThrowDelayedException ();
                }
-#endif
 
                [MonoTODO]
                public int EndReceiveMessageFrom (IAsyncResult asyncResult,
@@ -1360,7 +1353,6 @@ namespace System.Net.Sockets
                        ares.Delegate.EndInvoke (ares.Original);
                }
 
-#if !MOONLIGHT
                public int EndSendTo (IAsyncResult result)
                {
                        if (disposed && closed)
@@ -1381,7 +1373,6 @@ namespace System.Net.Sockets
                        req.CheckIfThrowDelayedException();
                        return req.Total;
                }
-#endif
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                private extern static void GetSocketOption_arr_internal(IntPtr socket,
@@ -1504,20 +1495,7 @@ namespace System.Net.Sockets
 
                public int Receive (byte [] buffer)
                {
-                       if (disposed && closed)
-                               throw new ObjectDisposedException (GetType ().ToString ());
-
-                       if (buffer == null)
-                               throw new ArgumentNullException ("buffer");
-
-                       SocketError error;
-
-                       int ret = Receive_nochecks (buffer, 0, buffer.Length, SocketFlags.None, out error);
-                       
-                       if (error != SocketError.Success)
-                               throw new SocketException ((int) error);
-
-                       return ret;
+                       return Receive (buffer, SocketFlags.None);
                }
 
                public int Receive (byte [] buffer, SocketFlags flags)
@@ -1534,7 +1512,7 @@ namespace System.Net.Sockets
                        
                        if (error != SocketError.Success) {
                                if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
-                                       throw new SocketException ((int) error, "Operation timed out.");
+                                       throw new SocketException ((int) error, timeout_exc_msg);
                                throw new SocketException ((int) error);
                        }
 
@@ -1557,7 +1535,7 @@ namespace System.Net.Sockets
                        
                        if (error != SocketError.Success) {
                                if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
-                                       throw new SocketException ((int) error, "Operation timed out.");
+                                       throw new SocketException ((int) error, timeout_exc_msg);
                                throw new SocketException ((int) error);
                        }
 
@@ -1580,7 +1558,7 @@ namespace System.Net.Sockets
                        
                        if (error != SocketError.Success) {
                                if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
-                                       throw new SocketException ((int) error, "Operation timed out.");
+                                       throw new SocketException ((int) error, timeout_exc_msg);
                                throw new SocketException ((int) error);
                        }
 
@@ -1600,7 +1578,6 @@ namespace System.Net.Sockets
                        return Receive_nochecks (buffer, offset, size, flags, out error);
                }
 
-#if !MOONLIGHT
                public bool ReceiveFromAsync (SocketAsyncEventArgs e)
                {
                        if (disposed && closed)
@@ -1620,17 +1597,15 @@ namespace System.Net.Sockets
                        res.Size = e.Count;
                        res.EndPoint = e.RemoteEndPoint;
                        res.SockFlags = e.SocketFlags;
-                       Worker worker = new Worker (e);
                        int count;
                        lock (readQ) {
-                               readQ.Enqueue (worker);
+                               readQ.Enqueue (e.Worker);
                                count = readQ.Count;
                        }
                        if (count == 1)
                                socket_pool_queue (Worker.Dispatcher, res);
                        return true;
                }
-#endif
 
                public int ReceiveFrom (byte [] buffer, ref EndPoint remoteEP)
                {
@@ -1722,7 +1697,7 @@ namespace System.Net.Sockets
                                        connected = false;
                                else if (err == SocketError.WouldBlock && blocking) { // This might happen when ReceiveTimeout is set
                                        if (throwOnError)       
-                                               throw new SocketException ((int) SocketError.TimedOut, "Operation timed out");
+                                               throw new SocketException ((int) SocketError.TimedOut, timeout_exc_msg);
                                        error = (int) SocketError.TimedOut;
                                        return 0;
                                }
@@ -1921,7 +1896,6 @@ namespace System.Net.Sockets
                        }
                }
 
-#if !MOONLIGHT
                public bool SendToAsync (SocketAsyncEventArgs e)
                {
                        // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
@@ -1941,17 +1915,15 @@ namespace System.Net.Sockets
                        res.Size = e.Count;
                        res.SockFlags = e.SocketFlags;
                        res.EndPoint = e.RemoteEndPoint;
-                       Worker worker = new Worker (e);
                        int count;
                        lock (writeQ) {
-                               writeQ.Enqueue (worker);
+                               writeQ.Enqueue (e.Worker);
                                count = writeQ.Count;
                        }
                        if (count == 1)
                                socket_pool_queue (Worker.Dispatcher, res);
                        return true;
                }
-#endif
                
                public int SendTo (byte [] buffer, EndPoint remote_end)
                {