[Socket] Fix Socket.BeginConnect to multiple IPAddress (#4960)
[mono.git] / mcs / class / System / System.Net.Sockets / Socket.cs
index 396b16f4c5416c06b77b6666e47c6404ea198e26..d19756b6c30013be319b87d94a0747081fc47394 100644 (file)
@@ -55,27 +55,20 @@ namespace System.Net.Sockets
                const string TIMEOUT_EXCEPTION_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";
 
-               /*
-                *      These two fields are looked up by name by the runtime, don't change
-                *  their name without also updating the runtime code.
-                */
-               static int ipv4_supported = -1;
-               static int ipv6_supported = -1;
-
                /* true if we called Close_internal */
                bool is_closed;
 
                bool is_listening;
-               bool use_overlapped_io;
+               bool useOverlappedIO;
 
                int linger_timeout;
 
-               AddressFamily address_family;
-               SocketType socket_type;
-               ProtocolType protocol_type;
+               AddressFamily addressFamily;
+               SocketType socketType;
+               ProtocolType protocolType;
 
-               /* the field "safe_handle" is looked up by name by the runtime */
-               internal SafeSocketHandle safe_handle;
+               /* the field "m_Handle" is looked up by name by the runtime */
+               internal SafeSocketHandle m_Handle;
 
                /*
                 * This EndPoint is used when creating new endpoints. Because
@@ -86,8 +79,8 @@ namespace System.Net.Sockets
                 */
                internal EndPoint seed_endpoint = null;
 
-               internal Queue<KeyValuePair<IntPtr, IOSelectorJob>> readQ = new Queue<KeyValuePair<IntPtr, IOSelectorJob>> (2);
-               internal Queue<KeyValuePair<IntPtr, IOSelectorJob>> writeQ = new Queue<KeyValuePair<IntPtr, IOSelectorJob>> (2);
+               internal SemaphoreSlim ReadSem = new SemaphoreSlim (1, 1);
+               internal SemaphoreSlim WriteSem = new SemaphoreSlim (1, 1);
 
                internal bool is_blocking = true;
                internal bool is_bound;
@@ -95,143 +88,59 @@ namespace System.Net.Sockets
                /* When true, the socket was connected at the time of the last IO operation */
                internal bool is_connected;
 
-               internal bool is_disposed;
+               int m_IntCleanedUp;
                internal bool connect_in_progress;
 
 #region Constructors
 
-               static Socket ()
-               {
-                       if (ipv4_supported == -1) {
-                               try {
-                                       Socket tmp = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
-                                       tmp.Close();
-
-                                       ipv4_supported = 1;
-                               } catch {
-                                       ipv4_supported = 0;
-                               }
-                       }
-
-                       if (ipv6_supported == -1) {
-                               // We need to put a try/catch around ConfigurationManager methods as will always throw an exception 
-                               // when run in a mono embedded application.  This occurs as embedded applications do not have a setup
-                               // for application config.  The exception is not thrown when called from a normal .NET application. 
-                               //
-                               // We, then, need to guard calls to the ConfigurationManager.  If the config is not found or throws an
-                               // exception, will fall through to the existing Socket / API directly below in the code.
-                               //
-                               // Also note that catching ConfigurationErrorsException specifically would require library dependency
-                               // System.Configuration, and wanted to avoid that.
-#if !MOBILE
-#if CONFIGURATION_DEP
-                               try {
-                                       SettingsSection config;
-                                       config = (SettingsSection) System.Configuration.ConfigurationManager.GetSection ("system.net/settings");
-                                       if (config != null)
-                                               ipv6_supported = config.Ipv6.Enabled ? -1 : 0;
-                               } catch {
-                                       ipv6_supported = -1;
-                               }
-#else
-                               try {
-                                       NetConfig config = System.Configuration.ConfigurationSettings.GetConfig("system.net/settings") as NetConfig;
-                                       if (config != null)
-                                               ipv6_supported = config.ipv6Enabled ? -1 : 0;
-                               } catch {
-                                       ipv6_supported = -1;
-                               }
-#endif
-#endif
-                               if (ipv6_supported != 0) {
-                                       try {
-                                               Socket tmp = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
-                                               tmp.Close();
-
-                                               ipv6_supported = 1;
-                                       } catch {
-                                               ipv6_supported = 0;
-                                       }
-                               }
-                       }
-               }
-
-               //
-               // This constructor is used by servers that want to listen for instance on both
-               // ipv4 and ipv6.   Mono has historically done that if you use InterNetworkV6 (at
-               // least on Unix), because that is the default behavior unless the IPV6_V6ONLY
-               // option is explicitly set by using setsockopt (sock, IPPROTO_IPV6, IPV6_ONLY)
-               //
-               public Socket (SocketType socketType, ProtocolType protocolType)
-                       : this (AddressFamily.InterNetworkV6, socketType, protocolType)
-               {
-                       DualMode = true;
-               }
-               
-               public Socket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)
-               {
-                       this.address_family = addressFamily;
-                       this.socket_type = socketType;
-                       this.protocol_type = protocolType;
-
-                       int error;
-                       this.safe_handle = new SafeSocketHandle (Socket_internal (addressFamily, socketType, protocolType, out error), true);
-
-                       if (error != 0)
-                               throw new SocketException (error);
-
-                       SocketDefaults ();
-               }
 
-#if !MOBILE
                public Socket (SocketInformation socketInformation)
                {
                        this.is_listening      = (socketInformation.Options & SocketInformationOptions.Listening) != 0;
                        this.is_connected      = (socketInformation.Options & SocketInformationOptions.Connected) != 0;
                        this.is_blocking       = (socketInformation.Options & SocketInformationOptions.NonBlocking) == 0;
-                       this.use_overlapped_io = (socketInformation.Options & SocketInformationOptions.UseOnlyOverlappedIO) != 0;
+                       this.useOverlappedIO = (socketInformation.Options & SocketInformationOptions.UseOnlyOverlappedIO) != 0;
 
                        var result = Mono.DataConverter.Unpack ("iiiil", socketInformation.ProtocolInformation, 0);
 
-                       this.address_family = (AddressFamily) (int) result [0];
-                       this.socket_type = (SocketType) (int) result [1];
-                       this.protocol_type = (ProtocolType) (int) result [2];
+                       this.addressFamily = (AddressFamily) (int) result [0];
+                       this.socketType = (SocketType) (int) result [1];
+                       this.protocolType = (ProtocolType) (int) result [2];
                        this.is_bound = (ProtocolType) (int) result [3] != 0;
-                       this.safe_handle = new SafeSocketHandle ((IntPtr) (long) result [4], true);
+                       this.m_Handle = new SafeSocketHandle ((IntPtr) (long) result [4], true);
+
+                       InitializeSockets ();
 
                        SocketDefaults ();
                }
-#endif
 
                /* private constructor used by Accept, which already has a socket handle to use */
                internal Socket(AddressFamily family, SocketType type, ProtocolType proto, SafeSocketHandle safe_handle)
                {
-                       this.address_family = family;
-                       this.socket_type = type;
-                       this.protocol_type = proto;
+                       this.addressFamily = family;
+                       this.socketType = type;
+                       this.protocolType = proto;
                        
-                       this.safe_handle = safe_handle;
+                       this.m_Handle = safe_handle;
                        this.is_connected = true;
-               }
 
-               ~Socket ()
-               {
-                       Dispose (false);
+                       InitializeSockets ();   
                }
 
                void SocketDefaults ()
                {
                        try {
                                /* Need to test IPv6 further */
-                               if (address_family == AddressFamily.InterNetwork
-                                       // || address_family == AddressFamily.InterNetworkV6
+                               if (addressFamily == AddressFamily.InterNetwork
+                                       // || addressFamily == AddressFamily.InterNetworkV6
                                ) {
                                        /* This is the default, but it probably has nasty side
                                         * effects on Linux, as the socket option is kludged by
                                         * turning on or off PMTU discovery... */
                                        this.DontFragment = false;
-                                       this.NoDelay = false;
-                               } else if (address_family == AddressFamily.InterNetworkV6) {
+                                       if (protocolType == ProtocolType.Tcp)
+                                               this.NoDelay = false;
+                               } else if (addressFamily == AddressFamily.InterNetworkV6) {
                                        this.DualMode = true;
                                }
 
@@ -252,60 +161,12 @@ namespace System.Net.Sockets
 
 #region Properties
 
-               [ObsoleteAttribute ("Use OSSupportsIPv4 instead")]
-               public static bool SupportsIPv4 {
-                       get { return ipv4_supported == 1; }
-               }
-
-               [ObsoleteAttribute ("Use OSSupportsIPv6 instead")]
-               public static bool SupportsIPv6 {
-                       get { return ipv6_supported == 1; }
-               }
-
-#if MOBILE
-               public static bool OSSupportsIPv4 {
-                       get { return ipv4_supported == 1; }
-               }
-#else
-               public static bool OSSupportsIPv4 {
-                       get {
-                               NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces ();
-
-                               foreach (NetworkInterface adapter in nics) {
-                                       if (adapter.Supports (NetworkInterfaceComponent.IPv4))
-                                               return true;
-                               }
-
-                               return false;
-                       }
-               }
-#endif
-
-#if MOBILE
-               public static bool OSSupportsIPv6 {
-                       get { return ipv6_supported == 1; }
-               }
-#else
-               public static bool OSSupportsIPv6 {
-                       get {
-                               NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces ();
-
-                               foreach (NetworkInterface adapter in nics) {
-                                       if (adapter.Supports (NetworkInterfaceComponent.IPv6))
-                                               return true;
-                               }
-
-                               return false;
-                       }
-               }
-#endif
-
                public int Available {
                        get {
                                ThrowIfDisposedAndClosed ();
 
                                int ret, error;
-                               ret = Available_internal (safe_handle, out error);
+                               ret = Available_internal (m_Handle, out error);
 
                                if (error != 0)
                                        throw new SocketException (error);
@@ -330,40 +191,12 @@ namespace System.Net.Sockets
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                extern static int Available_internal (IntPtr socket, out int error);
 
-               public bool DontFragment {
-                       get {
-                               ThrowIfDisposedAndClosed ();
-
-                               switch (address_family) {
-                               case AddressFamily.InterNetwork:
-                                       return ((int) GetSocketOption (SocketOptionLevel.IP, SocketOptionName.DontFragment)) != 0;
-                               case AddressFamily.InterNetworkV6:
-                                       return ((int) GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.DontFragment)) != 0;
-                               default:
-                                       throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
-                               }
-                       }
-                       set {
-                               ThrowIfDisposedAndClosed ();
-
-                               switch (address_family) {
-                               case AddressFamily.InterNetwork:
-                                       SetSocketOption (SocketOptionLevel.IP, SocketOptionName.DontFragment, value ? 1 : 0);
-                                       break;
-                               case AddressFamily.InterNetworkV6:
-                                       SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.DontFragment, value ? 1 : 0);
-                                       break;
-                               default:
-                                       throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
-                               }
-                       }
-               }
-
+               // FIXME: import from referencesource
                public bool EnableBroadcast {
                        get {
                                ThrowIfDisposedAndClosed ();
 
-                               if (protocol_type != ProtocolType.Udp)
+                               if (protocolType != ProtocolType.Udp)
                                        throw new SocketException ((int) SocketError.ProtocolOption);
 
                                return ((int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Broadcast)) != 0;
@@ -371,47 +204,20 @@ namespace System.Net.Sockets
                        set {
                                ThrowIfDisposedAndClosed ();
 
-                               if (protocol_type != ProtocolType.Udp)
+                               if (protocolType != ProtocolType.Udp)
                                        throw new SocketException ((int) SocketError.ProtocolOption);
 
                                SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Broadcast, value ? 1 : 0);
                        }
                }
 
-               public bool ExclusiveAddressUse {
-                       get {
-                               ThrowIfDisposedAndClosed ();
-
-                               return ((int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse)) != 0;
-                       }
-                       set {
-                               ThrowIfDisposedAndClosed ();
-
-                               if (is_bound)
-                                       throw new InvalidOperationException ("Bind has already been called for this socket");
-
-                               SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse, value ? 1 : 0);
-                       }
-               }
-
                public bool IsBound {
                        get {
                                return is_bound;
                        }
                }
 
-               public LingerOption LingerState {
-                       get {
-                               ThrowIfDisposedAndClosed ();
-
-                               return (LingerOption) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Linger);
-                       }
-                       set {
-                               ThrowIfDisposedAndClosed ();
-                               SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Linger, value);
-                       }
-               }
-
+               // FIXME: import from referencesource
                public bool MulticastLoopback {
                        get {
                                ThrowIfDisposedAndClosed ();
@@ -421,10 +227,10 @@ namespace System.Net.Sockets
                                 * "Setting this property on a Transmission Control Protocol (TCP)
                                 * socket will have no effect." but the MS runtime throws the
                                 * exception...) */
-                               if (protocol_type == ProtocolType.Tcp)
+                               if (protocolType == ProtocolType.Tcp)
                                        throw new SocketException ((int)SocketError.ProtocolOption);
 
-                               switch (address_family) {
+                               switch (addressFamily) {
                                case AddressFamily.InterNetwork:
                                        return ((int) GetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastLoopback)) != 0;
                                case AddressFamily.InterNetworkV6:
@@ -441,10 +247,10 @@ namespace System.Net.Sockets
                                 * "Setting this property on a Transmission Control Protocol (TCP)
                                 * socket will have no effect." but the MS runtime throws the
                                 * exception...) */
-                               if (protocol_type == ProtocolType.Tcp)
+                               if (protocolType == ProtocolType.Tcp)
                                        throw new SocketException ((int)SocketError.ProtocolOption);
 
-                               switch (address_family) {
+                               switch (addressFamily) {
                                case AddressFamily.InterNetwork:
                                        SetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastLoopback, value ? 1 : 0);
                                        break;
@@ -457,37 +263,6 @@ namespace System.Net.Sockets
                        }
                }
 
-               public bool DualMode {
-                       get {
-                               if (AddressFamily != AddressFamily.InterNetworkV6) 
-                                       throw new NotSupportedException("This protocol version is not supported");
-
-                               return ((int)GetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only) == 0);
-                       }
-                       set {
-                               if (AddressFamily != AddressFamily.InterNetworkV6) 
-                                       throw new NotSupportedException("This protocol version is not supported");
-
-                               SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, value ? 0 : 1);
-                       }
-               }
-
-               private bool IsDualMode {
-                       get {
-                               return AddressFamily == AddressFamily.InterNetworkV6 && DualMode;
-                       }
-               }
-
-               [MonoTODO ("This doesn't do anything on Mono yet")]
-               public bool UseOnlyOverlappedIO {
-                       get { return use_overlapped_io; }
-                       set { use_overlapped_io = value; }
-               }
-
-               public IntPtr Handle {
-                       get { return safe_handle.DangerousGetHandle (); }
-               }
-
                // Wish:  support non-IP endpoints.
                public EndPoint LocalEndPoint {
                        get {
@@ -499,7 +274,7 @@ namespace System.Net.Sockets
                                        return null;
 
                                int error;
-                               SocketAddress sa = LocalEndPoint_internal (safe_handle, (int) address_family, out error);
+                               SocketAddress sa = LocalEndPoint_internal (m_Handle, (int) addressFamily, out error);
 
                                if (error != 0)
                                        throw new SocketException (error);
@@ -524,61 +299,13 @@ namespace System.Net.Sockets
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                extern static SocketAddress LocalEndPoint_internal (IntPtr socket, int family, out int error);
 
-               public SocketType SocketType {
-                       get { return socket_type; }
-               }
-
-               public int SendTimeout {
-                       get {
-                               ThrowIfDisposedAndClosed ();
-
-                               return (int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendTimeout);
-                       }
-                       set {
-                               ThrowIfDisposedAndClosed ();
-
-                               if (value < -1)
-                                       throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than -1");
-
-                               /* According to the MSDN docs we should adjust values between 1 and
-                                * 499 to 500, but the MS runtime doesn't do this. */
-                               if (value == -1)
-                                       value = 0;
-
-                               SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, value);
-                       }
-               }
-
-               public int ReceiveTimeout {
-                       get {
-                               ThrowIfDisposedAndClosed ();
-
-                               return (int) GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout);
-                       }
-                       set {
-                               ThrowIfDisposedAndClosed ();
-
-                               if (value < -1)
-                                       throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than -1");
-
-                               if (value == -1)
-                                       value = 0;
-
-                               SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, value);
-                       }
-               }
-
-               public AddressFamily AddressFamily {
-                       get { return address_family; }
-               }
-
                public bool Blocking {
                        get { return is_blocking; }
                        set {
                                ThrowIfDisposedAndClosed ();
 
                                int error;
-                               Blocking_internal (safe_handle, value, out error);
+                               Blocking_internal (m_Handle, value, out error);
 
                                if (error != 0)
                                        throw new SocketException (error);
@@ -607,10 +334,7 @@ namespace System.Net.Sockets
                        internal set { is_connected = value; }
                }
 
-               public ProtocolType ProtocolType {
-                       get { return protocol_type; }
-               }
-
+               // FIXME: import from referencesource
                public bool NoDelay {
                        get {
                                ThrowIfDisposedAndClosed ();
@@ -622,75 +346,10 @@ namespace System.Net.Sockets
                        set {
                                ThrowIfDisposedAndClosed ();
                                ThrowIfUdp ();
-
                                SetSocketOption (SocketOptionLevel.Tcp, SocketOptionName.NoDelay, value ? 1 : 0);
                        }
                }
 
-               public int ReceiveBufferSize {
-                       get {
-                               ThrowIfDisposedAndClosed ();
-
-                               return (int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer);
-                       }
-                       set {
-                               ThrowIfDisposedAndClosed ();
-
-                               if (value < 0)
-                                       throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
-
-                               SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, value);
-                       }
-               }
-
-               public int SendBufferSize {
-                       get {
-                               ThrowIfDisposedAndClosed ();
-
-                               return (int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendBuffer);
-                       }
-                       set {
-                               ThrowIfDisposedAndClosed ();
-
-                               if (value < 0)
-                                       throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
-
-                               SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendBuffer, value);
-                       }
-               }
-
-               public short Ttl {
-                       get {
-                               ThrowIfDisposedAndClosed ();
-
-                               switch (address_family) {
-                               case AddressFamily.InterNetwork:
-                                       return (short) (int) GetSocketOption (SocketOptionLevel.IP, SocketOptionName.IpTimeToLive);
-                               case AddressFamily.InterNetworkV6:
-                                       return (short) (int) GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.HopLimit);
-                               default:
-                                       throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
-                               }
-                       }
-                       set {
-                               ThrowIfDisposedAndClosed ();
-
-                               if (value < 0 || value > 255)
-                                       throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero or greater than 255.");
-
-                               switch (address_family) {
-                               case AddressFamily.InterNetwork:
-                                       SetSocketOption (SocketOptionLevel.IP, SocketOptionName.IpTimeToLive, value);
-                                       break;
-                               case AddressFamily.InterNetworkV6:
-                                       SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.HopLimit, value);
-                                       break;
-                               default:
-                                       throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
-                               }
-                       }
-               }
-
                public EndPoint RemoteEndPoint {
                        get {
                                ThrowIfDisposedAndClosed ();
@@ -701,7 +360,7 @@ namespace System.Net.Sockets
                                        return null;
 
                                int error;
-                               SocketAddress sa = RemoteEndPoint_internal (safe_handle, (int) address_family, out error);
+                               SocketAddress sa = RemoteEndPoint_internal (m_Handle, (int) addressFamily, out error);
 
                                if (error != 0)
                                        throw new SocketException (error);
@@ -799,7 +458,7 @@ namespace System.Net.Sockets
                        if (list != null) {
                                foreach (Socket sock in list) {
                                        if (sock == null) // MS throws a NullRef
-                                               throw new ArgumentNullException ("name", "Contains a null element");
+                                               throw new ArgumentNullException (name, "Contains a null element");
                                        sockets.Add (sock);
                                }
                        }
@@ -822,7 +481,7 @@ namespace System.Net.Sockets
                                throw new NotSupportedException ("'mode' parameter is not valid.");
 
                        int error;
-                       bool result = Poll_internal (safe_handle, mode, microSeconds, out error);
+                       bool result = Poll_internal (m_Handle, mode, microSeconds, out error);
 
                        if (error != 0)
                                throw new SocketException (error);
@@ -861,7 +520,7 @@ namespace System.Net.Sockets
                        ThrowIfDisposedAndClosed ();
 
                        int error = 0;
-                       SafeSocketHandle safe_handle = Accept_internal (this.safe_handle, out error, is_blocking);
+                       SafeSocketHandle safe_handle = Accept_internal (this.m_Handle, out error, is_blocking);
 
                        if (error != 0) {
                                if (is_closed)
@@ -882,7 +541,7 @@ namespace System.Net.Sockets
                        ThrowIfDisposedAndClosed ();
 
                        int error = 0;
-                       SafeSocketHandle safe_handle = Accept_internal (this.safe_handle, out error, is_blocking);
+                       SafeSocketHandle safe_handle = Accept_internal (this.m_Handle, out error, is_blocking);
 
                        if (error != 0) {
                                if (is_closed)
@@ -890,10 +549,10 @@ namespace System.Net.Sockets
                                throw new SocketException (error);
                        }
 
-                       acceptSocket.address_family = this.AddressFamily;
-                       acceptSocket.socket_type = this.SocketType;
-                       acceptSocket.protocol_type = this.ProtocolType;
-                       acceptSocket.safe_handle = safe_handle;
+                       acceptSocket.addressFamily = this.AddressFamily;
+                       acceptSocket.socketType = this.SocketType;
+                       acceptSocket.protocolType = this.ProtocolType;
+                       acceptSocket.m_Handle = safe_handle;
                        acceptSocket.is_connected = true;
                        acceptSocket.seed_endpoint = this.seed_endpoint;
                        acceptSocket.Blocking = this.Blocking;
@@ -924,7 +583,7 @@ namespace System.Net.Sockets
 
                        InitSocketAsyncEventArgs (e, AcceptAsyncCallback, e, SocketOperation.Accept);
 
-                       QueueIOSelectorJob (readQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Read, BeginAcceptCallback, e.socket_async_result));
+                       QueueIOSelectorJob (ReadSem, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Read, BeginAcceptCallback, e.socket_async_result));
 
                        return true;
                }
@@ -957,7 +616,7 @@ namespace System.Net.Sockets
 
                        SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.Accept);
 
-                       QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginAcceptCallback, sockares));
+                       QueueIOSelectorJob (ReadSem, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginAcceptCallback, sockares));
 
                        return sockares;
                }
@@ -980,25 +639,6 @@ namespace System.Net.Sockets
                        sockares.Complete (acc_socket);
                });
 
-               public IAsyncResult BeginAccept (int receiveSize, AsyncCallback callback, object state)
-               {
-                       ThrowIfDisposedAndClosed ();
-
-                       if (receiveSize < 0)
-                               throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
-
-                       SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.AcceptReceive) {
-                               Buffer = new byte [receiveSize],
-                               Offset = 0,
-                               Size = receiveSize,
-                               SockFlags = SocketFlags.None,
-                       };
-
-                       QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginAcceptReceiveCallback, sockares));
-
-                       return sockares;
-               }
-
                public IAsyncResult BeginAccept (Socket acceptSocket, int receiveSize, AsyncCallback callback, object state)
                {
                        ThrowIfDisposedAndClosed ();
@@ -1029,7 +669,7 @@ namespace System.Net.Sockets
                                AcceptSocket = acceptSocket,
                        };
 
-                       QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginAcceptReceiveCallback, sockares));
+                       QueueIOSelectorJob (ReadSem, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginAcceptReceiveCallback, sockares));
 
                        return sockares;
                }
@@ -1055,7 +695,7 @@ namespace System.Net.Sockets
                        if (sockares.Size > 0) {
                                try {
                                        SocketError error;
-                                       total = acc_socket.Receive_nochecks (sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, out error);
+                                       total = acc_socket.Receive (sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, out error);
                                        if (error != 0) {
                                                sockares.Complete (new SocketException ((int) error));
                                                return;
@@ -1069,16 +709,10 @@ namespace System.Net.Sockets
                        sockares.Complete (acc_socket, total);
                });
 
-               public Socket EndAccept (IAsyncResult result)
+               public Socket EndAccept (IAsyncResult asyncResult)
                {
                        int bytes;
                        byte[] buffer;
-                       return EndAccept (out buffer, out bytes, result);
-               }
-
-               public Socket EndAccept (out byte[] buffer, IAsyncResult asyncResult)
-               {
-                       int bytes;
                        return EndAccept (out buffer, out bytes, asyncResult);
                }
 
@@ -1120,6 +754,9 @@ namespace System.Net.Sockets
 
                public void Bind (EndPoint localEP)
                {
+#if FEATURE_NO_BSD_SOCKETS
+                       throw new PlatformNotSupportedException ("System.Net.Sockets.Socket:Bind is not supported on this platform.");
+#else
                        ThrowIfDisposedAndClosed ();
 
                        if (localEP == null)
@@ -1131,7 +768,7 @@ namespace System.Net.Sockets
                        }
                        
                        int error;
-                       Bind_internal (safe_handle, localEP.Serialize(), out error);
+                       Bind_internal (m_Handle, localEP.Serialize(), out error);
 
                        if (error != 0)
                                throw new SocketException (error);
@@ -1139,6 +776,7 @@ namespace System.Net.Sockets
                                is_bound = true;
 
                        seed_endpoint = localEP;
+#endif // FEATURE_NO_BSD_SOCKETS
                }
 
                private static void Bind_internal (SafeSocketHandle safeHandle, SocketAddress sa, out int error)
@@ -1169,7 +807,7 @@ namespace System.Net.Sockets
                                throw new SocketException ((int) SocketError.InvalidArgument);
 
                        int error;
-                       Listen_internal(safe_handle, backlog, out error);
+                       Listen_internal(m_Handle, backlog, out error);
 
                        if (error != 0)
                                throw new SocketException (error);
@@ -1206,51 +844,6 @@ namespace System.Net.Sockets
                        Connect (Dns.GetHostAddresses (host), port);
                }
 
-               public void Connect (IPAddress[] addresses, int port)
-               {
-                       ThrowIfDisposedAndClosed ();
-
-                       if (addresses == null)
-                               throw new ArgumentNullException ("addresses");
-                       if (this.AddressFamily != AddressFamily.InterNetwork && this.AddressFamily != AddressFamily.InterNetworkV6)
-                               throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
-                       if (is_listening)
-                               throw new InvalidOperationException ();
-
-                       // FIXME: do non-blocking sockets Poll here?
-                       int error = 0;
-                       foreach (IPAddress address in addresses) {
-                               IPEndPoint iep = new IPEndPoint (address, port);
-                               
-                               iep = RemapIPEndPoint (iep);
-
-                               Connect_internal (safe_handle, iep.Serialize (), out error);
-                               if (error == 0) {
-                                       is_connected = true;
-                                       is_bound = true;
-                                       seed_endpoint = iep;
-                                       return;
-                               }
-                               if (error != (int)SocketError.InProgress && error != (int)SocketError.WouldBlock)
-                                       continue;
-
-                               if (!is_blocking) {
-                                       Poll (-1, SelectMode.SelectWrite);
-                                       error = (int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
-                                       if (error == 0) {
-                                               is_connected = true;
-                                               is_bound = true;
-                                               seed_endpoint = iep;
-                                               return;
-                                       }
-                               }
-                       }
-
-                       if (error != 0)
-                               throw new SocketException (error);
-               }
-
-
                public void Connect (EndPoint remoteEP)
                {
                        ThrowIfDisposedAndClosed ();
@@ -1260,7 +853,7 @@ namespace System.Net.Sockets
 
                        IPEndPoint ep = remoteEP as IPEndPoint;
                        /* Dgram uses Any to 'disconnect' */
-                       if (ep != null && socket_type != SocketType.Dgram) {
+                       if (ep != null && socketType != SocketType.Dgram) {
                                if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any))
                                        throw new SocketException ((int) SocketError.AddressNotAvailable);
                        }
@@ -1275,7 +868,7 @@ namespace System.Net.Sockets
                        SocketAddress serial = remoteEP.Serialize ();
 
                        int error = 0;
-                       Connect_internal (safe_handle, serial, out error);
+                       Connect_internal (m_Handle, serial, out error, is_blocking);
 
                        if (error == 0 || error == 10035)
                                seed_endpoint = remoteEP; // Keep the ep around for non-blocking sockets
@@ -1286,7 +879,7 @@ namespace System.Net.Sockets
                                throw new SocketException (error);
                        }
 
-                       is_connected = !(socket_type == SocketType.Dgram && ep != null && (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)));
+                       is_connected = !(socketType == SocketType.Dgram && ep != null && (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)));
                        is_bound = true;
                }
 
@@ -1308,12 +901,11 @@ namespace System.Net.Sockets
                                SocketAsyncResult ares;
 
                                if (!GetCheckedIPs (e, out addresses)) {
-                                       e.socket_async_result.EndPoint = e.RemoteEndPoint;
+                                       //NOTE: DualMode may cause Socket's RemoteEndpoint to differ in AddressFamily from the
+                                       // SocketAsyncEventArgs, but the SocketAsyncEventArgs itself is not changed
                                        ares = (SocketAsyncResult) BeginConnect (e.RemoteEndPoint, ConnectAsyncCallback, e);
                                } else {
-                                       DnsEndPoint dep = (e.RemoteEndPoint as DnsEndPoint);
-                                       e.socket_async_result.Addresses = addresses;
-                                       e.socket_async_result.Port = dep.Port;
+                                       DnsEndPoint dep = (DnsEndPoint)e.RemoteEndPoint;
                                        ares = (SocketAsyncResult) BeginConnect (addresses, dep.Port, ConnectAsyncCallback, e);
                                }
 
@@ -1329,12 +921,6 @@ namespace System.Net.Sockets
                        return true;
                }
 
-               public static bool ConnectAsync (SocketType socketType, ProtocolType protocolType, SocketAsyncEventArgs e)
-               {
-                       var sock = new Socket (e.RemoteEndPoint.AddressFamily, socketType, protocolType);
-                       return sock.ConnectAsync (e);
-               }
-
                public static void CancelConnectAsync (SocketAsyncEventArgs e)
                {
                        if (e == null)
@@ -1361,107 +947,40 @@ namespace System.Net.Sockets
                        }
                });
 
-               public IAsyncResult BeginConnect (IPAddress address, int port, AsyncCallback callback, object state)
-               {
-                       ThrowIfDisposedAndClosed ();
-
-                       if (address == null)
-                               throw new ArgumentNullException ("address");
-                       if (address.ToString ().Length == 0)
-                               throw new ArgumentException ("The length of the IP address is zero");
-                       if (port <= 0 || port > 65535)
-                               throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
-                       if (is_listening)
-                               throw new InvalidOperationException ();
-
-                       return BeginConnect (new IPEndPoint (address, port), callback, state);
-               }
-
-               public IAsyncResult BeginConnect (string host, int port, AsyncCallback callback, object state)
+               public IAsyncResult BeginConnect (string host, int port, AsyncCallback requestCallback, object state)
                {
                        ThrowIfDisposedAndClosed ();
 
                        if (host == null)
                                throw new ArgumentNullException ("host");
-                       if (address_family != AddressFamily.InterNetwork && address_family != AddressFamily.InterNetworkV6)
+                       if (addressFamily != AddressFamily.InterNetwork && addressFamily != AddressFamily.InterNetworkV6)
                                throw new NotSupportedException ("This method is valid only for sockets in the InterNetwork and InterNetworkV6 families");
                        if (port <= 0 || port > 65535)
                                throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
                        if (is_listening)
                                throw new InvalidOperationException ();
 
-                       return BeginConnect (Dns.GetHostAddresses (host), port, callback, state);
+                       return BeginConnect (Dns.GetHostAddresses (host), port, requestCallback, state);
                }
 
-               public IAsyncResult BeginConnect (EndPoint end_point, AsyncCallback callback, object state)
+               public IAsyncResult BeginConnect (EndPoint remoteEP, AsyncCallback callback, object state)
                {
                        ThrowIfDisposedAndClosed ();
 
-                       if (end_point == null)
-                               throw new ArgumentNullException ("end_point");
+                       if (remoteEP == null)
+                               throw new ArgumentNullException ("remoteEP");
+                       if (is_listening)
+                               throw new InvalidOperationException ();
 
                        SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.Connect) {
-                               EndPoint = end_point,
+                               EndPoint = remoteEP,
                        };
 
-                       // Bug #75154: Connect() should not succeed for .Any addresses.
-                       if (end_point is IPEndPoint) {
-                               IPEndPoint ep = (IPEndPoint) end_point;
-                               if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)) {
-                                       sockares.Complete (new SocketException ((int) SocketError.AddressNotAvailable), true);
-                                       return sockares;
-                               }
-                               
-                               end_point = RemapIPEndPoint (ep);
-                       }
-
-                       int error = 0;
-
-                       if (connect_in_progress) {
-                               // This could happen when multiple IPs are used
-                               // Calling connect() again will reset the connection attempt and cause
-                               // an error. Better to just close the socket and move on.
-                               connect_in_progress = false;
-                               safe_handle.Dispose ();
-                               safe_handle = new SafeSocketHandle (Socket_internal (address_family, socket_type, protocol_type, out error), true);
-                               if (error != 0)
-                                       throw new SocketException (error);
-                       }
-
-                       bool blk = is_blocking;
-                       if (blk)
-                               Blocking = false;
-                       Connect_internal (safe_handle, end_point.Serialize (), out error);
-                       if (blk)
-                               Blocking = true;
-
-                       if (error == 0) {
-                               // succeeded synch
-                               is_connected = true;
-                               is_bound = true;
-                               sockares.Complete (true);
-                               return sockares;
-                       }
-
-                       if (error != (int) SocketError.InProgress && error != (int) SocketError.WouldBlock) {
-                               // error synch
-                               is_connected = false;
-                               is_bound = false;
-                               sockares.Complete (new SocketException (error), true);
-                               return sockares;
-                       }
-
-                       // continue asynch
-                       is_connected = false;
-                       is_bound = false;
-                       connect_in_progress = true;
-
-                       IOSelector.Add (sockares.Handle, new IOSelectorJob (IOOperation.Write, BeginConnectCallback, sockares));
-
+                       BeginSConnect (sockares);
                        return sockares;
                }
 
-               public IAsyncResult BeginConnect (IPAddress[] addresses, int port, AsyncCallback callback, object state)
+               public IAsyncResult BeginConnect (IPAddress[] addresses, int port, AsyncCallback requestCallback, object state)
                {
                        ThrowIfDisposedAndClosed ();
 
@@ -1476,46 +995,92 @@ namespace System.Net.Sockets
                        if (is_listening)
                                throw new InvalidOperationException ();
 
-                       SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.Connect) {
+                       SocketAsyncResult sockares = new SocketAsyncResult (this, requestCallback, state, SocketOperation.Connect) {
                                Addresses = addresses,
                                Port = port,
                        };
 
                        is_connected = false;
 
-                       return BeginMConnect (sockares);
+                       BeginMConnect (sockares);
+                       return sockares;
                }
 
-               internal IAsyncResult BeginMConnect (SocketAsyncResult sockares)
+               static void BeginMConnect (SocketAsyncResult sockares)
                {
-                       SocketAsyncResult ares = null;
                        Exception exc = null;
-                       AsyncCallback callback;
 
                        for (int i = sockares.CurrentAddress; i < sockares.Addresses.Length; i++) {
                                try {
                                        sockares.CurrentAddress++;
+                                       sockares.EndPoint = new IPEndPoint (sockares.Addresses [i], sockares.Port);
 
-                                       ares = (SocketAsyncResult) BeginConnect (new IPEndPoint (sockares.Addresses [i], sockares.Port), null, sockares);
-                                       if (ares.IsCompleted && ares.CompletedSynchronously) {
-                                               ares.CheckIfThrowDelayedException ();
-
-                                               callback = ares.AsyncCallback;
-                                               if (callback != null)
-                                                       ThreadPool.UnsafeQueueUserWorkItem (_ => callback (ares), null);
-                                       }
-
-                                       break;
+                                       BeginSConnect (sockares);
+                                       return;
                                } catch (Exception e) {
                                        exc = e;
-                                       ares = null;
                                }
                        }
 
-                       if (ares == null)
-                               throw exc;
+                       throw exc;
+               }
 
-                       return sockares;
+               static void BeginSConnect (SocketAsyncResult sockares)
+               {
+                       EndPoint remoteEP = sockares.EndPoint;
+                       // Bug #75154: Connect() should not succeed for .Any addresses.
+                       if (remoteEP is IPEndPoint) {
+                               IPEndPoint ep = (IPEndPoint) remoteEP;
+                               if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)) {
+                                       sockares.Complete (new SocketException ((int) SocketError.AddressNotAvailable), true);
+                                       return;
+                               }
+
+                               sockares.EndPoint = remoteEP = sockares.socket.RemapIPEndPoint (ep);
+                       }
+
+                       int error = 0;
+
+                       if (sockares.socket.connect_in_progress) {
+                               // This could happen when multiple IPs are used
+                               // Calling connect() again will reset the connection attempt and cause
+                               // an error. Better to just close the socket and move on.
+                               sockares.socket.connect_in_progress = false;
+                               sockares.socket.m_Handle.Dispose ();
+                               sockares.socket.m_Handle = new SafeSocketHandle (sockares.socket.Socket_internal (sockares.socket.addressFamily, sockares.socket.socketType, sockares.socket.protocolType, out error), true);
+                               if (error != 0)
+                                       throw new SocketException (error);
+                       }
+
+                       bool blk = sockares.socket.is_blocking;
+                       if (blk)
+                               sockares.socket.Blocking = false;
+                       Connect_internal (sockares.socket.m_Handle, remoteEP.Serialize (), out error, false);
+                       if (blk)
+                               sockares.socket.Blocking = true;
+
+                       if (error == 0) {
+                               // succeeded synch
+                               sockares.socket.is_connected = true;
+                               sockares.socket.is_bound = true;
+                               sockares.Complete (true);
+                               return;
+                       }
+
+                       if (error != (int) SocketError.InProgress && error != (int) SocketError.WouldBlock) {
+                               // error synch
+                               sockares.socket.is_connected = false;
+                               sockares.socket.is_bound = false;
+                               sockares.Complete (new SocketException (error), true);
+                               return;
+                       }
+
+                       // continue asynch
+                       sockares.socket.is_connected = false;
+                       sockares.socket.is_bound = false;
+                       sockares.socket.connect_in_progress = true;
+
+                       IOSelector.Add (sockares.Handle, new IOSelectorJob (IOOperation.Write, BeginConnectCallback, sockares));
                }
 
                static IOAsyncCallback BeginConnectCallback = new IOAsyncCallback (ares => {
@@ -1526,18 +1091,11 @@ namespace System.Net.Sockets
                                return;
                        }
 
-                       SocketAsyncResult mconnect = sockares.AsyncState as SocketAsyncResult;
-                       bool is_mconnect = mconnect != null && mconnect.Addresses != null;
-
                        try {
-                               EndPoint ep = sockares.EndPoint;
-                               int error_code = (int) sockares.socket.GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
+                               int error = (int) sockares.socket.GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
 
-                               if (error_code == 0) {
-                                       if (is_mconnect)
-                                               sockares = mconnect;
-
-                                       sockares.socket.seed_endpoint = ep;
+                               if (error == 0) {
+                                       sockares.socket.seed_endpoint = sockares.EndPoint;
                                        sockares.socket.is_connected = true;
                                        sockares.socket.is_bound = true;
                                        sockares.socket.connect_in_progress = false;
@@ -1546,34 +1104,29 @@ namespace System.Net.Sockets
                                        return;
                                }
 
-                               if (!is_mconnect) {
+                               if (sockares.Addresses == null) {
                                        sockares.socket.connect_in_progress = false;
-                                       sockares.Complete (new SocketException (error_code));
+                                       sockares.Complete (new SocketException (error));
                                        return;
                                }
 
-                               if (mconnect.CurrentAddress >= mconnect.Addresses.Length) {
-                                       mconnect.Complete (new SocketException (error_code));
+                               if (sockares.CurrentAddress >= sockares.Addresses.Length) {
+                                       sockares.Complete (new SocketException (error));
                                        return;
                                }
 
-                               mconnect.socket.BeginMConnect (mconnect);
+                               BeginMConnect (sockares);
                        } catch (Exception e) {
                                sockares.socket.connect_in_progress = false;
-
-                               if (is_mconnect)
-                                       sockares = mconnect;
-
                                sockares.Complete (e);
-                               return;
                        }
                });
 
-               public void EndConnect (IAsyncResult result)
+               public void EndConnect (IAsyncResult asyncResult)
                {
                        ThrowIfDisposedAndClosed ();
 
-                       SocketAsyncResult sockares = ValidateEndIAsyncResult (result, "EndConnect", "result");
+                       SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndConnect", "asyncResult");
 
                        if (!sockares.IsCompleted)
                                sockares.AsyncWaitHandle.WaitOne();
@@ -1581,11 +1134,11 @@ namespace System.Net.Sockets
                        sockares.CheckIfThrowDelayedException();
                }
 
-               static void Connect_internal (SafeSocketHandle safeHandle, SocketAddress sa, out int error)
+               static void Connect_internal (SafeSocketHandle safeHandle, SocketAddress sa, out int error, bool blocking)
                {
                        try {
                                safeHandle.RegisterForBlockingSyscall ();
-                               Connect_internal (safeHandle.DangerousGetHandle (), sa, out error);
+                               Connect_internal (safeHandle.DangerousGetHandle (), sa, out error, blocking);
                        } finally {
                                safeHandle.UnRegisterForBlockingSyscall ();
                        }
@@ -1593,7 +1146,7 @@ namespace System.Net.Sockets
 
                /* Connects to the remote address */
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               extern static void Connect_internal(IntPtr sock, SocketAddress sa, out int error);
+               extern static void Connect_internal(IntPtr sock, SocketAddress sa, out int error, bool blocking);
 
                /* Returns :
                 *  - false when it is ok to use RemoteEndPoint
@@ -1626,7 +1179,7 @@ namespace System.Net.Sockets
                        ThrowIfDisposedAndClosed ();
 
                        int error = 0;
-                       Disconnect_internal (safe_handle, reuseSocket, out error);
+                       Disconnect_internal (m_Handle, reuseSocket, out error);
 
                        if (error != 0) {
                                if (error == 50) {
@@ -1730,97 +1283,26 @@ namespace System.Net.Sockets
 
 #region Receive
 
-               public int Receive (byte [] buffer)
-               {
-                       return Receive (buffer, SocketFlags.None);
-               }
-
-               public int Receive (byte [] buffer, SocketFlags socketFlags)
-               {
-                       ThrowIfDisposedAndClosed ();
-                       ThrowIfBufferNull (buffer);
-                       ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
-
-                       SocketError error;
-                       int ret = Receive_nochecks (buffer, 0, buffer.Length, socketFlags, out error);
-
-                       if (error != SocketError.Success) {
-                               if (error == SocketError.WouldBlock && is_blocking) // This might happen when ReceiveTimeout is set
-                                       throw new SocketException ((int) error, TIMEOUT_EXCEPTION_MSG);
-                               throw new SocketException ((int) error);
-                       }
-
-                       return ret;
-               }
-
-               public int Receive (byte [] buffer, int size, SocketFlags socketFlags)
-               {
-                       ThrowIfDisposedAndClosed ();
-                       ThrowIfBufferNull (buffer);
-                       ThrowIfBufferOutOfRange (buffer, 0, size);
-
-                       SocketError error;
-                       int ret = Receive_nochecks (buffer, 0, size, socketFlags, out error);
-
-                       if (error != SocketError.Success) {
-                               if (error == SocketError.WouldBlock && is_blocking) // This might happen when ReceiveTimeout is set
-                                       throw new SocketException ((int) error, TIMEOUT_EXCEPTION_MSG);
-                               throw new SocketException ((int) error);
-                       }
-
-                       return ret;
-               }
-
-               public int Receive (byte [] buffer, int offset, int size, SocketFlags socketFlags)
-               {
-                       ThrowIfDisposedAndClosed ();
-                       ThrowIfBufferNull (buffer);
-                       ThrowIfBufferOutOfRange (buffer, offset, size);
-
-                       SocketError error;
-                       int ret = Receive_nochecks (buffer, offset, size, socketFlags, out error);
-
-                       if (error != SocketError.Success) {
-                               if (error == SocketError.WouldBlock && is_blocking) // This might happen when ReceiveTimeout is set
-                                       throw new SocketException ((int) error, TIMEOUT_EXCEPTION_MSG);
-                               throw new SocketException ((int) error);
-                       }
-
-                       return ret;
-               }
-
                public int Receive (byte [] buffer, int offset, int size, SocketFlags socketFlags, out SocketError errorCode)
                {
                        ThrowIfDisposedAndClosed ();
                        ThrowIfBufferNull (buffer);
                        ThrowIfBufferOutOfRange (buffer, offset, size);
 
-                       return Receive_nochecks (buffer, offset, size, socketFlags, out errorCode);
-               }
-
-               public int Receive (IList<ArraySegment<byte>> buffers)
-               {
-                       SocketError error;
-                       int ret = Receive (buffers, SocketFlags.None, out error);
+                       int nativeError;
+                       int ret = Receive_internal (m_Handle, buffer, offset, size, socketFlags, out nativeError, is_blocking);
 
-                       if (error != SocketError.Success)
-                               throw new SocketException ((int) error);
+                       errorCode = (SocketError) nativeError;
+                       if (errorCode != SocketError.Success && errorCode != SocketError.WouldBlock && errorCode != SocketError.InProgress) {
+                               is_connected = false;
+                               is_bound = false;
+                       } else {
+                               is_connected = true;
+                       }
 
                        return ret;
                }
 
-               [CLSCompliant (false)]
-               public int Receive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags)
-               {
-                       SocketError error;
-                       int ret = Receive (buffers, socketFlags, out error);
-
-                       if (error != SocketError.Success)
-                               throw new SocketException ((int) error);
-
-                       return(ret);
-               }
-
                [CLSCompliant (false)]
                public int Receive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode)
                {
@@ -1851,7 +1333,7 @@ namespace System.Net.Sockets
                        }
 
                        try {
-                               ret = Receive_internal (safe_handle, bufarray, socketFlags, out nativeError);
+                               ret = Receive_internal (m_Handle, bufarray, socketFlags, out nativeError, is_blocking);
                        } finally {
                                for (int i = 0; i < numsegments; i++) {
                                        if (gch[i].IsAllocated)
@@ -1881,7 +1363,7 @@ namespace System.Net.Sockets
 
                                e.socket_async_result.Buffers = e.BufferList;
 
-                               QueueIOSelectorJob (readQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveGenericCallback, e.socket_async_result));
+                               QueueIOSelectorJob (ReadSem, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveGenericCallback, e.socket_async_result));
                        } else {
                                InitSocketAsyncEventArgs (e, ReceiveAsyncCallback, e, SocketOperation.Receive);
 
@@ -1889,7 +1371,7 @@ namespace System.Net.Sockets
                                e.socket_async_result.Offset = e.Offset;
                                e.socket_async_result.Size = e.Count;
 
-                               QueueIOSelectorJob (readQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveCallback, e.socket_async_result));
+                               QueueIOSelectorJob (ReadSem, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveCallback, e.socket_async_result));
                        }
 
                        return true;
@@ -1912,39 +1394,35 @@ namespace System.Net.Sockets
                        }
                });
 
-               public IAsyncResult BeginReceive (byte[] buffer, int offset, int size, SocketFlags socket_flags, AsyncCallback callback, object state)
+               public IAsyncResult BeginReceive (byte[] buffer, int offset, int size, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
                {
                        ThrowIfDisposedAndClosed ();
                        ThrowIfBufferNull (buffer);
                        ThrowIfBufferOutOfRange (buffer, offset, size);
 
+                       /* As far as I can tell from the docs and from experimentation, a pointer to the
+                        * SocketError parameter is not supposed to be saved for the async parts.  And as we don't
+                        * set any socket errors in the setup code, we just have to set it to Success. */
+                       errorCode = SocketError.Success;
+
                        SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.Receive) {
                                Buffer = buffer,
                                Offset = offset,
                                Size = size,
-                               SockFlags = socket_flags,
+                               SockFlags = socketFlags,
                        };
 
-                       QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveCallback, sockares));
+                       QueueIOSelectorJob (ReadSem, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveCallback, sockares));
 
                        return sockares;
                }
 
-               public IAsyncResult BeginReceive (byte[] buffer, int offset, int size, SocketFlags flags, out SocketError error, AsyncCallback callback, object state)
-               {
-                       /* As far as I can tell from the docs and from experimentation, a pointer to the
-                        * SocketError parameter is not supposed to be saved for the async parts.  And as we don't
-                        * set any socket errors in the setup code, we just have to set it to Success. */
-                       error = SocketError.Success;
-                       return BeginReceive (buffer, offset, size, flags, callback, state);
-               }
-
                static IOAsyncCallback BeginReceiveCallback = new IOAsyncCallback (ares => {
                        SocketAsyncResult sockares = (SocketAsyncResult) ares;
                        int total = 0;
 
                        try {
-                               total = Receive_internal (sockares.socket.safe_handle, sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, out sockares.error);
+                               total = Receive_internal (sockares.socket.m_Handle, sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, out sockares.error, sockares.socket.is_blocking);
                        } catch (Exception e) {
                                sockares.Complete (e);
                                return;
@@ -1954,31 +1432,26 @@ namespace System.Net.Sockets
                });
 
                [CLSCompliant (false)]
-               public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, AsyncCallback callback, object state)
+               public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
                {
                        ThrowIfDisposedAndClosed ();
 
                        if (buffers == null)
                                throw new ArgumentNullException ("buffers");
 
+                       /* I assume the same SocketError semantics as above */
+                       errorCode = SocketError.Success;
+
                        SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.ReceiveGeneric) {
                                Buffers = buffers,
                                SockFlags = socketFlags,
                        };
 
-                       QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveGenericCallback, sockares));
+                       QueueIOSelectorJob (ReadSem, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveGenericCallback, sockares));
 
                        return sockares;
                }
 
-               [CLSCompliant (false)]
-               public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
-               {
-                       /* I assume the same SocketError semantics as above */
-                       errorCode = SocketError.Success;
-                       return BeginReceive (buffers, socketFlags, callback, state);
-               }
-
                static IOAsyncCallback BeginReceiveGenericCallback = new IOAsyncCallback (ares => {
                        SocketAsyncResult sockares = (SocketAsyncResult) ares;
                        int total = 0;
@@ -1993,20 +1466,6 @@ namespace System.Net.Sockets
                        sockares.Complete (total);
                });
 
-               public int EndReceive (IAsyncResult result)
-               {
-                       SocketError error;
-                       int bytesReceived = EndReceive (result, out error);
-
-                       if (error != SocketError.Success) {
-                               if (error != SocketError.WouldBlock && error != SocketError.InProgress)
-                                       is_connected = false;
-                               throw new SocketException ((int)error);
-                       }
-
-                       return bytesReceived;
-               }
-
                public int EndReceive (IAsyncResult asyncResult, out SocketError errorCode)
                {
                        ThrowIfDisposedAndClosed ();
@@ -2016,96 +1475,98 @@ namespace System.Net.Sockets
                        if (!sockares.IsCompleted)
                                sockares.AsyncWaitHandle.WaitOne ();
 
+                       errorCode = sockares.ErrorCode;
+
+                       if (errorCode != SocketError.Success && errorCode != SocketError.WouldBlock && errorCode != SocketError.InProgress)
+                               is_connected = false;
+
                        // If no socket error occurred, call CheckIfThrowDelayedException in case there are other
                        // kinds of exceptions that should be thrown.
-                       if ((errorCode = sockares.ErrorCode) == SocketError.Success)
+                       if (errorCode == SocketError.Success)
                                sockares.CheckIfThrowDelayedException();
 
                        return sockares.Total;
                }
 
-               int Receive_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
-               {
-                       int nativeError;
-                       int ret = Receive_internal (safe_handle, buf, offset, size, flags, out nativeError);
-
-                       error = (SocketError) nativeError;
-                       if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress) {
-                               is_connected = false;
-                               is_bound = false;
-                       } else {
-                               is_connected = true;
-                       }
-
-                       return ret;
-               }
-
-               static int Receive_internal (SafeSocketHandle safeHandle, WSABUF[] bufarray, SocketFlags flags, out int error)
+               static int Receive_internal (SafeSocketHandle safeHandle, WSABUF[] bufarray, SocketFlags flags, out int error, bool blocking)
                {
                        try {
                                safeHandle.RegisterForBlockingSyscall ();
-                               return Receive_internal (safeHandle.DangerousGetHandle (), bufarray, flags, out error);
+                               return Receive_internal (safeHandle.DangerousGetHandle (), bufarray, flags, out error, blocking);
                        } finally {
                                safeHandle.UnRegisterForBlockingSyscall ();
                        }
                }
 
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               extern static int Receive_internal (IntPtr sock, WSABUF[] bufarray, SocketFlags flags, out int error);
+               extern static int Receive_internal (IntPtr sock, WSABUF[] bufarray, SocketFlags flags, out int error, bool blocking);
 
-               static int Receive_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, out int error)
+               static int Receive_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, out int error, bool blocking)
                {
                        try {
                                safeHandle.RegisterForBlockingSyscall ();
-                               return Receive_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, out error);
+                               return Receive_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, out error, blocking);
                        } finally {
                                safeHandle.UnRegisterForBlockingSyscall ();
                        }
                }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               extern static int Receive_internal(IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags, out int error);
+               extern static int Receive_internal(IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags, out int error, bool blocking);
 
 #endregion
 
 #region ReceiveFrom
 
-               public int ReceiveFrom (byte [] buffer, ref EndPoint remoteEP)
+               public int ReceiveFrom (byte [] buffer, int offset, int size, SocketFlags socketFlags, ref EndPoint remoteEP)
                {
                        ThrowIfDisposedAndClosed ();
                        ThrowIfBufferNull (buffer);
+                       ThrowIfBufferOutOfRange (buffer, offset, size);
 
-                       return ReceiveFrom (buffer, 0, buffer.Length, SocketFlags.None, ref remoteEP);
-               }
+                       if (remoteEP == null)
+                               throw new ArgumentNullException ("remoteEP");
 
-               public int ReceiveFrom (byte [] buffer, SocketFlags socketFlags, ref EndPoint remoteEP)
-               {
-                       ThrowIfDisposedAndClosed ();
-                       ThrowIfBufferNull (buffer);
+                       SocketError errorCode;
+                       int ret = ReceiveFrom (buffer, offset, size, socketFlags, ref remoteEP, out errorCode);
+
+                       if (errorCode != SocketError.Success)
+                               throw new SocketException (errorCode);
 
-                       return ReceiveFrom (buffer, 0, buffer.Length, socketFlags, ref remoteEP);
+                       return ret;
                }
 
-               public int ReceiveFrom (byte [] buffer, int size, SocketFlags socketFlags, ref EndPoint remoteEP)
+               internal int ReceiveFrom (byte [] buffer, int offset, int size, SocketFlags socketFlags, ref EndPoint remoteEP, out SocketError errorCode)
                {
-                       ThrowIfDisposedAndClosed ();
-                       ThrowIfBufferNull (buffer);
-                       ThrowIfBufferOutOfRange (buffer, 0, size);
+                       SocketAddress sockaddr = remoteEP.Serialize();
 
-                       return ReceiveFrom (buffer, 0, size, socketFlags, ref remoteEP);
-               }
+                       int nativeError;
+                       int cnt = ReceiveFrom_internal (m_Handle, buffer, offset, size, socketFlags, ref sockaddr, out nativeError, is_blocking);
 
-               public int ReceiveFrom (byte [] buffer, int offset, int size, SocketFlags socketFlags, ref EndPoint remoteEP)
-               {
-                       ThrowIfDisposedAndClosed ();
-                       ThrowIfBufferNull (buffer);
-                       ThrowIfBufferOutOfRange (buffer, offset, size);
+                       errorCode = (SocketError) nativeError;
+                       if (errorCode != SocketError.Success) {
+                               if (errorCode != SocketError.WouldBlock && errorCode != SocketError.InProgress) {
+                                       is_connected = false;
+                               } else if (errorCode == SocketError.WouldBlock && is_blocking) { // This might happen when ReceiveTimeout is set
+                                       errorCode = SocketError.TimedOut;
+                               }
 
-                       if (remoteEP == null)
-                               throw new ArgumentNullException ("remoteEP");
+                               return 0;
+                       }
+
+                       is_connected = true;
+                       is_bound = true;
+
+                       /* If sockaddr is null then we're a connection oriented protocol and should ignore the
+                        * remoteEP parameter (see MSDN documentation for Socket.ReceiveFrom(...) ) */
+                       if (sockaddr != null) {
+                               /* Stupidly, EndPoint.Create() is an instance method */
+                               remoteEP = remoteEP.Create (sockaddr);
+                       }
+
+                       seed_endpoint = remoteEP;
 
-                       int error;
-                       return ReceiveFrom_nochecks_exc (buffer, offset, size, socketFlags, ref remoteEP, true, out error);
+                       return cnt;
                }
 
                public bool ReceiveFromAsync (SocketAsyncEventArgs e)
@@ -2126,7 +1587,7 @@ namespace System.Net.Sockets
                        e.socket_async_result.EndPoint = e.RemoteEndPoint;
                        e.socket_async_result.SockFlags = e.SocketFlags;
 
-                       QueueIOSelectorJob (readQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveFromCallback, e.socket_async_result));
+                       QueueIOSelectorJob (ReadSem, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveFromCallback, e.socket_async_result));
 
                        return true;
                }
@@ -2148,24 +1609,24 @@ namespace System.Net.Sockets
                        }
                });
 
-               public IAsyncResult BeginReceiveFrom (byte[] buffer, int offset, int size, SocketFlags socket_flags, ref EndPoint remote_end, AsyncCallback callback, object state)
+               public IAsyncResult BeginReceiveFrom (byte[] buffer, int offset, int size, SocketFlags socketFlags, ref EndPoint remoteEP, AsyncCallback callback, object state)
                {
                        ThrowIfDisposedAndClosed ();
                        ThrowIfBufferNull (buffer);
                        ThrowIfBufferOutOfRange (buffer, offset, size);
 
-                       if (remote_end == null)
-                               throw new ArgumentNullException ("remote_end");
+                       if (remoteEP == null)
+                               throw new ArgumentNullException ("remoteEP");
 
                        SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.ReceiveFrom) {
                                Buffer = buffer,
                                Offset = offset,
                                Size = size,
-                               SockFlags = socket_flags,
-                               EndPoint = remote_end,
+                               SockFlags = socketFlags,
+                               EndPoint = remoteEP,
                        };
 
-                       QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveFromCallback, sockares));
+                       QueueIOSelectorJob (ReadSem, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveFromCallback, sockares));
 
                        return sockares;
                }
@@ -2175,8 +1636,13 @@ namespace System.Net.Sockets
                        int total = 0;
 
                        try {
-                               int error;
-                               total = sockares.socket.ReceiveFrom_nochecks_exc (sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, ref sockares.EndPoint, true, out error);
+                               SocketError errorCode;
+                               total = sockares.socket.ReceiveFrom (sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, ref sockares.EndPoint, out errorCode);
+
+                               if (errorCode != SocketError.Success) {
+                                       sockares.Complete (new SocketException (errorCode));
+                                       return;
+                               }
                        } catch (Exception e) {
                                sockares.Complete (e);
                                return;
@@ -2185,75 +1651,39 @@ namespace System.Net.Sockets
                        sockares.Complete (total);
                });
 
-               public int EndReceiveFrom(IAsyncResult result, ref EndPoint end_point)
+               public int EndReceiveFrom(IAsyncResult asyncResult, ref EndPoint endPoint)
                {
                        ThrowIfDisposedAndClosed ();
 
-                       if (end_point == null)
-                               throw new ArgumentNullException ("remote_end");
+                       if (endPoint == null)
+                               throw new ArgumentNullException ("endPoint");
 
-                       SocketAsyncResult sockares = ValidateEndIAsyncResult (result, "EndReceiveFrom", "result");
+                       SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndReceiveFrom", "asyncResult");
 
                        if (!sockares.IsCompleted)
                                sockares.AsyncWaitHandle.WaitOne();
 
                        sockares.CheckIfThrowDelayedException();
 
-                       end_point = sockares.EndPoint;
+                       endPoint = sockares.EndPoint;
 
                        return sockares.Total;
                }
 
-               internal int ReceiveFrom_nochecks_exc (byte [] buf, int offset, int size, SocketFlags flags, ref EndPoint remote_end, bool throwOnError, out int error)
-               {
-                       SocketAddress sockaddr = remote_end.Serialize();
-
-                       int cnt = ReceiveFrom_internal (safe_handle, buf, offset, size, flags, ref sockaddr, out error);
-
-                       SocketError err = (SocketError) error;
-                       if (err != 0) {
-                               if (err != SocketError.WouldBlock && err != SocketError.InProgress) {
-                                       is_connected = false;
-                               } else if (err == SocketError.WouldBlock && is_blocking) { // This might happen when ReceiveTimeout is set
-                                       if (throwOnError)       
-                                               throw new SocketException ((int) SocketError.TimedOut, TIMEOUT_EXCEPTION_MSG);
-                                       error = (int) SocketError.TimedOut;
-                                       return 0;
-                               }
-
-                               if (throwOnError)
-                                       throw new SocketException (error);
-
-                               return 0;
-                       }
-
-                       is_connected = true;
-                       is_bound = true;
-
-                       /* If sockaddr is null then we're a connection oriented protocol and should ignore the
-                        * remote_end parameter (see MSDN documentation for Socket.ReceiveFrom(...) ) */
-                       if (sockaddr != null) {
-                               /* Stupidly, EndPoint.Create() is an instance method */
-                               remote_end = remote_end.Create (sockaddr);
-                       }
-
-                       seed_endpoint = remote_end;
 
-                       return cnt;
-               }
 
-               static int ReceiveFrom_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, ref SocketAddress sockaddr, out int error)
+               static int ReceiveFrom_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, ref SocketAddress sockaddr, out int error, bool blocking)
                {
                        try {
                                safeHandle.RegisterForBlockingSyscall ();
-                               return ReceiveFrom_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, ref sockaddr, out error);
+                               return ReceiveFrom_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, ref sockaddr, out error, blocking);
                        } finally {
                                safeHandle.UnRegisterForBlockingSyscall ();
                        }
                }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               extern static int ReceiveFrom_internal(IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags, ref SocketAddress sockaddr, out int error);
+               extern static int ReceiveFrom_internal(IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags, ref SocketAddress sockaddr, out int error, bool blocking);
 
 #endregion
 
@@ -2304,7 +1734,7 @@ namespace System.Net.Sockets
                        if (endPoint == null)
                                throw new ArgumentNullException ("endPoint");
 
-                       SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndReceiveMessageFrom", "asyncResult");
+                       /*SocketAsyncResult sockares =*/ ValidateEndIAsyncResult (asyncResult, "EndReceiveMessageFrom", "asyncResult");
 
                        throw new NotImplementedException ();
                }
@@ -2313,97 +1743,33 @@ namespace System.Net.Sockets
 
 #region Send
 
-               public int Send (byte [] buffer)
-               {
-                       ThrowIfDisposedAndClosed ();
-                       ThrowIfBufferNull (buffer);
-                       ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
-
-                       SocketError error;
-                       int ret = Send_nochecks (buffer, 0, buffer.Length, SocketFlags.None, out error);
-
-                       if (error != SocketError.Success)
-                               throw new SocketException ((int) error);
-
-                       return ret;
-               }
-
-               public int Send (byte [] buffer, SocketFlags socketFlags)
-               {
-                       ThrowIfDisposedAndClosed ();
-                       ThrowIfBufferNull (buffer);
-                       ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
-
-                       SocketError error;
-                       int ret = Send_nochecks (buffer, 0, buffer.Length, socketFlags, out error);
-
-                       if (error != SocketError.Success)
-                               throw new SocketException ((int) error);
-
-                       return ret;
-               }
-
-               public int Send (byte [] buffer, int size, SocketFlags socketFlags)
-               {
-                       ThrowIfDisposedAndClosed ();
-                       ThrowIfBufferNull (buffer);
-                       ThrowIfBufferOutOfRange (buffer, 0, size);
-
-                       SocketError error;
-                       int ret = Send_nochecks (buffer, 0, size, socketFlags, out error);
-
-                       if (error != SocketError.Success)
-                               throw new SocketException ((int) error);
-
-                       return ret;
-               }
-
-               public int Send (byte [] buffer, int offset, int size, SocketFlags socketFlags)
-               {
-                       ThrowIfDisposedAndClosed ();
-                       ThrowIfBufferNull (buffer);
-                       ThrowIfBufferOutOfRange (buffer, offset, size);
-
-                       SocketError error;
-                       int ret = Send_nochecks (buffer, offset, size, socketFlags, out error);
-
-                       if (error != SocketError.Success)
-                               throw new SocketException ((int) error);
-
-                       return ret;
-               }
-
                public int Send (byte [] buffer, int offset, int size, SocketFlags socketFlags, out SocketError errorCode)
                {
                        ThrowIfDisposedAndClosed ();
                        ThrowIfBufferNull (buffer);
                        ThrowIfBufferOutOfRange (buffer, offset, size);
 
-                       return Send_nochecks (buffer, offset, size, socketFlags, out errorCode);
-               }
-
-               public
-               int Send (IList<ArraySegment<byte>> buffers)
-               {
-                       SocketError error;
-                       int ret = Send (buffers, SocketFlags.None, out error);
-
-                       if (error != SocketError.Success)
-                               throw new SocketException ((int) error);
-
-                       return ret;
-               }
-
-               public
-               int Send (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags)
-               {
-                       SocketError error;
-                       int ret = Send (buffers, socketFlags, out error);
+                       if (size == 0) {
+                               errorCode = SocketError.Success;
+                               return 0;
+                       }
 
-                       if (error != SocketError.Success)
-                               throw new SocketException ((int) error);
+                       int nativeError;
+                       int sent = 0;
+                       do {
+                               sent += Send_internal (
+m_Handle, buffer, offset + sent, size - sent, socketFlags, out nativeError, is_blocking);
+                               errorCode = (SocketError)nativeError;
+                               if (errorCode != SocketError.Success && errorCode != SocketError.WouldBlock && errorCode != SocketError.InProgress) {
+                                       is_connected = false;
+                                       is_bound = false;
+                                       break;
+                               } else {
+                                       is_connected = true;
+                               }
+                       } while (sent < size);
 
-                       return ret;
+                       return sent;
                }
 
                [CLSCompliant (false)]
@@ -2435,7 +1801,7 @@ namespace System.Net.Sockets
                        }
 
                        try {
-                               ret = Send_internal (safe_handle, bufarray, socketFlags, out nativeError);
+                               ret = Send_internal (m_Handle, bufarray, socketFlags, out nativeError, is_blocking);
                        } finally {
                                for(int i = 0; i < numsegments; i++) {
                                        if (gch[i].IsAllocated) {
@@ -2449,28 +1815,6 @@ namespace System.Net.Sockets
                        return ret;
                }
 
-               int Send_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
-               {
-                       if (size == 0) {
-                               error = SocketError.Success;
-                               return 0;
-                       }
-
-                       int nativeError;
-                       int ret = Send_internal (safe_handle, buf, offset, size, flags, out nativeError);
-
-                       error = (SocketError)nativeError;
-
-                       if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress) {
-                               is_connected = false;
-                               is_bound = false;
-                       } else {
-                               is_connected = true;
-                       }
-
-                       return ret;
-               }
-
                public bool SendAsync (SocketAsyncEventArgs e)
                {
                        // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
@@ -2485,7 +1829,7 @@ namespace System.Net.Sockets
 
                                e.socket_async_result.Buffers = e.BufferList;
 
-                               QueueIOSelectorJob (writeQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Write, BeginSendGenericCallback, e.socket_async_result));
+                               QueueIOSelectorJob (WriteSem, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Write, BeginSendGenericCallback, e.socket_async_result));
                        } else {
                                InitSocketAsyncEventArgs (e, SendAsyncCallback, e, SocketOperation.Send);
 
@@ -2493,7 +1837,7 @@ namespace System.Net.Sockets
                                e.socket_async_result.Offset = e.Offset;
                                e.socket_async_result.Size = e.Count;
 
-                               QueueIOSelectorJob (writeQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendCallback ((SocketAsyncResult) s, 0), e.socket_async_result));
+                               QueueIOSelectorJob (WriteSem, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendCallback ((SocketAsyncResult) s, 0), e.socket_async_result));
                        }
 
                        return true;
@@ -2518,32 +1862,25 @@ namespace System.Net.Sockets
 
                public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
                {
+                       ThrowIfDisposedAndClosed ();
+                       ThrowIfBufferNull (buffer);
+                       ThrowIfBufferOutOfRange (buffer, offset, size);
+
                        if (!is_connected) {
                                errorCode = SocketError.NotConnected;
-                               throw new SocketException ((int) errorCode);
+                               return null;
                        }
 
                        errorCode = SocketError.Success;
-                       return BeginSend (buffer, offset, size, socketFlags, callback, state);
-               }
-
-               public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socket_flags, AsyncCallback callback, object state)
-               {
-                       ThrowIfDisposedAndClosed ();
-                       ThrowIfBufferNull (buffer);
-                       ThrowIfBufferOutOfRange (buffer, offset, size);
-
-                       if (!is_connected)
-                               throw new SocketException ((int)SocketError.NotConnected);
 
                        SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.Send) {
                                Buffer = buffer,
                                Offset = offset,
                                Size = size,
-                               SockFlags = socket_flags,
+                               SockFlags = socketFlags,
                        };
 
-                       QueueIOSelectorJob (writeQ, sockares.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendCallback ((SocketAsyncResult) s, 0), sockares));
+                       QueueIOSelectorJob (WriteSem, sockares.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendCallback ((SocketAsyncResult) s, 0), sockares));
 
                        return sockares;
                }
@@ -2553,7 +1890,7 @@ namespace System.Net.Sockets
                        int total = 0;
 
                        try {
-                               total = Socket.Send_internal (sockares.socket.safe_handle, sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, out sockares.error);
+                               total = Socket.Send_internal (sockares.socket.m_Handle, sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, out sockares.error, false);
                        } catch (Exception e) {
                                sockares.Complete (e);
                                return;
@@ -2564,7 +1901,7 @@ namespace System.Net.Sockets
                                sockares.Offset += total;
                                sockares.Size -= total;
 
-                               if (sockares.socket.is_disposed) {
+                               if (sockares.socket.CleanedUp) {
                                        sockares.Complete (total);
                                        return;
                                }
@@ -2580,37 +1917,31 @@ namespace System.Net.Sockets
                        sockares.Complete (total);
                }
 
-               public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, AsyncCallback callback, object state)
+               [CLSCompliant (false)]
+               public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
                {
                        ThrowIfDisposedAndClosed ();
 
                        if (buffers == null)
                                throw new ArgumentNullException ("buffers");
-                       if (!is_connected)
-                               throw new SocketException ((int)SocketError.NotConnected);
+
+                       if (!is_connected) {
+                               errorCode = SocketError.NotConnected;
+                               return null;
+                       }
+
+                       errorCode = SocketError.Success;
 
                        SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.SendGeneric) {
                                Buffers = buffers,
                                SockFlags = socketFlags,
                        };
 
-                       QueueIOSelectorJob (writeQ, sockares.Handle, new IOSelectorJob (IOOperation.Write, BeginSendGenericCallback, sockares));
+                       QueueIOSelectorJob (WriteSem, sockares.Handle, new IOSelectorJob (IOOperation.Write, BeginSendGenericCallback, sockares));
 
                        return sockares;
                }
 
-               [CLSCompliant (false)]
-               public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
-               {
-                       if (!is_connected) {
-                               errorCode = SocketError.NotConnected;
-                               throw new SocketException ((int)errorCode);
-                       }
-
-                       errorCode = SocketError.Success;
-                       return BeginSend (buffers, socketFlags, callback, state);
-               }
-
                static IOAsyncCallback BeginSendGenericCallback = new IOAsyncCallback (ares => {
                        SocketAsyncResult sockares = (SocketAsyncResult) ares;
                        int total = 0;
@@ -2625,20 +1956,6 @@ namespace System.Net.Sockets
                        sockares.Complete (total);
                });
 
-               public int EndSend (IAsyncResult result)
-               {
-                       SocketError error;
-                       int bytesSent = EndSend (result, out error);
-
-                       if (error != SocketError.Success) {
-                               if (error != SocketError.WouldBlock && error != SocketError.InProgress)
-                                       is_connected = false;
-                               throw new SocketException ((int)error);
-                       }
-
-                       return bytesSent;
-               }
-
                public int EndSend (IAsyncResult asyncResult, out SocketError errorCode)
                {
                        ThrowIfDisposedAndClosed ();
@@ -2648,67 +1965,49 @@ namespace System.Net.Sockets
                        if (!sockares.IsCompleted)
                                sockares.AsyncWaitHandle.WaitOne ();
 
+                       errorCode = sockares.ErrorCode;
+
+                       if (errorCode != SocketError.Success && errorCode != SocketError.WouldBlock && errorCode != SocketError.InProgress)
+                               is_connected = false;
+
                        /* If no socket error occurred, call CheckIfThrowDelayedException in
                         * case there are other kinds of exceptions that should be thrown.*/
-                       if ((errorCode = sockares.ErrorCode) == SocketError.Success)
+                       if (errorCode == SocketError.Success)
                                sockares.CheckIfThrowDelayedException ();
 
                        return sockares.Total;
                }
 
-               static int Send_internal (SafeSocketHandle safeHandle, WSABUF[] bufarray, SocketFlags flags, out int error)
+               static int Send_internal (SafeSocketHandle safeHandle, WSABUF[] bufarray, SocketFlags flags, out int error, bool blocking)
                {
-                       bool release = false;
                        try {
-                               safeHandle.DangerousAddRef (ref release);
-                               return Send_internal (safeHandle.DangerousGetHandle (), bufarray, flags, out error);
+                               safeHandle.RegisterForBlockingSyscall ();
+                               return Send_internal (safeHandle.DangerousGetHandle (), bufarray, flags, out error, blocking);
                        } finally {
-                               if (release)
-                                       safeHandle.DangerousRelease ();
+                               safeHandle.UnRegisterForBlockingSyscall ();
                        }
                }
 
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               extern static int Send_internal (IntPtr sock, WSABUF[] bufarray, SocketFlags flags, out int error);
+               extern static int Send_internal (IntPtr sock, WSABUF[] bufarray, SocketFlags flags, out int error, bool blocking);
 
-               static int Send_internal (SafeSocketHandle safeHandle, byte[] buf, int offset, int count, SocketFlags flags, out int error)
+               static int Send_internal (SafeSocketHandle safeHandle, byte[] buf, int offset, int count, SocketFlags flags, out int error, bool blocking)
                {
                        try {
                                safeHandle.RegisterForBlockingSyscall ();
-                               return Send_internal (safeHandle.DangerousGetHandle (), buf, offset, count, flags, out error);
+                               return Send_internal (safeHandle.DangerousGetHandle (), buf, offset, count, flags, out error, blocking);
                        } finally {
                                safeHandle.UnRegisterForBlockingSyscall ();
                        }
                }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               extern static int Send_internal(IntPtr sock, byte[] buf, int offset, int count, SocketFlags flags, out int error);
+               extern static int Send_internal(IntPtr sock, byte[] buf, int offset, int count, SocketFlags flags, out int error, bool blocking);
 
 #endregion
 
 #region SendTo
 
-               public int SendTo (byte [] buffer, EndPoint remoteEP)
-               {
-                       ThrowIfDisposedAndClosed ();
-                       ThrowIfBufferNull (buffer);
-
-                       return SendTo (buffer, 0, buffer.Length, SocketFlags.None, remoteEP);
-               }
-
-               public int SendTo (byte [] buffer, SocketFlags socketFlags, EndPoint remoteEP)
-               {
-                       ThrowIfDisposedAndClosed ();
-                       ThrowIfBufferNull (buffer);
-
-                       return SendTo (buffer, 0, buffer.Length, socketFlags, remoteEP);
-               }
-
-               public int SendTo (byte [] buffer, int size, SocketFlags socketFlags, EndPoint remoteEP)
-               {
-                       return SendTo (buffer, 0, size, socketFlags, remoteEP);
-               }
-
                public int SendTo (byte [] buffer, int offset, int size, SocketFlags socketFlags, EndPoint remoteEP)
                {
                        ThrowIfDisposedAndClosed ();
@@ -2718,7 +2017,21 @@ namespace System.Net.Sockets
                        if (remoteEP == null)
                                throw new ArgumentNullException("remoteEP");
 
-                       return SendTo_nochecks (buffer, offset, size, socketFlags, remoteEP);
+                       int error;
+                       int ret = SendTo_internal (m_Handle, buffer, offset, size, socketFlags, remoteEP.Serialize (), out error, is_blocking);
+
+                       SocketError err = (SocketError) error;
+                       if (err != 0) {
+                               if (err != SocketError.WouldBlock && err != SocketError.InProgress)
+                                       is_connected = false;
+                               throw new SocketException (error);
+                       }
+
+                       is_connected = true;
+                       is_bound = true;
+                       seed_endpoint = remoteEP;
+
+                       return ret;
                }
 
                public bool SendToAsync (SocketAsyncEventArgs e)
@@ -2740,7 +2053,7 @@ namespace System.Net.Sockets
                        e.socket_async_result.SockFlags = e.SocketFlags;
                        e.socket_async_result.EndPoint = e.RemoteEndPoint;
 
-                       QueueIOSelectorJob (writeQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendToCallback ((SocketAsyncResult) s, 0), e.socket_async_result));
+                       QueueIOSelectorJob (WriteSem, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendToCallback ((SocketAsyncResult) s, 0), e.socket_async_result));
 
                        return true;
                }
@@ -2762,7 +2075,7 @@ namespace System.Net.Sockets
                        }
                });
 
-               public IAsyncResult BeginSendTo(byte[] buffer, int offset, int size, SocketFlags socket_flags, EndPoint remote_end, AsyncCallback callback, object state)
+               public IAsyncResult BeginSendTo(byte[] buffer, int offset, int size, SocketFlags socketFlags, EndPoint remoteEP, AsyncCallback callback, object state)
                {
                        ThrowIfDisposedAndClosed ();
                        ThrowIfBufferNull (buffer);
@@ -2772,11 +2085,11 @@ namespace System.Net.Sockets
                                Buffer = buffer,
                                Offset = offset,
                                Size = size,
-                               SockFlags = socket_flags,
-                               EndPoint = remote_end,
+                               SockFlags = socketFlags,
+                               EndPoint = remoteEP,
                        };
 
-                       QueueIOSelectorJob (writeQ, sockares.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendToCallback ((SocketAsyncResult) s, 0), sockares));
+                       QueueIOSelectorJob (WriteSem, sockares.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendToCallback ((SocketAsyncResult) s, 0), sockares));
 
                        return sockares;
                }
@@ -2785,7 +2098,7 @@ namespace System.Net.Sockets
                {
                        int total = 0;
                        try {
-                               total = sockares.socket.SendTo_nochecks (sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, sockares.EndPoint);
+                               total = sockares.socket.SendTo (sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, sockares.EndPoint);
 
                                if (sockares.error == 0) {
                                        sent_so_far += total;
@@ -2807,11 +2120,11 @@ namespace System.Net.Sockets
                        sockares.Complete ();
                }
 
-               public int EndSendTo (IAsyncResult result)
+               public int EndSendTo (IAsyncResult asyncResult)
                {
                        ThrowIfDisposedAndClosed ();
 
-                       SocketAsyncResult sockares = ValidateEndIAsyncResult (result, "EndSendTo", "result");
+                       SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndSendTo", "result");
 
                        if (!sockares.IsCompleted)
                                sockares.AsyncWaitHandle.WaitOne();
@@ -2821,54 +2134,23 @@ namespace System.Net.Sockets
                        return sockares.Total;
                }
 
-               int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags, EndPoint remote_end)
-               {
-                       int error;
-                       int ret = SendTo_internal (safe_handle, buffer, offset, size, flags, remote_end.Serialize (), out error);
-
-                       SocketError err = (SocketError) error;
-                       if (err != 0) {
-                               if (err != SocketError.WouldBlock && err != SocketError.InProgress)
-                                       is_connected = false;
-                               throw new SocketException (error);
-                       }
-
-                       is_connected = true;
-                       is_bound = true;
-                       seed_endpoint = remote_end;
-
-                       return ret;
-               }
-
-               static int SendTo_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, SocketAddress sa, out int error)
+               static int SendTo_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, SocketAddress sa, out int error, bool blocking)
                {
                        try {
                                safeHandle.RegisterForBlockingSyscall ();
-                               return SendTo_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, sa, out error);
+                               return SendTo_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, sa, out error, blocking);
                        } finally {
                                safeHandle.UnRegisterForBlockingSyscall ();
                        }
                }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               extern static int SendTo_internal (IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags, SocketAddress sa, out int error);
+               extern static int SendTo_internal (IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags, SocketAddress sa, out int error, bool blocking);
 
 #endregion
 
 #region SendFile
 
-               public void SendFile (string fileName)
-               {
-                       ThrowIfDisposedAndClosed ();
-
-                       if (!is_connected)
-                               throw new NotSupportedException ();
-                       if (!is_blocking)
-                               throw new InvalidOperationException ();
-
-                       SendFile (fileName, null, null, 0);
-               }
-
                public void SendFile (string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags)
                {
                        ThrowIfDisposedAndClosed ();
@@ -2878,26 +2160,15 @@ namespace System.Net.Sockets
                        if (!is_blocking)
                                throw new InvalidOperationException ();
 
-                       if (!SendFile_internal (safe_handle, fileName, preBuffer, postBuffer, flags)) {
-                               SocketException exc = new SocketException ();
+                       int error = 0;
+                       if (!SendFile_internal (m_Handle, fileName, preBuffer, postBuffer, flags, out error, is_blocking) || error != 0) {
+                               SocketException exc = new SocketException (error);
                                if (exc.ErrorCode == 2 || exc.ErrorCode == 3)
                                        throw new FileNotFoundException ();
                                throw exc;
                        }
                }
 
-               public IAsyncResult BeginSendFile (string fileName, AsyncCallback callback, object state)
-               {
-                       ThrowIfDisposedAndClosed ();
-
-                       if (!is_connected)
-                               throw new NotSupportedException ();
-                       if (!File.Exists (fileName))
-                               throw new FileNotFoundException ();
-
-                       return BeginSendFile (fileName, null, null, 0, callback, state);
-               }
-
                public IAsyncResult BeginSendFile (string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags, AsyncCallback callback, object state)
                {
                        ThrowIfDisposedAndClosed ();
@@ -2926,18 +2197,18 @@ namespace System.Net.Sockets
                        ares.Delegate.EndInvoke (ares.Original);
                }
 
-               static bool SendFile_internal (SafeSocketHandle safeHandle, string filename, byte [] pre_buffer, byte [] post_buffer, TransmitFileOptions flags)
+               static bool SendFile_internal (SafeSocketHandle safeHandle, string filename, byte [] pre_buffer, byte [] post_buffer, TransmitFileOptions flags, out int error, bool blocking)
                {
                        try {
                                safeHandle.RegisterForBlockingSyscall ();
-                               return SendFile_internal (safeHandle.DangerousGetHandle (), filename, pre_buffer, post_buffer, flags);
+                               return SendFile_internal (safeHandle.DangerousGetHandle (), filename, pre_buffer, post_buffer, flags, out error, blocking);
                        } finally {
                                safeHandle.UnRegisterForBlockingSyscall ();
                        }
                }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               extern static bool SendFile_internal (IntPtr sock, string filename, byte [] pre_buffer, byte [] post_buffer, TransmitFileOptions flags);
+               extern static bool SendFile_internal (IntPtr sock, string filename, byte [] pre_buffer, byte [] post_buffer, TransmitFileOptions flags, out int error, bool blocking);
 
                delegate void SendFileHandler (string fileName, byte [] preBuffer, byte [] postBuffer, TransmitFileOptions flags);
 
@@ -2994,7 +2265,6 @@ namespace System.Net.Sockets
 
 #region DuplicateAndClose
 
-#if !MOBILE
                [MonoLimitation ("We do not support passing sockets across processes, we merely allow this API to pass the socket across AppDomains")]
                public SocketInformation DuplicateAndClose (int targetProcessId)
                {
@@ -3003,14 +2273,18 @@ namespace System.Net.Sockets
                                (is_listening      ? SocketInformationOptions.Listening : 0) |
                                (is_connected      ? SocketInformationOptions.Connected : 0) |
                                (is_blocking       ? 0 : SocketInformationOptions.NonBlocking) |
-                               (use_overlapped_io ? SocketInformationOptions.UseOnlyOverlappedIO : 0);
+                               (useOverlappedIO ? SocketInformationOptions.UseOnlyOverlappedIO : 0);
 
-                       si.ProtocolInformation = Mono.DataConverter.Pack ("iiiil", (int)address_family, (int)socket_type, (int)protocol_type, is_bound ? 1 : 0, (long)Handle);
-                       safe_handle = null;
+                       MonoIOError error;
+                       IntPtr duplicateHandle;
+                       if (!MonoIO.DuplicateHandle (System.Diagnostics.Process.GetCurrentProcess ().Handle, Handle, new IntPtr (targetProcessId), out duplicateHandle, 0, 0, 0x00000002 /* DUPLICATE_SAME_ACCESS */, out error))
+                               throw MonoIO.GetException (error);
 
-                       return si;
+                       si.ProtocolInformation = Mono.DataConverter.Pack ("iiiil", (int)addressFamily, (int)socketType, (int)protocolType, is_bound ? 1 : 0, (long)duplicateHandle);
+                       m_Handle = null;
+                       return si;
                }
-#endif
 
 #endregion
 
@@ -3024,7 +2298,7 @@ namespace System.Net.Sockets
                                throw new SocketException ((int) SocketError.Fault, "Error trying to dereference an invalid pointer");
 
                        int error;
-                       GetSocketOption_arr_internal (safe_handle, optionLevel, optionName, ref optionValue, out error);
+                       GetSocketOption_arr_internal (m_Handle, optionLevel, optionName, ref optionValue, out error);
 
                        if (error != 0)
                                throw new SocketException (error);
@@ -3036,7 +2310,7 @@ namespace System.Net.Sockets
 
                        int error;
                        byte[] byte_val = new byte [optionLength];
-                       GetSocketOption_arr_internal (safe_handle, optionLevel, optionName, ref byte_val, out error);
+                       GetSocketOption_arr_internal (m_Handle, optionLevel, optionName, ref byte_val, out error);
 
                        if (error != 0)
                                throw new SocketException (error);
@@ -3050,7 +2324,7 @@ namespace System.Net.Sockets
 
                        int error;
                        object obj_val;
-                       GetSocketOption_obj_internal (safe_handle, optionLevel, optionName, out obj_val, out error);
+                       GetSocketOption_obj_internal (m_Handle, optionLevel, optionName, out obj_val, out error);
 
                        if (error != 0)
                                throw new SocketException (error);
@@ -3108,7 +2382,7 @@ namespace System.Net.Sockets
                                throw new SocketException ((int) SocketError.Fault, "Error trying to dereference an invalid pointer");
 
                        int error;
-                       SetSocketOption_internal (safe_handle, optionLevel, optionName, null, optionValue, 0, out error);
+                       SetSocketOption_internal (m_Handle, optionLevel, optionName, null, optionValue, 0, out error);
 
                        if (error != 0) {
                                if (error == (int) SocketError.InvalidArgument)
@@ -3131,17 +2405,17 @@ namespace System.Net.Sockets
                                LingerOption linger = optionValue as LingerOption;
                                if (linger == null)
                                        throw new ArgumentException ("A 'LingerOption' value must be specified.", "optionValue");
-                               SetSocketOption_internal (safe_handle, optionLevel, optionName, linger, null, 0, out error);
+                               SetSocketOption_internal (m_Handle, optionLevel, optionName, linger, null, 0, out error);
                        } else if (optionLevel == SocketOptionLevel.IP && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
                                MulticastOption multicast = optionValue as MulticastOption;
                                if (multicast == null)
                                        throw new ArgumentException ("A 'MulticastOption' value must be specified.", "optionValue");
-                               SetSocketOption_internal (safe_handle, optionLevel, optionName, multicast, null, 0, out error);
+                               SetSocketOption_internal (m_Handle, optionLevel, optionName, multicast, null, 0, out error);
                        } else if (optionLevel == SocketOptionLevel.IPv6 && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
                                IPv6MulticastOption multicast = optionValue as IPv6MulticastOption;
                                if (multicast == null)
                                        throw new ArgumentException ("A 'IPv6MulticastOption' value must be specified.", "optionValue");
-                               SetSocketOption_internal (safe_handle, optionLevel, optionName, multicast, null, 0, out error);
+                               SetSocketOption_internal (m_Handle, optionLevel, optionName, multicast, null, 0, out error);
                        } else {
                                throw new ArgumentException ("Invalid value specified.", "optionValue");
                        }
@@ -3164,11 +2438,8 @@ namespace System.Net.Sockets
                {
                        ThrowIfDisposedAndClosed ();
 
-                       if (optionLevel == SocketOptionLevel.Socket && optionName == SocketOptionName.ReuseAddress && optionValue != 0 && !SupportsPortReuse (protocol_type))
-                               throw new SocketException ((int) SocketError.OperationNotSupported, "Operating system sockets do not support ReuseAddress.\nIf your socket is not intended to bind to the same address and port multiple times remove this option, otherwise you should ignore this exception inside a try catch and check that ReuseAddress is true before binding to the same address and port multiple times.");
-
                        int error;
-                       SetSocketOption_internal (safe_handle, optionLevel, optionName, null, null, optionValue, out error);
+                       SetSocketOption_internal (m_Handle, optionLevel, optionName, null, null, optionValue, out error);
 
                        if (error != 0) {
                                if (error == (int) SocketError.InvalidArgument)
@@ -3198,11 +2469,11 @@ namespace System.Net.Sockets
 
                public int IOControl (int ioControlCode, byte [] optionInValue, byte [] optionOutValue)
                {
-                       if (is_disposed)
+                       if (CleanedUp)
                                throw new ObjectDisposedException (GetType ().ToString ());
 
                        int error;
-                       int result = IOControl_internal (safe_handle, ioControlCode, optionInValue, optionOutValue, out error);
+                       int result = IOControl_internal (m_Handle, ioControlCode, optionInValue, optionOutValue, out error);
 
                        if (error != 0)
                                throw new SocketException (error);
@@ -3212,11 +2483,6 @@ namespace System.Net.Sockets
                        return result;
                }
 
-               public int IOControl (IOControlCode ioControlCode, byte[] optionInValue, byte[] optionOutValue)
-               {
-                       return IOControl ((int) ioControlCode, optionInValue, optionOutValue);
-               }
-
                static int IOControl_internal (SafeSocketHandle safeHandle, int ioctl_code, byte [] input, byte [] output, out int error)
                {
                        bool release = false;
@@ -3266,7 +2532,7 @@ namespace System.Net.Sockets
                                throw new SocketException (10057); // Not connected
 
                        int error;
-                       Shutdown_internal (safe_handle, how, out error);
+                       Shutdown_internal (m_Handle, how, out error);
 
                        if (error != 0)
                                throw new SocketException (error);
@@ -3293,30 +2559,24 @@ namespace System.Net.Sockets
 
                protected virtual void Dispose (bool disposing)
                {
-                       if (is_disposed)
+                       if (CleanedUp)
                                return;
 
-                       is_disposed = true;
+                       m_IntCleanedUp = 1;
                        bool was_connected = is_connected;
                        is_connected = false;
 
-                       if (safe_handle != null) {
+                       if (m_Handle != null) {
                                is_closed = true;
                                IntPtr x = Handle;
 
                                if (was_connected)
                                        Linger (x);
 
-                               safe_handle.Dispose ();
+                               m_Handle.Dispose ();
                        }
                }
 
-               public void Dispose ()
-               {
-                       Dispose (true);
-                       GC.SuppressFinalize (this);
-               }
-
                void Linger (IntPtr handle)
                {
                        if (!is_connected || linger_timeout <= 0)
@@ -3351,13 +2611,13 @@ namespace System.Net.Sockets
 
                void ThrowIfDisposedAndClosed (Socket socket)
                {
-                       if (socket.is_disposed && socket.is_closed)
+                       if (socket.CleanedUp && socket.is_closed)
                                throw new ObjectDisposedException (socket.GetType ().ToString ());
                }
 
                void ThrowIfDisposedAndClosed ()
                {
-                       if (is_disposed && is_closed)
+                       if (CleanedUp && is_closed)
                                throw new ObjectDisposedException (GetType ().ToString ());
                }
 
@@ -3381,7 +2641,7 @@ namespace System.Net.Sockets
 
                void ThrowIfUdp ()
                {
-                       if (protocol_type == ProtocolType.Udp)
+                       if (protocolType == ProtocolType.Udp)
                                throw new SocketException ((int)SocketError.ProtocolOption);
                }
 
@@ -3399,16 +2659,27 @@ namespace System.Net.Sockets
                        return sockares;
                }
 
-               void QueueIOSelectorJob (Queue<KeyValuePair<IntPtr, IOSelectorJob>> queue, IntPtr handle, IOSelectorJob job)
+               void QueueIOSelectorJob (SemaphoreSlim sem, IntPtr handle, IOSelectorJob job)
                {
-                       int count;
-                       lock (queue) {
-                               queue.Enqueue (new KeyValuePair<IntPtr, IOSelectorJob> (handle, job));
-                               count = queue.Count;
-                       }
-
-                       if (count == 1)
+                       var task = sem.WaitAsync();
+                       // fast path without Task<Action> allocation.
+                       if (task.IsCompleted) {
+                               if (CleanedUp) {
+                                       job.MarkDisposed ();
+                                       return;
+                               }
                                IOSelector.Add (handle, job);
+                       }
+                       else
+                       {
+                               task.ContinueWith( t => {
+                                       if (CleanedUp) {
+                                               job.MarkDisposed ();
+                                               return;
+                                       }
+                                       IOSelector.Add(handle, job);
+                               });
+                       }
                }
 
                void InitSocketAsyncEventArgs (SocketAsyncEventArgs e, AsyncCallback callback, object state, SocketOperation operation)
@@ -3466,6 +2737,41 @@ namespace System.Net.Sockets
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                internal static extern bool SupportsPortReuse (ProtocolType proto);
+
+               internal static int FamilyHint {
+                       get {
+                               // Returns one of
+                               //      MONO_HINT_UNSPECIFIED           = 0,
+                               //      MONO_HINT_IPV4                          = 1,
+                               //      MONO_HINT_IPV6                          = 2,
+
+                               int hint = 0;
+                               if (OSSupportsIPv4) {
+                                       hint = 1;
+                               }
+
+                               if (OSSupportsIPv6) {
+                                       hint = hint == 0 ? 2 : 0;
+                               }
+
+                               return hint;
+                       }
+               }
+
+               static bool IsProtocolSupported (NetworkInterfaceComponent networkInterface)
+               {
+#if MOBILE
+                       return true;
+#else
+                       var nics = NetworkInterface.GetAllNetworkInterfaces ();
+                       foreach (var adapter in nics) {
+                               if (adapter.Supports (networkInterface))
+                                       return true;
+                       }
+
+                       return false;
+#endif
+               }
        }
 }