Merge pull request #409 from Alkarex/patch-1
[mono.git] / mcs / class / System / System.Net.Sockets / Socket.cs
index 78c81620b7902816fdab616c5a576e7723e95435..763bc3462f422e907943bb3439a3aa1fb0478b2c 100644 (file)
@@ -9,7 +9,7 @@
 //
 // Copyright (C) 2001, 2002 Phillip Pearson and Ximian, Inc.
 //    http://www.myelin.co.nz
-// (c) 2004-2006 Novell, Inc. (http://www.novell.com)
+// (c) 2004-2011 Novell, Inc. (http://www.novell.com)
 //
 
 //
@@ -36,6 +36,7 @@
 using System;
 using System.Net;
 using System.Collections;
+using System.Collections.Generic;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Threading;
@@ -43,573 +44,20 @@ using System.Reflection;
 using System.IO;
 using System.Net.Configuration;
 using System.Text;
-
-#if NET_2_0
-using System.Collections.Generic;
-using System.Net.NetworkInformation;
-#if !NET_2_1
 using System.Timers;
-#endif
+#if !MOONLIGHT
+using System.Net.NetworkInformation;
 #endif
 
 namespace System.Net.Sockets 
 {
        public partial class Socket : IDisposable
        {
-               enum SocketOperation {
-                       Accept,
-                       Connect,
-                       Receive,
-                       ReceiveFrom,
-                       Send,
-                       SendTo,
-                       UsedInManaged1,
-                       UsedInManaged2,
-                       UsedInProcess,
-                       UsedInConsole2,
-                       Disconnect,
-                       AcceptReceive,
-                       ReceiveGeneric,
-                       SendGeneric
-               }
-
-               [StructLayout (LayoutKind.Sequential)]
-               struct WSABUF 
-               {
-                       public int len;
-                       public IntPtr buf;
-               };
-
-               [StructLayout (LayoutKind.Sequential)]
-               private sealed class SocketAsyncResult: IAsyncResult
-               {
-                       /* Same structure in the runtime */
-                       /*
-                         Keep this in sync with MonoSocketAsyncResult in
-                         metadata/socket-io.h and ProcessAsyncReader
-                         in System.Diagnostics/Process.cs.
-                       */
-
-                       public Socket Sock;
-                       public IntPtr handle;
-                       object state;
-                       AsyncCallback callback;
-                       WaitHandle waithandle;
-
-                       Exception delayedException;
-
-                       public EndPoint EndPoint;       // Connect,ReceiveFrom,SendTo
-                       public byte [] Buffer;          // Receive,ReceiveFrom,Send,SendTo
-                       public int Offset;              // Receive,ReceiveFrom,Send,SendTo
-                       public int Size;                // Receive,ReceiveFrom,Send,SendTo
-                       public SocketFlags SockFlags;   // Receive,ReceiveFrom,Send,SendTo
-                       public Socket AcceptSocket;     // AcceptReceive
-                       public IPAddress[] Addresses;   // Connect
-                       public int Port;                // Connect
-#if NET_2_0
-                       public IList<ArraySegment<byte>> Buffers;       // Receive, Send
-#else
-                       public object Buffers;          // Reserve this slot in older profiles
-#endif
-                       public bool ReuseSocket;        // Disconnect
-
-                       // Return values
-                       Socket acc_socket;
-                       int total;
-
-                       bool completed_sync;
-                       bool completed;
-                       public bool blocking;
-                       internal int error;
-                       SocketOperation operation;
-                       public object ares;
-                       public int EndCalled;
-
-                       public SocketAsyncResult (Socket sock, object state, AsyncCallback callback, SocketOperation operation)
-                       {
-                               this.Sock = sock;
-                               this.blocking = sock.blocking;
-                               this.handle = sock.socket;
-                               this.state = state;
-                               this.callback = callback;
-                               this.operation = operation;
-                               SockFlags = SocketFlags.None;
-                       }
-
-                       public void CheckIfThrowDelayedException ()
-                       {
-                               if (delayedException != null) {
-                                       Sock.connected = false;
-                                       throw delayedException;
-                               }
-
-                               if (error != 0) {
-                                       Sock.connected = false;
-                                       throw new SocketException (error);
-                               }
-                       }
-
-                       void CompleteAllOnDispose (Queue queue)
-                       {
-                               object [] pending = queue.ToArray ();
-                               queue.Clear ();
-
-                               WaitCallback cb;
-                               for (int i = 0; i < pending.Length; i++) {
-                                       SocketAsyncResult ares = (SocketAsyncResult) pending [i];
-                                       cb = new WaitCallback (ares.CompleteDisposed);
-                                       ThreadPool.QueueUserWorkItem (cb, null);
-                               }
-                               if (pending.Length == 0)
-                                       Buffer = null;
-                       }
-
-                       void CompleteDisposed (object unused)
-                       {
-                               Complete ();
-                       }
-
-                       public void Complete ()
-                       {
-                               if (operation != SocketOperation.Receive && Sock.disposed)
-                                       delayedException = new ObjectDisposedException (Sock.GetType ().ToString ());
-
-                               IsCompleted = true;
-
-                               Queue queue = null;
-                               if (operation == SocketOperation.Receive || operation == SocketOperation.ReceiveFrom) {
-                                       queue = Sock.readQ;
-                               } else if (operation == SocketOperation.Send || operation == SocketOperation.SendTo) {
-                                       queue = Sock.writeQ;
-                               }
-
-                               if (queue != null) {
-                                       SocketAsyncCall sac = null;
-                                       SocketAsyncResult req = null;
-                                       lock (queue) {
-                                               queue.Dequeue (); // remove ourselves
-                                               if (queue.Count > 0) {
-                                                       req = (SocketAsyncResult) queue.Peek ();
-                                                       if (!Sock.disposed) {
-                                                               Worker worker = new Worker (req);
-                                                               sac = GetDelegate (worker, req.operation);
-                                                       } else {
-                                                               CompleteAllOnDispose (queue);
-                                                       }
-                                               }
-                                       }
-
-                                       if (sac != null)
-                                               sac.BeginInvoke (null, req);
-                               }
-
-                               if (callback != null)
-                                       callback (this);
-                               Buffer = null;
-                       }
-
-                       SocketAsyncCall GetDelegate (Worker worker, SocketOperation op)
-                       {
-                               switch (op) {
-                               case SocketOperation.Receive:
-                                       return new SocketAsyncCall (worker.Receive);
-                               case SocketOperation.ReceiveFrom:
-                                       return new SocketAsyncCall (worker.ReceiveFrom);
-                               case SocketOperation.Send:
-                                       return new SocketAsyncCall (worker.Send);
-                               case SocketOperation.SendTo:
-                                       return new SocketAsyncCall (worker.SendTo);
-                               default:
-                                       return null; // never happens
-                               }
-                       }
-
-                       public void Complete (bool synch)
-                       {
-                               completed_sync = synch;
-                               Complete ();
-                       }
-
-                       public void Complete (int total)
-                       {
-                               this.total = total;
-                               Complete ();
-                       }
-
-                       public void Complete (Exception e, bool synch)
-                       {
-                               completed_sync = synch;
-                               delayedException = e;
-                               Complete ();
-                       }
-
-                       public void Complete (Exception e)
-                       {
-                               delayedException = e;
-                               Complete ();
-                       }
-
-                       public void Complete (Socket s)
-                       {
-                               acc_socket = s;
-                               Complete ();
-                       }
-
-                       public void Complete (Socket s, int total)
-                       {
-                               acc_socket = s;
-                               this.total = total;
-                               Complete ();
-                       }
-
-                       public object AsyncState {
-                               get {
-                                       return state;
-                               }
-                       }
-
-                       public WaitHandle AsyncWaitHandle {
-                               get {
-                                       lock (this) {
-                                               if (waithandle == null)
-                                                       waithandle = new ManualResetEvent (completed);
-                                       }
-
-                                       return waithandle;
-                               }
-                               set {
-                                       waithandle=value;
-                               }
-                       }
-
-                       public bool CompletedSynchronously {
-                               get {
-                                       return(completed_sync);
-                               }
-                       }
-
-                       public bool IsCompleted {
-                               get {
-                                       return(completed);
-                               }
-                               set {
-                                       completed=value;
-                                       lock (this) {
-                                               if (waithandle != null && value) {
-                                                       ((ManualResetEvent) waithandle).Set ();
-                                               }
-                                       }
-                               }
-                       }
-                       
-                       public Socket Socket {
-                               get {
-                                       return acc_socket;
-                               }
-                       }
-
-                       public int Total {
-                               get { return total; }
-                               set { total = value; }
-                       }
-
-                       public SocketError ErrorCode
-                       {
-                               get {
-#if NET_2_0
-                                       SocketException ex = delayedException as SocketException;
-                                       
-                                       if (ex != null)
-                                               return(ex.SocketErrorCode);
-
-                                       if (error != 0)
-                                               return((SocketError)error);
-#endif
-                                       return(SocketError.Success);
-                               }
-                       }
-               }
-
-               private sealed class Worker 
-               {
-                       SocketAsyncResult result;
-
-                       public Worker (SocketAsyncResult ares)
-                       {
-                               this.result = ares;
-                       }
-
-                       public void Accept ()
-                       {
-                               Socket acc_socket = null;
-                               try {
-                                       acc_socket = result.Sock.Accept ();
-                               } catch (Exception e) {
-                                       result.Complete (e);
-                                       return;
-                               }
-
-                               result.Complete (acc_socket);
-                       }
-
-                       /* only used in 2.0 profile and newer, but
-                        * leave in older profiles to keep interface
-                        * to runtime consistent
-                        */
-                       public void AcceptReceive ()
-                       {
-                               Socket acc_socket = null;
-                               
-                               try {
-                                       if (result.AcceptSocket == null) {
-                                               acc_socket = result.Sock.Accept ();
-                                       } else {
-                                               acc_socket = result.AcceptSocket;
-                                               result.Sock.Accept (acc_socket);
-                                       }
-                               } catch (Exception e) {
-                                       result.Complete (e);
-                                       return;
-                               }
-
-                               /* It seems the MS runtime
-                                * special-cases 0-length requested
-                                * receive data.  See bug 464201.
-                                */
-                               int total = 0;
-                               if (result.Size > 0) {
-                                       try {
-                                               SocketError error;
-                                       
-                                               total = acc_socket.Receive_nochecks (result.Buffer,
-                                                                                    result.Offset,
-                                                                                    result.Size,
-                                                                                    result.SockFlags,
-                                                                                    out error);
-                                       } catch (Exception e) {
-                                               result.Complete (e);
-                                               return;
-                                       }
-                               }
-
-                               result.Complete (acc_socket, total);
-                       }
-
-                       public void Connect ()
-                       {
-                               /* If result.EndPoint is non-null,
-                                * this is the standard one-address
-                                * connect attempt.  Otherwise
-                                * Addresses must be non-null and
-                                * contain a list of addresses to try
-                                * to connect to; the first one to
-                                * succeed causes the rest of the list
-                                * to be ignored.
-                                */
-                               if (result.EndPoint != null) {
-                                       try {
-                                               if (!result.Sock.Blocking) {
-                                                       int success;
-                                                       result.Sock.Poll (-1, SelectMode.SelectWrite, out success);
-                                                       if (success == 0) {
-                                                               result.Sock.connected = true;
-                                                       } else {
-                                                               result.Complete (new SocketException (success));
-                                                               return;
-                                                       }
-                                               } else {
-                                                       result.Sock.seed_endpoint = result.EndPoint;
-                                                       result.Sock.Connect (result.EndPoint);
-                                                       result.Sock.connected = true;
-                                               }
-                                       } catch (Exception e) {
-                                               result.Complete (e);
-                                               return;
-                                       }
-
-                                       result.Complete ();
-                               } else if (result.Addresses != null) {
-                                       foreach(IPAddress address in result.Addresses) {
-                                               IPEndPoint iep = new IPEndPoint (address, result.Port);
-                                               SocketAddress serial = iep.Serialize ();
-                                               int error = 0;
-                                               
-                                               Socket.Connect_internal (result.Sock.socket, serial, out error);
-                                               if (error == 0) {
-                                                       result.Sock.connected = true;
-                                                       result.Sock.seed_endpoint = iep;
-                                                       result.Complete ();
-                                                       return;
-                                               } else if (error != (int)SocketError.InProgress &&
-                                                          error != (int)SocketError.WouldBlock) {
-                                                       continue;
-                                               }
-
-                                               if (!result.Sock.Blocking) {
-                                                       int success;
-                                                       result.Sock.Poll (-1, SelectMode.SelectWrite, out success);
-                                                       if (success == 0) {
-                                                               result.Sock.connected = true;
-                                                               result.Sock.seed_endpoint = iep;
-                                                               result.Complete ();
-                                                               return;
-                                                       }
-                                               }
-                                       }
-                                       
-                                       result.Complete (new SocketException ((int)SocketError.InProgress));
-                               } else {
-                                       result.Complete (new SocketException ((int)SocketError.AddressNotAvailable));
-                               }
-                       }
-
-                       /* Also only used in 2.0 profile and newer */
-                       public void Disconnect ()
-                       {
-#if NET_2_0
-                               try {
-                                       result.Sock.Disconnect (result.ReuseSocket);
-                               } catch (Exception e) {
-                                       result.Complete (e);
-                                       return;
-                               }
-                               result.Complete ();
-#else
-                               result.Complete (new SocketException ((int)SocketError.Fault));
-#endif
-                       }
-
-                       public void Receive ()
-                       {
-                               // Actual recv() done in the runtime
-                               result.Complete ();
-                       }
-
-                       public void ReceiveFrom ()
-                       {
-                               int total = 0;
-                               try {
-                                       total = result.Sock.ReceiveFrom_nochecks (result.Buffer,
-                                                                        result.Offset,
-                                                                        result.Size,
-                                                                        result.SockFlags,
-                                                                        ref result.EndPoint);
-                               } catch (Exception e) {
-                                       result.Complete (e);
-                                       return;
-                               }
-
-                               result.Complete (total);
-                       }
-
-                       public void ReceiveGeneric ()
-                       {
-#if NET_2_0
-                               int total = 0;
-                               try {
-                                       SocketError error;
-                                       
-                                       total = result.Sock.Receive (result.Buffers, result.SockFlags, out error);
-                               } catch (Exception e) {
-                                       result.Complete (e);
-                                       return;
-                               }
-                               
-                               result.Complete (total);
-#else
-                               result.Complete (new SocketException ((int)SocketError.Fault));
-#endif
-                       }
-
-                       int send_so_far;
-
-                       void UpdateSendValues (int last_sent)
-                       {
-                               if (result.error == 0) {
-                                       send_so_far += last_sent;
-                                       result.Offset += last_sent;
-                                       result.Size -= last_sent;
-                               }
-                       }
-
-                       public void Send ()
-                       {
-                               // Actual send() done in the runtime
-                               if (result.error == 0) {
-                                       UpdateSendValues (result.Total);
-                                       if (result.Sock.disposed) {
-                                               result.Complete ();
-                                               return;
-                                       }
-
-                                       if (result.Size > 0) {
-                                               SocketAsyncCall sac = new SocketAsyncCall (this.Send);
-                                               sac.BeginInvoke (null, result);
-                                               return; // Have to finish writing everything. See bug #74475.
-                                       }
-                                       result.Total = send_so_far;
-                               }
-                               result.Complete ();
-                       }
-
-                       public void SendTo ()
-                       {
-                               int total = 0;
-                               try {
-                                       total = result.Sock.SendTo_nochecks (result.Buffer,
-                                                                   result.Offset,
-                                                                   result.Size,
-                                                                   result.SockFlags,
-                                                                   result.EndPoint);
-
-                                       UpdateSendValues (total);
-                                       if (result.Size > 0) {
-                                               SocketAsyncCall sac = new SocketAsyncCall (this.SendTo);
-                                               sac.BeginInvoke (null, result);
-                                               return; // Have to finish writing everything. See bug #74475.
-                                       }
-                                       result.Total = send_so_far;
-                               } catch (Exception e) {
-                                       result.Complete (e);
-                                       return;
-                               }
-
-                               result.Complete ();
-                       }
-
-                       public void SendGeneric ()
-                       {
-#if NET_2_0
-                               int total = 0;
-                               try {
-                                       SocketError error;
-                                       
-                                       total = result.Sock.Send (result.Buffers, result.SockFlags, out error);
-                               } catch (Exception e) {
-                                       result.Complete (e);
-                                       return;
-                               }
-                               
-                               result.Complete (total);
-#else
-                               result.Complete (new SocketException ((int)SocketError.Fault));
-#endif
-                       }
-               }
-                       
-
-               private Queue readQ = new Queue (2);
-               private Queue writeQ = new Queue (2);
-
-               delegate void SocketAsyncCall ();
-
-#if NET_2_0
                private bool islistening;
                private bool useoverlappedIO;
-#endif
-               
+               private const int SOCKET_CLOSED = 10004;
 
-               static void AddSockets (ArrayList sockets, IList list, string name)
+               static void AddSockets (List<Socket> sockets, IList list, string name)
                {
                        if (list != null) {
                                foreach (Socket sock in list) {
@@ -629,7 +77,7 @@ namespace System.Net.Sockets
 #endif
                public static void Select (IList checkRead, IList checkWrite, IList checkError, int microSeconds)
                {
-                       ArrayList list = new ArrayList ();
+                       var list = new List<Socket> ();
                        AddSockets (list, checkRead, "checkRead");
                        AddSockets (list, checkWrite, "checkWrite");
                        AddSockets (list, checkError, "checkError");
@@ -645,7 +93,7 @@ namespace System.Net.Sockets
                         *                               WRITE socket 0-n, null,
                         *                               ERROR socket 0-n, null
                         */
-                       Socket [] sockets = (Socket []) list.ToArray (typeof (Socket));
+                       Socket [] sockets = list.ToArray ();
                        Select_internal (ref sockets, microSeconds, out error);
 
                        if (error != 0)
@@ -666,7 +114,6 @@ namespace System.Net.Sockets
                        IList currentList = checkRead;
                        int currentIdx = 0;
                        for (int i = 0; i < count; i++) {
-                               Socket cur_sock;
                                Socket sock = sockets [i];
                                if (sock == null) { // separator
                                        if (currentList != null) {
@@ -687,8 +134,8 @@ namespace System.Net.Sockets
                                }
 
                                // Remove non-signaled sockets before the current one
-                               int max = currentList.Count;
-                               while ((cur_sock = (Socket) currentList [currentIdx]) != sock) {
+                               //int max = currentList.Count;
+                               while (((Socket) currentList [currentIdx]) != sock) {
                                        currentList.RemoveAt (currentIdx);
                                }
                                currentIdx++;
@@ -697,7 +144,7 @@ namespace System.Net.Sockets
 
                // private constructor used by Accept, which already
                // has a socket handle to use
-               private Socket(AddressFamily family, SocketType type,
+               internal Socket(AddressFamily family, SocketType type,
                               ProtocolType proto, IntPtr sock)
                {
                        address_family=family;
@@ -710,7 +157,6 @@ namespace System.Net.Sockets
 
                private void SocketDefaults ()
                {
-#if NET_2_0
                        try {
                                if (address_family == AddressFamily.InterNetwork /* Need to test IPv6 further ||
                                                                                   address_family == AddressFamily.InterNetworkV6 */) {
@@ -733,35 +179,28 @@ namespace System.Net.Sockets
                                //this.SendBufferSize = 8192;
                        } catch (SocketException) {
                        }
-#endif
                }
 
-
-#if NET_2_0
-               [MonoTODO]
+#if !MOBILE
                public Socket (SocketInformation socketInformation)
                {
-                       throw new NotImplementedException ("SocketInformation not figured out yet");
+                       var options = socketInformation.Options;
+                       islistening = (options & SocketInformationOptions.Listening) != 0;
+                       connected   = (options & SocketInformationOptions.Connected) != 0;
+                       blocking    = (options & SocketInformationOptions.NonBlocking) == 0;
+                       useoverlappedIO = (options & SocketInformationOptions.UseOnlyOverlappedIO) != 0;
 
-                       // ifdef to avoid the warnings.
-#if false
-                       //address_family = socketInformation.address_family;
-                       //socket_type = socketInformation.socket_type;
-                       //protocol_type = socketInformation.protocol_type;
-                       address_family = AddressFamily.InterNetwork;
-                       socket_type = SocketType.Stream;
-                       protocol_type = ProtocolType.IP;
+                       var result = Mono.DataConverter.Unpack ("iiiil", socketInformation.ProtocolInformation, 0);
                        
-                       int error;
-                       socket = Socket_internal (address_family, socket_type, protocol_type, out error);
-                       if (error != 0)
-                               throw new SocketException (error);
-
+                       address_family = (AddressFamily) (int) result [0];
+                       socket_type = (SocketType) (int) result [1];
+                       protocol_type = (ProtocolType) (int) result [2];
+                       isbound = (ProtocolType) (int) result [3] != 0;
+                       socket = (IntPtr) (long) result [4];
                        SocketDefaults ();
-#endif
                }
 #endif
-
+       
 #if !TARGET_JVM
                // Returns the amount of data waiting to be read on socket
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
@@ -785,7 +224,6 @@ namespace System.Net.Sockets
                }
 
 
-#if NET_2_0
                public bool DontFragment {
                        get {
                                if (disposed && closed) {
@@ -960,7 +398,6 @@ namespace System.Net.Sockets
                                useoverlappedIO = value;
                        }
                }
-#endif
 
                public IntPtr Handle {
                        get {
@@ -971,7 +408,7 @@ namespace System.Net.Sockets
 #if !TARGET_JVM
                // Returns the local endpoint details in addr and port
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               private extern static SocketAddress LocalEndPoint_internal(IntPtr socket, out int error);
+               private extern static SocketAddress LocalEndPoint_internal(IntPtr socket, int family, out int error);
 #endif
 
                // Wish:  support non-IP endpoints.
@@ -991,7 +428,7 @@ namespace System.Net.Sockets
                                SocketAddress sa;
                                int error;
                                
-                               sa=LocalEndPoint_internal(socket, out error);
+                               sa=LocalEndPoint_internal(socket, (int) address_family, out error);
 
                                if (error != 0)
                                        throw new SocketException (error);
@@ -1006,7 +443,6 @@ namespace System.Net.Sockets
                        }
                }
 
-#if NET_2_0
                public int SendTimeout {
                        get {
                                if (disposed && closed)
@@ -1063,6 +499,7 @@ namespace System.Net.Sockets
                        }
                }
 
+#if !MOONLIGHT
                public bool AcceptAsync (SocketAsyncEventArgs e)
                {
                        // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
@@ -1077,26 +514,26 @@ namespace System.Net.Sockets
                                throw new ArgumentException ("Multiple buffers cannot be used with this method.");
                        if (e.Count < 0)
                                throw new ArgumentOutOfRangeException ("e.Count");
-                       
+
                        Socket acceptSocket = e.AcceptSocket;
                        if (acceptSocket != null) {
                                if (acceptSocket.IsBound || acceptSocket.Connected)
                                        throw new InvalidOperationException ("AcceptSocket: The socket must not be bound or connected.");
-                       } else
-                               e.AcceptSocket = new Socket (AddressFamily, SocketType, ProtocolType);
-
-                       try {
-                               e.DoOperation (SocketAsyncOperation.Accept, this);
-                       } catch {
-                               ((IDisposable)e).Dispose ();
-                               throw;
                        }
 
-                       // We always return true for now
+                       e.curSocket = this;
+                       Worker w = e.Worker;
+                       w.Init (this, e, SocketOperation.Accept);
+                       int count;
+                       lock (readQ) {
+                               readQ.Enqueue (e.Worker);
+                               count = readQ.Count;
+                       }
+                       if (count == 1)
+                               socket_pool_queue (Worker.Dispatcher, w.result);
                        return true;
                }
 #endif
-               
                // Creates a new system socket, returning the handle
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                private extern static IntPtr Accept_internal(IntPtr sock, out int error, bool blocking);
@@ -1107,23 +544,19 @@ namespace System.Net.Sockets
 
                        int error = 0;
                        IntPtr sock = (IntPtr) (-1);
-                       blocking_thread = Thread.CurrentThread;
                        try {
+                               RegisterForBlockingSyscall ();
                                sock = Accept_internal(socket, out error, blocking);
-                       } catch (ThreadAbortException) {
-                               if (disposed) {
-#if !NET_2_1
-                                       Thread.ResetAbort ();
-#endif
-                                       error = (int) SocketError.Interrupted;
-                               }
                        } finally {
-                               blocking_thread = null;
+                               UnRegisterForBlockingSyscall ();
+                       }
+
+                       if (error != 0) {
+                               if (closed)
+                                       error = SOCKET_CLOSED;
+                               throw new SocketException(error);
                        }
 
-                       if (error != 0)
-                               throw new SocketException (error);
-                       
                        Socket accepted = new Socket(this.AddressFamily, this.SocketType,
                                this.ProtocolType, sock);
 
@@ -1139,23 +572,19 @@ namespace System.Net.Sockets
                        
                        int error = 0;
                        IntPtr sock = (IntPtr)(-1);
-                       blocking_thread = Thread.CurrentThread;
                        
                        try {
+                               RegisterForBlockingSyscall ();
                                sock = Accept_internal (socket, out error, blocking);
-                       } catch (ThreadAbortException) {
-                               if (disposed) {
-#if !NET_2_1
-                                       Thread.ResetAbort ();
-#endif
-                                       error = (int)SocketError.Interrupted;
-                               }
                        } finally {
-                               blocking_thread = null;
+                               UnRegisterForBlockingSyscall ();
                        }
                        
-                       if (error != 0)
+                       if (error != 0) {
+                               if (closed)
+                                       error = SOCKET_CLOSED;
                                throw new SocketException (error);
+                       }
                        
                        acceptSocket.address_family = this.AddressFamily;
                        acceptSocket.socket_type = this.SocketType;
@@ -1170,26 +599,25 @@ namespace System.Net.Sockets
                         */
                }
 
-               public IAsyncResult BeginAccept(AsyncCallback callback,
-                                               object state)
+               public IAsyncResult BeginAccept(AsyncCallback callback, object state)
                {
                        if (disposed && closed)
                                throw new ObjectDisposedException (GetType ().ToString ());
 
-#if NET_2_0
-                       /* FIXME: check the 1.1 docs for this too */
                        if (!isbound || !islistening)
                                throw new InvalidOperationException ();
-#endif
 
                        SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Accept);
-                       Worker worker = new Worker (req);
-                       SocketAsyncCall sac = new SocketAsyncCall (worker.Accept);
-                       sac.BeginInvoke (null, req);
-                       return(req);
+                       int count;
+                       lock (readQ) {
+                               readQ.Enqueue (req.Worker);
+                               count = readQ.Count;
+                       }
+                       if (count == 1)
+                               socket_pool_queue (Worker.Dispatcher, req);
+                       return req;
                }
 
-#if NET_2_0
                public IAsyncResult BeginAccept (int receiveSize,
                                                 AsyncCallback callback,
                                                 object state)
@@ -1201,16 +629,18 @@ namespace System.Net.Sockets
                                throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
 
                        SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.AcceptReceive);
-                       Worker worker = new Worker (req);
-                       SocketAsyncCall sac = new SocketAsyncCall (worker.AcceptReceive);
-                       
                        req.Buffer = new byte[receiveSize];
                        req.Offset = 0;
                        req.Size = receiveSize;
                        req.SockFlags = SocketFlags.None;
-
-                       sac.BeginInvoke (null, req);
-                       return(req);
+                       int count;
+                       lock (readQ) {
+                               readQ.Enqueue (req.Worker);
+                               count = readQ.Count;
+                       }
+                       if (count == 1)
+                               socket_pool_queue (Worker.Dispatcher, req);
+                       return req;
                }
 
                public IAsyncResult BeginAccept (Socket acceptSocket,
@@ -1241,69 +671,21 @@ namespace System.Net.Sockets
                        }
                        
                        SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.AcceptReceive);
-                       Worker worker = new Worker (req);
-                       SocketAsyncCall sac = new SocketAsyncCall (worker.AcceptReceive);
-                       
                        req.Buffer = new byte[receiveSize];
                        req.Offset = 0;
                        req.Size = receiveSize;
                        req.SockFlags = SocketFlags.None;
                        req.AcceptSocket = acceptSocket;
-
-                       sac.BeginInvoke (null, req);
-                       return(req);
-               }
-#endif
-
-               public IAsyncResult BeginConnect(EndPoint end_point,
-                                                AsyncCallback callback,
-                                                object state) {
-
-                       if (disposed && closed)
-                               throw new ObjectDisposedException (GetType ().ToString ());
-
-                       if (end_point == null)
-                               throw new ArgumentNullException ("end_point");
-
-                       SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Connect);
-                       req.EndPoint = end_point;
-
-                       // 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)) {
-                                       req.Complete (new SocketException ((int) SocketError.AddressNotAvailable), true);
-                                       return req;
-                               }
-                       }
-
-                       int error = 0;
-                       if (!blocking) {
-                               SocketAddress serial = end_point.Serialize ();
-                               Connect_internal (socket, serial, out error);
-                               if (error == 0) {
-                                       // succeeded synch
-                                       connected = true;
-                                       req.Complete (true);
-                               } else if (error != (int) SocketError.InProgress && error != (int) SocketError.WouldBlock) {
-                                       // error synch
-                                       connected = false;
-                                       req.Complete (new SocketException (error), true);
-                               }
-                       }
-
-                       if (blocking || error == (int) SocketError.InProgress || error == (int) SocketError.WouldBlock) {
-                               // continue asynch
-                               connected = false;
-                               Worker worker = new Worker (req);
-                               SocketAsyncCall sac = new SocketAsyncCall (worker.Connect);
-                               sac.BeginInvoke (null, req);
+                       int count;
+                       lock (readQ) {
+                               readQ.Enqueue (req.Worker);
+                               count = readQ.Count;
                        }
-
+                       if (count == 1)
+                               socket_pool_queue (Worker.Dispatcher, req);
                        return(req);
                }
 
-#if NET_2_0
                public IAsyncResult BeginConnect (IPAddress address, int port,
                                                  AsyncCallback callback,
                                                  object state)
@@ -1317,6 +699,9 @@ namespace System.Net.Sockets
                        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 (islistening)
                                throw new InvalidOperationException ();
 
@@ -1324,36 +709,6 @@ namespace System.Net.Sockets
                        return(BeginConnect (iep, callback, state));
                }
 
-               public IAsyncResult BeginConnect (IPAddress[] addresses,
-                                                 int port,
-                                                 AsyncCallback callback,
-                                                 object state)
-               {
-                       if (disposed && closed)
-                               throw new ObjectDisposedException (GetType ().ToString ());
-
-                       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 (islistening)
-                               throw new InvalidOperationException ();
-
-                       SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Connect);
-                       req.Addresses = addresses;
-                       req.Port = port;
-                       
-                       connected = false;
-                       Worker worker = new Worker (req);
-                       SocketAsyncCall sac = new SocketAsyncCall (worker.Connect);
-                       sac.BeginInvoke (null, req);
-                       
-                       return(req);
-               }
-
                public IAsyncResult BeginConnect (string host, int port,
                                                  AsyncCallback callback,
                                                  object state)
@@ -1368,11 +723,13 @@ namespace System.Net.Sockets
                                address_family != 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 (islistening)
                                throw new InvalidOperationException ();
 
-                       IPHostEntry hostent = Dns.GetHostEntry (host);
-                       return (BeginConnect (hostent.AddressList, port, callback, state));
+                       return BeginConnect (Dns.GetHostAddresses (host), port, callback, state);
                }
 
                public IAsyncResult BeginDisconnect (bool reuseSocket,
@@ -1384,14 +741,24 @@ namespace System.Net.Sockets
 
                        SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Disconnect);
                        req.ReuseSocket = reuseSocket;
-                       
-                       Worker worker = new Worker (req);
-                       SocketAsyncCall sac = new SocketAsyncCall (worker.Disconnect);
-                       sac.BeginInvoke (null, req);
-                       
+                       socket_pool_queue (Worker.Dispatcher, req);
                        return(req);
                }
-#endif
+
+               void CheckRange (byte[] buffer, int offset, int size)
+               {
+                       if (offset < 0)
+                               throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
+                               
+                       if (offset > buffer.Length)
+                               throw new ArgumentOutOfRangeException ("offset", "offset must be <= buffer.Length");
+
+                       if (size < 0)                          
+                               throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
+                               
+                       if (size > buffer.Length - offset)
+                               throw new ArgumentOutOfRangeException ("size", "size must be <= buffer.Length - offset");
+               }
                
                public IAsyncResult BeginReceive(byte[] buffer, int offset,
                                                 int size,
@@ -1405,30 +772,23 @@ namespace System.Net.Sockets
                        if (buffer == null)
                                throw new ArgumentNullException ("buffer");
 
-                       if (offset < 0 || offset > buffer.Length)
-                               throw new ArgumentOutOfRangeException ("offset");
+                       CheckRange (buffer, offset, size);
 
-                       if (size < 0 || offset + size > buffer.Length)
-                               throw new ArgumentOutOfRangeException ("size");
-
-                       SocketAsyncResult req;
+                       SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Receive);
+                       req.Buffer = buffer;
+                       req.Offset = offset;
+                       req.Size = size;
+                       req.SockFlags = socket_flags;
+                       int count;
                        lock (readQ) {
-                               req = new SocketAsyncResult (this, state, callback, SocketOperation.Receive);
-                               req.Buffer = buffer;
-                               req.Offset = offset;
-                               req.Size = size;
-                               req.SockFlags = socket_flags;
-                               readQ.Enqueue (req);
-                               if (readQ.Count == 1) {
-                                       Worker worker = new Worker (req);
-                                       SocketAsyncCall sac = new SocketAsyncCall (worker.Receive);
-                                       sac.BeginInvoke (null, req);
-                               }
+                               readQ.Enqueue (req.Worker);
+                               count = readQ.Count;
                        }
-
+                       if (count == 1)
+                               socket_pool_queue (Worker.Dispatcher, req);
                        return req;
                }
-#if NET_2_0
+
                public IAsyncResult BeginReceive (byte[] buffer, int offset,
                                                  int size, SocketFlags flags,
                                                  out SocketError error,
@@ -1458,20 +818,17 @@ namespace System.Net.Sockets
                        if (buffers == null)
                                throw new ArgumentNullException ("buffers");
 
-                       SocketAsyncResult req;
+                       SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveGeneric);
+                       req.Buffers = buffers;
+                       req.SockFlags = socketFlags;
+                       int count;
                        lock(readQ) {
-                               req = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveGeneric);
-                               req.Buffers = buffers;
-                               req.SockFlags = socketFlags;
-                               readQ.Enqueue (req);
-                               if (readQ.Count == 1) {
-                                       Worker worker = new Worker (req);
-                                       SocketAsyncCall sac = new SocketAsyncCall (worker.ReceiveGeneric);
-                                       sac.BeginInvoke (null, req);
-                               }
+                               readQ.Enqueue (req.Worker);
+                               count = readQ.Count;
                        }
-                       
-                       return(req);
+                       if (count == 1)
+                               socket_pool_queue (Worker.Dispatcher, req);
+                       return req;
                }
                
                [CLSCompliant (false)]
@@ -1487,7 +844,6 @@ namespace System.Net.Sockets
                        errorCode = SocketError.Success;
                        return (BeginReceive (buffers, socketFlags, callback, state));
                }
-#endif
 
                public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset,
                                                     int size,
@@ -1501,34 +857,27 @@ namespace System.Net.Sockets
                        if (buffer == null)
                                throw new ArgumentNullException ("buffer");
 
-                       if (offset < 0)
-                               throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
-
-                       if (size < 0)
-                               throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
+                       if (remote_end == null)
+                               throw new ArgumentNullException ("remote_end");
 
-                       if (offset + size > buffer.Length)
-                               throw new ArgumentOutOfRangeException ("offset, size", "offset + size exceeds the buffer length");
+                       CheckRange (buffer, offset, size);
 
-                       SocketAsyncResult req;
+                       SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveFrom);
+                       req.Buffer = buffer;
+                       req.Offset = offset;
+                       req.Size = size;
+                       req.SockFlags = socket_flags;
+                       req.EndPoint = remote_end;
+                       int count;
                        lock (readQ) {
-                               req = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveFrom);
-                               req.Buffer = buffer;
-                               req.Offset = offset;
-                               req.Size = size;
-                               req.SockFlags = socket_flags;
-                               req.EndPoint = remote_end;
-                               readQ.Enqueue (req);
-                               if (readQ.Count == 1) {
-                                       Worker worker = new Worker (req);
-                                       SocketAsyncCall sac = new SocketAsyncCall (worker.ReceiveFrom);
-                                       sac.BeginInvoke (null, req);
-                               }
+                               readQ.Enqueue (req.Worker);
+                               count = readQ.Count;
                        }
+                       if (count == 1)
+                               socket_pool_queue (Worker.Dispatcher, req);
                        return req;
                }
 
-#if NET_2_0
                [MonoTODO]
                public IAsyncResult BeginReceiveMessageFrom (
                        byte[] buffer, int offset, int size,
@@ -1544,15 +893,10 @@ namespace System.Net.Sockets
                        if (remoteEP == null)
                                throw new ArgumentNullException ("remoteEP");
 
-                       if (offset < 0 || offset > buffer.Length)
-                               throw new ArgumentOutOfRangeException ("offset");
-
-                       if (size < 0 || offset + size > buffer.Length)
-                               throw new ArgumentOutOfRangeException ("size");
+                       CheckRange (buffer, offset, size);
 
                        throw new NotImplementedException ();
                }
-#endif
 
                public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socket_flags,
                                               AsyncCallback callback, object state)
@@ -1563,39 +907,26 @@ namespace System.Net.Sockets
                        if (buffer == null)
                                throw new ArgumentNullException ("buffer");
 
-                       if (offset < 0)
-                               throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
-
-                       if (size < 0)
-                               throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
+                       CheckRange (buffer, offset, size);
 
-                       if (offset + size > buffer.Length)
-                               throw new ArgumentOutOfRangeException ("offset, size", "offset + size exceeds the buffer length");
-
-#if NET_2_0
-                       /* TODO: Check this exception in the 1.1 profile */
                        if (!connected)
                                throw new SocketException ((int)SocketError.NotConnected);
-#endif
 
-                       SocketAsyncResult req;
+                       SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Send);
+                       req.Buffer = buffer;
+                       req.Offset = offset;
+                       req.Size = size;
+                       req.SockFlags = socket_flags;
+                       int count;
                        lock (writeQ) {
-                               req = new SocketAsyncResult (this, state, callback, SocketOperation.Send);
-                               req.Buffer = buffer;
-                               req.Offset = offset;
-                               req.Size = size;
-                               req.SockFlags = socket_flags;
-                               writeQ.Enqueue (req);
-                               if (writeQ.Count == 1) {
-                                       Worker worker = new Worker (req);
-                                       SocketAsyncCall sac = new SocketAsyncCall (worker.Send);
-                                       sac.BeginInvoke (null, req);
-                               }
+                               writeQ.Enqueue (req.Worker);
+                               count = writeQ.Count;
                        }
+                       if (count == 1)
+                               socket_pool_queue (Worker.Dispatcher, req);
                        return req;
                }
 
-#if NET_2_0
                public IAsyncResult BeginSend (byte[] buffer, int offset,
                                               int size,
                                               SocketFlags socketFlags,
@@ -1628,20 +959,17 @@ namespace System.Net.Sockets
                        if (!connected)
                                throw new SocketException ((int)SocketError.NotConnected);
 
-                       SocketAsyncResult req;
+                       SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.SendGeneric);
+                       req.Buffers = buffers;
+                       req.SockFlags = socketFlags;
+                       int count;
                        lock (writeQ) {
-                               req = new SocketAsyncResult (this, state, callback, SocketOperation.SendGeneric);
-                               req.Buffers = buffers;
-                               req.SockFlags = socketFlags;
-                               writeQ.Enqueue (req);
-                               if (writeQ.Count == 1) {
-                                       Worker worker = new Worker (req);
-                                       SocketAsyncCall sac = new SocketAsyncCall (worker.SendGeneric);
-                                       sac.BeginInvoke (null, req);
-                               }
+                               writeQ.Enqueue (req.Worker);
+                               count = writeQ.Count;
                        }
-                       
-                       return(req);
+                       if (count == 1)
+                               socket_pool_queue (Worker.Dispatcher, req);
+                       return req;
                }
 
                [CLSCompliant (false)]
@@ -1660,7 +988,43 @@ namespace System.Net.Sockets
                        return (BeginSend (buffers, socketFlags, callback, state));
                }
 
-               [MonoTODO ("Not implemented")]
+               delegate void SendFileHandler (string fileName, byte [] preBuffer, byte [] postBuffer, TransmitFileOptions flags);
+
+               sealed class SendFileAsyncResult : IAsyncResult {
+                       IAsyncResult ares;
+                       SendFileHandler d;
+
+                       public SendFileAsyncResult (SendFileHandler d, IAsyncResult ares)
+                       {
+                               this.d = d;
+                               this.ares = ares;
+                       }
+
+                       public object AsyncState {
+                               get { return ares.AsyncState; }
+                       }
+
+                       public WaitHandle AsyncWaitHandle {
+                               get { return ares.AsyncWaitHandle; }
+                       }
+
+                       public bool CompletedSynchronously {
+                               get { return ares.CompletedSynchronously; }
+                       }
+
+                       public bool IsCompleted {
+                               get { return ares.IsCompleted; }
+                       }
+
+                       public SendFileHandler Delegate {
+                               get { return d; }
+                       }
+
+                       public IAsyncResult Original {
+                               get { return ares; }
+                       }
+               }
+
                public IAsyncResult BeginSendFile (string fileName,
                                                   AsyncCallback callback,
                                                   object state)
@@ -1674,10 +1038,9 @@ namespace System.Net.Sockets
                        if (!File.Exists (fileName))
                                throw new FileNotFoundException ();
 
-                       throw new NotImplementedException ();
+                       return BeginSendFile (fileName, null, null, 0, callback, state);
                }
 
-               [MonoTODO ("Not implemented")]
                public IAsyncResult BeginSendFile (string fileName,
                                                   byte[] preBuffer,
                                                   byte[] postBuffer,
@@ -1694,9 +1057,9 @@ namespace System.Net.Sockets
                        if (!File.Exists (fileName))
                                throw new FileNotFoundException ();
 
-                       throw new NotImplementedException ();
+                       SendFileHandler d = new SendFileHandler (SendFile);
+                       return new SendFileAsyncResult (d, d.BeginInvoke (fileName, preBuffer, postBuffer, flags, callback, state));
                }
-#endif
 
                public IAsyncResult BeginSendTo(byte[] buffer, int offset,
                                                int size,
@@ -1710,30 +1073,21 @@ namespace System.Net.Sockets
                        if (buffer == null)
                                throw new ArgumentNullException ("buffer");
 
-                       if (offset < 0)
-                               throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
-
-                       if (size < 0)
-                               throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
-
-                       if (offset + size > buffer.Length)
-                               throw new ArgumentOutOfRangeException ("offset, size", "offset + size exceeds the buffer length");
+                       CheckRange (buffer, offset, size);
 
-                       SocketAsyncResult req;
+                       SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.SendTo);
+                       req.Buffer = buffer;
+                       req.Offset = offset;
+                       req.Size = size;
+                       req.SockFlags = socket_flags;
+                       req.EndPoint = remote_end;
+                       int count;
                        lock (writeQ) {
-                               req = new SocketAsyncResult (this, state, callback, SocketOperation.SendTo);
-                               req.Buffer = buffer;
-                               req.Offset = offset;
-                               req.Size = size;
-                               req.SockFlags = socket_flags;
-                               req.EndPoint = remote_end;
-                               writeQ.Enqueue (req);
-                               if (writeQ.Count == 1) {
-                                       Worker worker = new Worker (req);
-                                       SocketAsyncCall sac = new SocketAsyncCall (worker.SendTo);
-                                       sac.BeginInvoke (null, req);
-                               }
+                               writeQ.Enqueue (req.Worker);
+                               count = writeQ.Count;
                        }
+                       if (count == 1)
+                               socket_pool_queue (Worker.Dispatcher, req);
                        return req;
                }
 
@@ -1755,50 +1109,12 @@ namespace System.Net.Sockets
                        Bind_internal(socket, local_end.Serialize(), out error);
                        if (error != 0)
                                throw new SocketException (error);
-#if NET_2_0
                        if (error == 0)
                                isbound = true;
-#endif
                        
                        seed_endpoint = local_end;
                }
 
-#if NET_2_0 && !NET_2_1
-               public void Close (int timeout) 
-               {
-                       System.Timers.Timer close_timer = new System.Timers.Timer ();
-                       close_timer.Elapsed += new ElapsedEventHandler (OnTimeoutClose);
-                       close_timer.Interval = timeout * 1000;
-                       close_timer.AutoReset = false;
-                       close_timer.Enabled = true;
-               }
-
-               private void OnTimeoutClose (object source, ElapsedEventArgs e)
-               {
-                       this.Close ();
-               }
-
-               public bool ConnectAsync (SocketAsyncEventArgs e)
-               {
-                       // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
-                       
-                       if (disposed && closed)
-                               throw new ObjectDisposedException (GetType ().ToString ());
-                       if (islistening)
-                               throw new InvalidOperationException ("You may not perform this operation after calling the Listen method.");
-                       if (e.RemoteEndPoint == null)
-                               throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
-                       if (e.BufferList != null)
-                               throw new ArgumentException ("Multiple buffers cannot be used with this method.");
-
-                       e.DoOperation (SocketAsyncOperation.Connect, this);
-
-                       // We always return true for now
-                       return true;
-               }
-#endif
-               
-#if NET_2_0
                public void Connect (IPAddress address, int port)
                {
                        Connect (new IPEndPoint (address, port));
@@ -1820,15 +1136,15 @@ namespace System.Net.Sockets
                                throw new InvalidOperationException ();
 
                        /* FIXME: do non-blocking sockets Poll here? */
+                       int error = 0;
                        foreach (IPAddress address in addresses) {
-                               IPEndPoint iep = new IPEndPoint (address,
-                                                                port);
+                               IPEndPoint iep = new IPEndPoint (address, port);
                                SocketAddress serial = iep.Serialize ();
-                               int error = 0;
                                
                                Connect_internal (socket, serial, out error);
                                if (error == 0) {
                                        connected = true;
+                                       isbound = true;
                                        seed_endpoint = iep;
                                        return;
                                } else if (error != (int)SocketError.InProgress &&
@@ -1838,38 +1154,41 @@ namespace System.Net.Sockets
                                
                                if (!blocking) {
                                        Poll (-1, SelectMode.SelectWrite);
-                                       int success = (int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
-                                       if (success == 0) {
+                                       error = (int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
+                                       if (error == 0) {
                                                connected = true;
+                                               isbound = true;
                                                seed_endpoint = iep;
                                                return;
                                        }
                                }
                        }
+                       if (error != 0)
+                               throw new SocketException (error);
                }
 
                public void Connect (string host, int port)
                {
-                       IPHostEntry hostent = Dns.GetHostEntry (host);
-                       Connect (hostent.AddressList, port);
+                       IPAddress [] addresses = Dns.GetHostAddresses (host);
+                       Connect (addresses, port);
                }
 
-#if NET_2_0
+#if !MOONLIGHT
                public bool DisconnectAsync (SocketAsyncEventArgs e)
                {
                        // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
                        if (disposed && closed)
                                throw new ObjectDisposedException (GetType ().ToString ());
 
-                       e.DoOperation (SocketAsyncOperation.Disconnect, this);
-
+                       e.curSocket = this;
+                       e.Worker.Init (this, e, SocketOperation.Disconnect);
+                       socket_pool_queue (Worker.Dispatcher, e.Worker.result);
                        return true;
                }
 #endif
+
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               private extern static void Disconnect_internal(IntPtr sock,
-                                                              bool reuse,
-                                                              out int error);
+               extern static void Disconnect_internal(IntPtr sock, bool reuse, out int error);
 
                /* According to the docs, the MS runtime will throw
                 * PlatformNotSupportedException if the platform is
@@ -1900,18 +1219,24 @@ namespace System.Net.Sockets
                        }
                }
 
-               [MonoTODO ("Not implemented")]
+#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)
                {
-                       /* Need to serialize this socket into a
-                        * SocketInformation struct, but must study
-                        * the MS implementation harder to figure out
-                        * behaviour as documentation is lacking
-                        */
-                       throw new NotImplementedException ();
+                       var si = new SocketInformation ();
+                       si.Options =
+                               (islistening ? SocketInformationOptions.Listening : 0) |
+                               (connected ? SocketInformationOptions.Connected : 0) |
+                               (blocking ? 0 : SocketInformationOptions.NonBlocking) |
+                               (useoverlappedIO ? SocketInformationOptions.UseOnlyOverlappedIO : 0);
+
+                       si.ProtocolInformation = Mono.DataConverter.Pack ("iiiil", (int)address_family, (int)socket_type, (int)protocol_type, isbound ? 1 : 0, (long)socket);
+                       socket = (IntPtr) (-1);
+
+                       return si;
                }
 #endif
-               
+       
                public Socket EndAccept (IAsyncResult result)
                {
                        int bytes;
@@ -1920,23 +1245,13 @@ namespace System.Net.Sockets
                        return(EndAccept (out buffer, out bytes, result));
                }
 
-#if NET_2_0
-               public Socket EndAccept (out byte[] buffer,
-                                        IAsyncResult asyncResult)
+               public Socket EndAccept (out byte[] buffer, IAsyncResult asyncResult)
                {
                        int bytes;
-                       
                        return(EndAccept (out buffer, out bytes, asyncResult));
                }
-#endif
 
-#if NET_2_0
-               public
-#else
-               private
-#endif
-               Socket EndAccept (out byte[] buffer, out int bytesTransferred,
-                                 IAsyncResult asyncResult)
+               public Socket EndAccept (out byte[] buffer, out int bytesTransferred, IAsyncResult asyncResult)
                {
                        if (disposed && closed)
                                throw new ObjectDisposedException (GetType ().ToString ());
@@ -1981,7 +1296,7 @@ namespace System.Net.Sockets
                        req.CheckIfThrowDelayedException();
                }
 
-#if NET_2_0
+#if !MOONLIGHT
                public void EndDisconnect (IAsyncResult asyncResult)
                {
                        if (disposed && closed)
@@ -1999,68 +1314,10 @@ namespace System.Net.Sockets
                        if (!asyncResult.IsCompleted)
                                asyncResult.AsyncWaitHandle.WaitOne ();
 
-                       req.CheckIfThrowDelayedException ();
-               }
-#endif
-
-               public int EndReceive (IAsyncResult result)
-               {
-                       SocketError error;
-                       
-                       return (EndReceive (result, out error));
-               }
-
-#if NET_2_0
-               public
-#else
-               private
-#endif
-               int EndReceive (IAsyncResult asyncResult, out SocketError errorCode)
-               {
-                       if (disposed && closed)
-                               throw new ObjectDisposedException (GetType ().ToString ());
-
-                       if (asyncResult == null)
-                               throw new ArgumentNullException ("asyncResult");
-
-                       SocketAsyncResult req = asyncResult as SocketAsyncResult;
-                       if (req == null)
-                               throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
-
-                       if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
-                               throw InvalidAsyncOp ("EndReceive");
-                       if (!asyncResult.IsCompleted)
-                               asyncResult.AsyncWaitHandle.WaitOne ();
-
-                       errorCode = req.ErrorCode;
-                       req.CheckIfThrowDelayedException ();
-                       
-                       return(req.Total);
-               }
-
-               public int EndReceiveFrom(IAsyncResult result, ref EndPoint end_point)
-               {
-                       if (disposed && closed)
-                               throw new ObjectDisposedException (GetType ().ToString ());
-
-                       if (result == null)
-                               throw new ArgumentNullException ("result");
-
-                       SocketAsyncResult req = result as SocketAsyncResult;
-                       if (req == null)
-                               throw new ArgumentException ("Invalid IAsyncResult", "result");
-
-                       if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
-                               throw InvalidAsyncOp ("EndReceiveFrom");
-                       if (!result.IsCompleted)
-                               result.AsyncWaitHandle.WaitOne();
-
-                       req.CheckIfThrowDelayedException();
-                       end_point = req.EndPoint;
-                       return req.Total;
+                       req.CheckIfThrowDelayedException ();
                }
+#endif
 
-#if NET_2_0
                [MonoTODO]
                public int EndReceiveMessageFrom (IAsyncResult asyncResult,
                                                  ref SocketFlags socketFlags,
@@ -2084,45 +1341,7 @@ namespace System.Net.Sockets
                                throw InvalidAsyncOp ("EndReceiveMessageFrom");
                        throw new NotImplementedException ();
                }
-#endif
-
-               public int EndSend (IAsyncResult result)
-               {
-                       SocketError error;
-                       
-                       return(EndSend (result, out error));
-               }
-
-#if NET_2_0
-               public
-#else
-               private
-#endif
-               int EndSend (IAsyncResult asyncResult, out SocketError errorCode)
-               {
-                       if (disposed && closed)
-                               throw new ObjectDisposedException (GetType ().ToString ());
-
-                       if (asyncResult == null)
-                               throw new ArgumentNullException ("asyncResult");
-                       
-                       SocketAsyncResult req = asyncResult as SocketAsyncResult;
-                       if (req == null)
-                               throw new ArgumentException ("Invalid IAsyncResult", "result");
-
-                       if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
-                               throw InvalidAsyncOp ("EndSend");
-                       if (!asyncResult.IsCompleted)
-                               asyncResult.AsyncWaitHandle.WaitOne ();
-
-                       errorCode = req.ErrorCode;
-                       req.CheckIfThrowDelayedException ();
-                       
-                       return(req.Total);
-               }
 
-#if NET_2_0
-               [MonoTODO]
                public void EndSendFile (IAsyncResult asyncResult)
                {
                        if (disposed && closed)
@@ -2131,21 +1350,14 @@ namespace System.Net.Sockets
                        if (asyncResult == null)
                                throw new ArgumentNullException ("asyncResult");
 
-                       SocketAsyncResult req = asyncResult as SocketAsyncResult;
-                       if (req == null)
+                       SendFileAsyncResult ares = asyncResult as SendFileAsyncResult;
+                       if (ares == null)
                                throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
 
-                       if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
-                               throw InvalidAsyncOp ("EndSendFile");
-                       throw new NotImplementedException ();
-               }
-#endif
-
-               Exception InvalidAsyncOp (string method)
-               {
-                       return new InvalidOperationException (method + " can only be called once per asynchronous operation");
+                       ares.Delegate.EndInvoke (ares.Original);
                }
 
+#if !MOONLIGHT
                public int EndSendTo (IAsyncResult result)
                {
                        if (disposed && closed)
@@ -2166,34 +1378,39 @@ namespace System.Net.Sockets
                        req.CheckIfThrowDelayedException();
                        return req.Total;
                }
+#endif
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                private extern static void GetSocketOption_arr_internal(IntPtr socket,
                        SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val,
                        out int error);
 
-               public void GetSocketOption (SocketOptionLevel level, SocketOptionName name, byte [] opt_value)
+               public void GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, byte [] optionValue)
                {
                        if (disposed && closed)
                                throw new ObjectDisposedException (GetType ().ToString ());
 
+                       if (optionValue == null)
+                               throw new SocketException ((int) SocketError.Fault,
+                                       "Error trying to dereference an invalid pointer");
+
                        int error;
-                       
-                       GetSocketOption_arr_internal(socket, level, name, ref opt_value,
+
+                       GetSocketOption_arr_internal (socket, optionLevel, optionName, ref optionValue,
                                out error);
                        if (error != 0)
                                throw new SocketException (error);
                }
 
-               public byte [] GetSocketOption (SocketOptionLevel level, SocketOptionName name, int length)
+               public byte [] GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int length)
                {
                        if (disposed && closed)
                                throw new ObjectDisposedException (GetType ().ToString ());
 
                        byte[] byte_val=new byte[length];
                        int error;
-                       
-                       GetSocketOption_arr_internal(socket, level, name, ref byte_val,
+
+                       GetSocketOption_arr_internal (socket, optionLevel, optionName, ref byte_val,
                                out error);
                        if (error != 0)
                                throw new SocketException (error);
@@ -2204,7 +1421,8 @@ namespace System.Net.Sockets
                // See Socket.IOControl, WSAIoctl documentation in MSDN. The
                // common options between UNIX and Winsock are FIONREAD,
                // FIONBIO and SIOCATMARK. Anything else will depend on the
-               // system.
+               // system except SIO_KEEPALIVE_VALS which is properly handled
+               // on both windows and linux.
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                extern static int WSAIoctl (IntPtr sock, int ioctl_code, byte [] input,
                        byte [] output, out int error);
@@ -2227,46 +1445,29 @@ namespace System.Net.Sockets
                        return result;
                }
 
-#if NET_2_0
-               [MonoTODO]
-               public int IOControl (IOControlCode ioControlCode,
-                                     byte[] optionInValue,
-                                     byte[] optionOutValue)
+               public int IOControl (IOControlCode ioControlCode, byte[] optionInValue, byte[] optionOutValue)
                {
-                       /* Probably just needs to mirror the int
-                        * overload, but more investigation needed.
-                        */
-                       throw new NotImplementedException ();
+                       return IOControl ((int) ioControlCode, optionInValue, optionOutValue);
                }
-#endif
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               private extern static void Listen_internal(IntPtr sock, int backlog,
-                       out int error);
+               private extern static void Listen_internal(IntPtr sock, int backlog, out int error);
 
                public void Listen (int backlog)
                {
                        if (disposed && closed)
                                throw new ObjectDisposedException (GetType ().ToString ());
 
-#if NET_2_0
-                       /* TODO: check if this should be thrown in the
-                        * 1.1 profile too
-                        */
                        if (!isbound)
                                throw new SocketException ((int)SocketError.InvalidArgument);
-#endif
 
                        int error;
-                       
                        Listen_internal(socket, backlog, out error);
 
                        if (error != 0)
                                throw new SocketException (error);
 
-#if NET_2_0
                        islistening = true;
-#endif
                }
 
                public bool Poll (int time_us, SelectMode mode)
@@ -2298,17 +1499,17 @@ namespace System.Net.Sockets
                        return result;
                }
 
-               public int Receive (byte [] buf)
+               public int Receive (byte [] buffer)
                {
                        if (disposed && closed)
                                throw new ObjectDisposedException (GetType ().ToString ());
 
-                       if (buf == null)
-                               throw new ArgumentNullException ("buf");
+                       if (buffer == null)
+                               throw new ArgumentNullException ("buffer");
 
                        SocketError error;
 
-                       int ret = Receive_nochecks (buf, 0, buf.Length, SocketFlags.None, out error);
+                       int ret = Receive_nochecks (buffer, 0, buffer.Length, SocketFlags.None, out error);
                        
                        if (error != SocketError.Success)
                                throw new SocketException ((int) error);
@@ -2316,17 +1517,17 @@ namespace System.Net.Sockets
                        return ret;
                }
 
-               public int Receive (byte [] buf, SocketFlags flags)
+               public int Receive (byte [] buffer, SocketFlags flags)
                {
                        if (disposed && closed)
                                throw new ObjectDisposedException (GetType ().ToString ());
 
-                       if (buf == null)
-                               throw new ArgumentNullException ("buf");
+                       if (buffer == null)
+                               throw new ArgumentNullException ("buffer");
 
                        SocketError error;
 
-                       int ret = Receive_nochecks (buf, 0, buf.Length, flags, out error);
+                       int ret = Receive_nochecks (buffer, 0, buffer.Length, flags, out error);
                        
                        if (error != SocketError.Success) {
                                if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
@@ -2337,20 +1538,19 @@ namespace System.Net.Sockets
                        return ret;
                }
 
-               public int Receive (byte [] buf, int size, SocketFlags flags)
+               public int Receive (byte [] buffer, int size, SocketFlags flags)
                {
                        if (disposed && closed)
                                throw new ObjectDisposedException (GetType ().ToString ());
 
-                       if (buf == null)
-                               throw new ArgumentNullException ("buf");
+                       if (buffer == null)
+                               throw new ArgumentNullException ("buffer");
 
-                       if (size < 0 || size > buf.Length)
-                               throw new ArgumentOutOfRangeException ("size");
+                       CheckRange (buffer, 0, size);
 
                        SocketError error;
 
-                       int ret = Receive_nochecks (buf, 0, size, flags, out error);
+                       int ret = Receive_nochecks (buffer, 0, size, flags, out error);
                        
                        if (error != SocketError.Success) {
                                if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
@@ -2361,23 +1561,19 @@ namespace System.Net.Sockets
                        return ret;
                }
 
-               public int Receive (byte [] buf, int offset, int size, SocketFlags flags)
+               public int Receive (byte [] buffer, int offset, int size, SocketFlags flags)
                {
                        if (disposed && closed)
                                throw new ObjectDisposedException (GetType ().ToString ());
 
-                       if (buf == null)
-                               throw new ArgumentNullException ("buf");
-
-                       if (offset < 0 || offset > buf.Length)
-                               throw new ArgumentOutOfRangeException ("offset");
+                       if (buffer == null)
+                               throw new ArgumentNullException ("buffer");
 
-                       if (size < 0 || offset + size > buf.Length)
-                               throw new ArgumentOutOfRangeException ("size");
+                       CheckRange (buffer, offset, size);
                        
                        SocketError error;
 
-                       int ret = Receive_nochecks (buf, offset, size, flags, out error);
+                       int ret = Receive_nochecks (buffer, offset, size, flags, out error);
                        
                        if (error != SocketError.Success) {
                                if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
@@ -2388,110 +1584,20 @@ namespace System.Net.Sockets
                        return ret;
                }
 
-#if NET_2_0
-               public int Receive (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
+               public int Receive (byte [] buffer, int offset, int size, SocketFlags flags, out SocketError error)
                {
                        if (disposed && closed)
                                throw new ObjectDisposedException (GetType ().ToString ());
 
-                       if (buf == null)
-                               throw new ArgumentNullException ("buf");
-
-                       if (offset < 0 || offset > buf.Length)
-                               throw new ArgumentOutOfRangeException ("offset");
-
-                       if (size < 0 || offset + size > buf.Length)
-                               throw new ArgumentOutOfRangeException ("size");
-                       
-                       return Receive_nochecks (buf, offset, size, flags, out error);
-               }
-
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               private extern static int Receive_internal (IntPtr sock,
-                                                           WSABUF[] bufarray,
-                                                           SocketFlags flags,
-                                                           out int error);
-               
-               public int Receive (IList<ArraySegment<byte>> buffers)
-               {
-                       int ret;
-                       SocketError error;
-                       
-                       ret = Receive (buffers, SocketFlags.None, out error);
-                       if (error != SocketError.Success) {
-                               throw new SocketException ((int)error);
-                       }
-                       
-                       return(ret);
-               }
-               
-               [CLSCompliant (false)]
-               public int Receive (IList<ArraySegment<byte>> buffers,
-                                   SocketFlags socketFlags)
-               {
-                       int ret;
-                       SocketError error;
-                       
-                       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)
-               {
-                       if (buffers == null ||
-                           buffers.Count == 0) {
-                               throw new ArgumentNullException ("buffers");
-                       }
-                       
-                       if (disposed && closed) {
-                               throw new ObjectDisposedException (GetType ().ToString ());
-                       }
-
-                       int numsegments = buffers.Count;
-                       int nativeError;
-                       int ret;                        
-
-                       /* Only example I can find of sending a byte
-                        * array reference directly into an internal
-                        * call is in
-                        * System.Runtime.Remoting/System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeSocket.cs,
-                        * so taking a lead from that...
-                        */
-                       WSABUF[] bufarray = new WSABUF[numsegments];
-                       GCHandle[] gch = new GCHandle[numsegments];
+                       if (buffer == null)
+                               throw new ArgumentNullException ("buffer");
 
-                       for(int i = 0; i < numsegments; i++) {
-                               ArraySegment<byte> segment = buffers[i];
-                               gch[i] = GCHandle.Alloc (segment.Array, GCHandleType.Pinned);
-                               bufarray[i].len = segment.Count;
-                               bufarray[i].buf = Marshal.UnsafeAddrOfPinnedArrayElement (segment.Array, segment.Offset);
-                       }
+                       CheckRange (buffer, offset, size);
                        
-                       try {
-                               ret = Receive_internal (socket, bufarray,
-                                                       socketFlags,
-                                                       out nativeError);
-                       } finally {
-                               for(int i = 0; i < numsegments; i++) {
-                                       if (gch[i].IsAllocated) {
-                                               gch[i].Free ();
-                                       }
-                               }
-                       }
-
-                       errorCode = (SocketError)nativeError;
-                       return(ret);
+                       return Receive_nochecks (buffer, offset, size, flags, out error);
                }
-#endif
 
-#if NET_2_0
+#if !MOONLIGHT
                public bool ReceiveFromAsync (SocketAsyncEventArgs e)
                {
                        if (disposed && closed)
@@ -2503,57 +1609,69 @@ namespace System.Net.Sockets
                        if (e.RemoteEndPoint == null)
                                throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
 
-                       e.DoOperation (SocketAsyncOperation.ReceiveFrom, this);
-
-                       // We always return true for now
+                       e.curSocket = this;
+                       e.Worker.Init (this, e, SocketOperation.ReceiveFrom);
+                       SocketAsyncResult res = e.Worker.result;
+                       res.Buffer = e.Buffer;
+                       res.Offset = e.Offset;
+                       res.Size = e.Count;
+                       res.EndPoint = e.RemoteEndPoint;
+                       res.SockFlags = e.SocketFlags;
+                       int count;
+                       lock (readQ) {
+                               readQ.Enqueue (e.Worker);
+                               count = readQ.Count;
+                       }
+                       if (count == 1)
+                               socket_pool_queue (Worker.Dispatcher, res);
                        return true;
                }
 #endif
-               
-               public int ReceiveFrom (byte [] buf, ref EndPoint remote_end)
+
+               public int ReceiveFrom (byte [] buffer, ref EndPoint remoteEP)
                {
                        if (disposed && closed)
                                throw new ObjectDisposedException (GetType ().ToString ());
 
-                       if (buf == null)
-                               throw new ArgumentNullException ("buf");
+                       if (buffer == null)
+                               throw new ArgumentNullException ("buffer");
 
-                       if (remote_end == null)
-                               throw new ArgumentNullException ("remote_end");
+                       if (remoteEP == null)
+                               throw new ArgumentNullException ("remoteEP");
 
-                       return ReceiveFrom_nochecks (buf, 0, buf.Length, SocketFlags.None, ref remote_end);
+                       return ReceiveFrom_nochecks (buffer, 0, buffer.Length, SocketFlags.None, ref remoteEP);
                }
 
-               public int ReceiveFrom (byte [] buf, SocketFlags flags, ref EndPoint remote_end)
+               public int ReceiveFrom (byte [] buffer, SocketFlags flags, ref EndPoint remoteEP)
                {
                        if (disposed && closed)
                                throw new ObjectDisposedException (GetType ().ToString ());
 
-                       if (buf == null)
-                               throw new ArgumentNullException ("buf");
+                       if (buffer == null)
+                               throw new ArgumentNullException ("buffer");
 
-                       if (remote_end == null)
-                               throw new ArgumentNullException ("remote_end");
+                       if (remoteEP == null)
+                               throw new ArgumentNullException ("remoteEP");
 
-                       return ReceiveFrom_nochecks (buf, 0, buf.Length, flags, ref remote_end);
+                       return ReceiveFrom_nochecks (buffer, 0, buffer.Length, flags, ref remoteEP);
                }
 
-               public int ReceiveFrom (byte [] buf, int size, SocketFlags flags,
-                                       ref EndPoint remote_end)
+               public int ReceiveFrom (byte [] buffer, int size, SocketFlags flags,
+                                       ref EndPoint remoteEP)
                {
                        if (disposed && closed)
                                throw new ObjectDisposedException (GetType ().ToString ());
 
-                       if (buf == null)
-                               throw new ArgumentNullException ("buf");
+                       if (buffer == null)
+                               throw new ArgumentNullException ("buffer");
 
-                       if (remote_end == null)
-                               throw new ArgumentNullException ("remote_end");
+                       if (remoteEP == null)
+                               throw new ArgumentNullException ("remoteEP");
 
-                       if (size < 0 || size > buf.Length)
+                       if (size < 0 || size > buffer.Length)
                                throw new ArgumentOutOfRangeException ("size");
 
-                       return ReceiveFrom_nochecks (buf, 0, size, flags, ref remote_end);
+                       return ReceiveFrom_nochecks (buffer, 0, size, flags, ref remoteEP);
                }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
@@ -2565,25 +1683,21 @@ namespace System.Net.Sockets
                                                            ref SocketAddress sockaddr,
                                                            out int error);
 
-               public int ReceiveFrom (byte [] buf, int offset, int size, SocketFlags flags,
-                                       ref EndPoint remote_end)
+               public int ReceiveFrom (byte [] buffer, int offset, int size, SocketFlags flags,
+                                       ref EndPoint remoteEP)
                {
                        if (disposed && closed)
                                throw new ObjectDisposedException (GetType ().ToString ());
 
-                       if (buf == null)
-                               throw new ArgumentNullException ("buf");
-
-                       if (remote_end == null)
-                               throw new ArgumentNullException ("remote_end");
+                       if (buffer == null)
+                               throw new ArgumentNullException ("buffer");
 
-                       if (offset < 0 || offset > buf.Length)
-                               throw new ArgumentOutOfRangeException ("offset");
+                       if (remoteEP == null)
+                               throw new ArgumentNullException ("remoteEP");
 
-                       if (size < 0 || offset + size > buf.Length)
-                               throw new ArgumentOutOfRangeException ("size");
+                       CheckRange (buffer, offset, size);
 
-                       return ReceiveFrom_nochecks (buf, offset, size, flags, ref remote_end);
+                       return ReceiveFrom_nochecks (buffer, offset, size, flags, ref remoteEP);
                }
 
                internal int ReceiveFrom_nochecks (byte [] buf, int offset, int size, SocketFlags flags,
@@ -2615,10 +1729,7 @@ namespace System.Net.Sockets
                        }
 
                        connected = true;
-
-#if NET_2_0
                        isbound = true;
-#endif
 
                        // If sockaddr is null then we're a connection
                        // oriented protocol and should ignore the
@@ -2636,7 +1747,6 @@ namespace System.Net.Sockets
                        return cnt;
                }
 
-#if NET_2_0
                [MonoTODO ("Not implemented")]
                public bool ReceiveMessageFromAsync (SocketAsyncEventArgs e)
                {
@@ -2663,11 +1773,7 @@ namespace System.Net.Sockets
                        if (remoteEP == null)
                                throw new ArgumentNullException ("remoteEP");
 
-                       if (offset < 0 || offset > buffer.Length)
-                               throw new ArgumentOutOfRangeException ("offset");
-
-                       if (size < 0 || offset + size > buffer.Length)
-                               throw new ArgumentOutOfRangeException ("size");
+                       CheckRange (buffer, offset, size);
 
                        /* FIXME: figure out how we get hold of the
                         * IPPacketInformation
@@ -2686,8 +1792,6 @@ namespace System.Net.Sockets
                        throw new NotImplementedException ();
                }
 
-#endif
-
                public int Send (byte [] buf)
                {
                        if (disposed && closed)
@@ -2732,8 +1836,7 @@ namespace System.Net.Sockets
                        if (buf == null)
                                throw new ArgumentNullException ("buf");
 
-                       if (size < 0 || size > buf.Length)
-                               throw new ArgumentOutOfRangeException ("size");
+                       CheckRange (buf, 0, size);
 
                        SocketError error;
 
@@ -2753,11 +1856,7 @@ namespace System.Net.Sockets
                        if (buf == null)
                                throw new ArgumentNullException ("buffer");
 
-                       if (offset < 0 || offset > buf.Length)
-                               throw new ArgumentOutOfRangeException ("offset");
-
-                       if (size < 0 || offset + size > buf.Length)
-                               throw new ArgumentOutOfRangeException ("size");
+                       CheckRange (buf, offset, size);
 
                        SocketError error;
 
@@ -2769,7 +1868,6 @@ namespace System.Net.Sockets
                        return ret;
                }
 
-#if NET_2_0
                public int Send (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
                {
                        if (disposed && closed)
@@ -2778,96 +1876,14 @@ namespace System.Net.Sockets
                        if (buf == null)
                                throw new ArgumentNullException ("buffer");
 
-                       if (offset < 0 || offset > buf.Length)
-                               throw new ArgumentOutOfRangeException ("offset");
-
-                       if (size < 0 || offset + size > buf.Length)
-                               throw new ArgumentOutOfRangeException ("size");
+                       CheckRange (buf, offset, size);
 
                        return Send_nochecks (buf, offset, size, flags, out error);
                }
 
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               private extern static int Send_internal (IntPtr sock,
-                                                        WSABUF[] bufarray,
-                                                        SocketFlags flags,
-                                                        out int error);
-
-               public int Send (IList<ArraySegment<byte>> buffers)
-               {
-                       int ret;
-                       SocketError error;
-                       
-                       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)
-               {
-                       int ret;
-                       SocketError error;
-                       
-                       ret = Send (buffers, socketFlags, out error);
-                       if (error != SocketError.Success) {
-                               throw new SocketException ((int)error);
-                       }
-                       
-                       return(ret);
-               }
-
-               [CLSCompliant (false)]
-               public int Send (IList<ArraySegment<byte>> buffers,
-                                SocketFlags socketFlags,
-                                out SocketError errorCode)
-               {
-                       if (disposed && closed) {
-                               throw new ObjectDisposedException (GetType ().ToString ());
-                       }
-                       
-                       if (buffers == null) {
-                               throw new ArgumentNullException ("buffers");
-                       }
-                       
-                       if (buffers.Count == 0) {
-                               throw new ArgumentException ("Buffer is empty", "buffers");
-                       }
-                       
-                       int numsegments = buffers.Count;
-                       int nativeError;
-                       int ret;
-                       
-                       WSABUF[] bufarray = new WSABUF[numsegments];
-                       GCHandle[] gch = new GCHandle[numsegments];
-                       
-                       for(int i = 0; i < numsegments; i++) {
-                               ArraySegment<byte> segment = buffers[i];
-                               gch[i] = GCHandle.Alloc (segment.Array, GCHandleType.Pinned);
-                               bufarray[i].len = segment.Count;
-                               bufarray[i].buf = Marshal.UnsafeAddrOfPinnedArrayElement (segment.Array, segment.Offset);
-                       }
-                       
-                       try {
-                               ret = Send_internal (socket, bufarray,
-                                                    socketFlags,
-                                                    out nativeError);
-                       } finally {
-                               for(int i = 0; i < numsegments; i++) {
-                                       if (gch[i].IsAllocated) {
-                                               gch[i].Free ();
-                                       }
-                               }
-                       }
-                       
-                       errorCode = (SocketError)nativeError;
-                       return(ret);
-               }
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private extern static bool SendFile (IntPtr sock, string filename, byte [] pre_buffer, byte [] post_buffer, TransmitFileOptions flags);
 
-               [MonoTODO ("Not implemented")]
                public void SendFile (string fileName)
                {
                        if (disposed && closed)
@@ -2879,14 +1895,9 @@ namespace System.Net.Sockets
                        if (!blocking)
                                throw new InvalidOperationException ();
 
-                       if (!File.Exists (fileName))
-                               throw new FileNotFoundException ();
-
-                       /* FIXME: Implement TransmitFile */
-                       throw new NotImplementedException ();
+                       SendFile (fileName, null, null, 0);
                }
 
-               [MonoTODO ("Not implemented")]
                public void SendFile (string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags)
                {
                        if (disposed && closed)
@@ -2898,25 +1909,41 @@ namespace System.Net.Sockets
                        if (!blocking)
                                throw new InvalidOperationException ();
 
-                       if (!File.Exists (fileName))
-                               throw new FileNotFoundException ();
-
-                       /* FIXME: Implement TransmitFile */
-                       throw new NotImplementedException ();
+                       if (!SendFile (socket, fileName, preBuffer, postBuffer, flags)) {
+                               SocketException exc = new SocketException ();
+                               if (exc.ErrorCode == 2 || exc.ErrorCode == 3)
+                                       throw new FileNotFoundException ();
+                               throw exc;
+                       }
                }
 
+#if !MOONLIGHT
                public bool SendToAsync (SocketAsyncEventArgs e)
                {
                        // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
                        
                        if (disposed && closed)
                                throw new ObjectDisposedException (GetType ().ToString ());
+                       if (e.BufferList != null)
+                               throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
                        if (e.RemoteEndPoint == null)
                                throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
-                       
-                       e.DoOperation (SocketAsyncOperation.SendTo, this);
 
-                       // We always return true for now
+                       e.curSocket = this;
+                       e.Worker.Init (this, e, SocketOperation.SendTo);
+                       SocketAsyncResult res = e.Worker.result;
+                       res.Buffer = e.Buffer;
+                       res.Offset = e.Offset;
+                       res.Size = e.Count;
+                       res.SockFlags = e.SocketFlags;
+                       res.EndPoint = e.RemoteEndPoint;
+                       int count;
+                       lock (writeQ) {
+                               writeQ.Enqueue (e.Worker);
+                               count = writeQ.Count;
+                       }
+                       if (count == 1)
+                               socket_pool_queue (Worker.Dispatcher, res);
                        return true;
                }
 #endif
@@ -2960,8 +1987,7 @@ namespace System.Net.Sockets
                        if (remote_end == null)
                                throw new ArgumentNullException ("remote_end");
 
-                       if (size < 0 || size > buffer.Length)
-                               throw new ArgumentOutOfRangeException ("size");
+                       CheckRange (buffer, 0, size);
 
                        return SendTo_nochecks (buffer, 0, size, flags, remote_end);
                }
@@ -2987,11 +2013,7 @@ namespace System.Net.Sockets
                        if (remote_end == null)
                                throw new ArgumentNullException("remote_end");
 
-                       if (offset < 0 || offset > buffer.Length)
-                               throw new ArgumentOutOfRangeException ("offset");
-
-                       if (size < 0 || offset + size > buffer.Length)
-                               throw new ArgumentOutOfRangeException ("size");
+                       CheckRange (buffer, offset, size);
 
                        return SendTo_nochecks (buffer, offset, size, flags, remote_end);
                }
@@ -3014,87 +2036,85 @@ namespace System.Net.Sockets
                        }
 
                        connected = true;
-
-#if NET_2_0
                        isbound = true;
-#endif
-                       
                        seed_endpoint = remote_end;
                        
                        return ret;
                }
 
-               public void SetSocketOption (SocketOptionLevel level, SocketOptionName name, byte[] opt_value)
+               public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, byte [] optionValue)
                {
                        if (disposed && closed)
                                throw new ObjectDisposedException (GetType ().ToString ());
 
-                       int error;
+                       // I'd throw an ArgumentNullException, but this is what MS does.
+                       if (optionValue == null)
+                               throw new SocketException ((int) SocketError.Fault,
+                                       "Error trying to dereference an invalid pointer");
                        
-                       SetSocketOption_internal(socket, level, name, null,
-                                                opt_value, 0, out error);
+                       int error;
 
-                       if (error != 0)
+                       SetSocketOption_internal (socket, optionLevel, optionName, null,
+                                                optionValue, 0, out error);
+
+                       if (error != 0) {
+                               if (error == (int) SocketError.InvalidArgument)
+                                       throw new ArgumentException ();
                                throw new SocketException (error);
+                       }
                }
 
-               public void SetSocketOption (SocketOptionLevel level, SocketOptionName name, object opt_value)
+               public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, object optionValue)
                {
-
                        if (disposed && closed)
                                throw new ObjectDisposedException (GetType ().ToString ());
 
-                       if (opt_value == null)
-                               throw new ArgumentNullException("opt_value");
+                       // NOTE: if a null is passed, the byte[] overload is used instead...
+                       if (optionValue == null)
+                               throw new ArgumentNullException("optionValue");
                        
                        int error;
-                       /* From MS documentation on SetSocketOption: "For an
-                        * option with a Boolean data type, specify a nonzero
-                        * value to enable the option, and a zero value to
-                        * disable the option."
-                        * Booleans are only handled in 2.0
-                        */
 
-                       if (opt_value is System.Boolean) {
-#if NET_2_0
-                               bool bool_val = (bool) opt_value;
-                               int int_val = (bool_val) ? 1 : 0;
-
-                               SetSocketOption_internal (socket, level, name, null, null, int_val, out error);
-#else
-                               throw new ArgumentException ("Use an integer 1 (true) or 0 (false) instead of a boolean.", "opt_value");
-#endif
+                       if (optionLevel == SocketOptionLevel.Socket && optionName == SocketOptionName.Linger) {
+                               LingerOption linger = optionValue as LingerOption;
+                               if (linger == null)
+                                       throw new ArgumentException ("A 'LingerOption' value must be specified.", "optionValue");
+                               SetSocketOption_internal (socket, 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 (socket, 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 (socket, optionLevel, optionName, multicast, null, 0, out error);
                        } else {
-                               SetSocketOption_internal (socket, level, name, opt_value, null, 0, out error);
+                               throw new ArgumentException ("Invalid value specified.", "optionValue");
                        }
 
-                       if (error != 0)
+                       if (error != 0) {
+                               if (error == (int) SocketError.InvalidArgument)
+                                       throw new ArgumentException ();
                                throw new SocketException (error);
+                       }
                }
 
-#if NET_2_0
-               public void SetSocketOption (SocketOptionLevel level, SocketOptionName name, bool optionValue)
+               public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, bool optionValue)
                {
                        if (disposed && closed)
                                throw new ObjectDisposedException (GetType ().ToString ());
 
                        int error;
                        int int_val = (optionValue) ? 1 : 0;
-                       SetSocketOption_internal (socket, level, name, null, null, int_val, out error);
-                       if (error != 0)
+                       SetSocketOption_internal (socket, optionLevel, optionName, null, null, int_val, out error);
+                       if (error != 0) {
+                               if (error == (int) SocketError.InvalidArgument)
+                                       throw new ArgumentException ();
                                throw new SocketException (error);
+                       }
                }
-#endif
-
-#if ONLY_1_1
-               public override int GetHashCode ()
-               {
-                       // LAMESPEC:
-                       // The socket is not suitable to serve as a hash code,
-                       // because it will change during its lifetime, but
-                       // this is how MS.NET 1.1 implemented this method.
-                       return (int) socket; 
-               }
-#endif
        }
 }
+