* Makefile: Added new targets for running the tests. Now the generated
[mono.git] / mcs / class / System / System.Net.Sockets / Socket.cs
index 05a322df553fa5903b08870a1472b39246edc1f0..bb93fcd57b2ff6e9ecc24ed2abe076ffb3550e46 100644 (file)
 // System.Net.Sockets.Socket.cs
 //
-// Author:
-//    Phillip Pearson (pp@myelin.co.nz)
+// Authors:
+//     Phillip Pearson (pp@myelin.co.nz)
+//     Dick Porter <dick@ximian.com>
+//     Gonzalo Paniagua Javier (gonzalo@ximian.com)
 //
-// Copyright (C) 2001, Phillip Pearson
+// Copyright (C) 2001, 2002 Phillip Pearson and Ximian, Inc.
 //    http://www.myelin.co.nz
+// (c) 2004 Novell, Inc. (http://www.novell.com)
 //
 
-// NB: This is untested (probably buggy) code - take care if using it
-//     Nowhere near finished yet ...
-
 using System;
 using System.Net;
 using System.Collections;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Reflection;
+using System.IO;
 
-namespace System.Net.Sockets \r
+namespace System.Net.Sockets 
 {
-
-       public class Socket : IDisposable \r
+       public class Socket : IDisposable 
        {
-               // static method:
-
-               /// <summary>\r
-               /// Blocks while waiting for readability, writeability or\r
-               /// error conditions on a number of sockets\r
-               /// </summary>\r
-               /// <param name="read_list">A list of sockets to watch\r
-               /// for readability</param>\r
-               /// <param name="write_list">A list of sockets to watch\r
-               /// for writeability</param>\r
-               /// <param name="err_list">A list of sockets to watch\r
-               /// for errors</param>\r
-               /// <param name="time_us">Timeout, in microseconds</param>
-               public static void Select (
-                       IList read_list,
-                       IList write_list,
-                       IList err_list,
-                       int time_us)
-               {
-                       throw new NotImplementedException();
-               }
-
-               // public constructor:
-
-               /// <summary>\r
-               /// Makes a new Socket\r
-               /// </summary>\r
-               /// <param name="family">Address family (e.g. \r
-               /// AddressFamily.InterNetwork for IPv4)</param>\r
-               /// <param name="type">Socket Type (e.g. SocketType.Stream\r
-               /// for stream sockets)</param>\r
-               /// <param name="proto">Protocol (e.g.
-               /// ProtocolType.Tcp for TCP)</param>
-               public Socket (\r
-                       AddressFamily family,\r
-                       SocketType type,\r
-                       ProtocolType proto)\r
-               {
-                       throw new NotImplementedException();
-               }
-
-               // public properties:
-
-               /// <summary>\r
-               /// The address family (see contructor)\r
-               /// </summary>
-               public AddressFamily AddressFamily\r
-               {
-                       get \r
+               [StructLayout (LayoutKind.Sequential)]
+               private sealed class SocketAsyncResult: IAsyncResult 
+               {
+                       /* Same structure in the runtime */
+                       public Socket Sock;
+                       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
+
+                       // Return values
+                       Socket acc_socket;
+                       int total;
+
+                       bool completed_sync;
+                       bool completed;
+                       AsyncCallback real_callback;
+                       int error;
+
+                       public SocketAsyncResult (Socket sock, object state, AsyncCallback callback)
                        {
-                               throw new NotImplementedException();
-                               //return AddressFamily.InterNetwork;
+                               this.Sock = sock;
+                               this.handle = sock.socket;
+                               this.state = state;
+                               this.real_callback = callback;
+                               SockFlags = SocketFlags.None;
+                       }
+
+                       public void CreateAsyncDelegate ()
+                       {
+                               if (real_callback != null)
+                                       this.callback = new AsyncCallback (FakeCB);
+                       }
+
+                       static void FakeCB (IAsyncResult result)
+                       {
+                               SocketAsyncResult ares = (SocketAsyncResult) result;
+                               ares.real_callback.BeginInvoke (ares, null, null);
+                       }
+
+                       public void CheckIfThrowDelayedException ()
+                       {
+                               if (delayedException != null)
+                                       throw delayedException;
+
+                               if (error != 0)
+                                       throw new SocketException (error);
+                       }
+
+                       public void Complete ()
+                       {
+                               IsCompleted = true;
+                               if (real_callback != null)
+                                       real_callback (this);
+                       }
+
+                       public void Complete (int total)
+                       {
+                               this.total = total;
+                               Complete ();
+                       }
+                       
+                       public void Complete (Exception e)
+                       {
+                               delayedException = e;
+                               Complete ();
+                       }
+
+                       public void Complete (Socket s)
+                       {
+                               acc_socket = s;
+                               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;
+                               }
                        }
                }
 
-               /// <summary>\r
-               /// How much data is waiting to be read (i.e. the amount\r
-               /// of data in the in buffer)\r
-               /// </summary>
-               public int Available \r
+               private sealed class Worker 
                {
+                       SocketAsyncResult result;
+
+                       public Worker (SocketAsyncResult ares)
+                       {
+                               this.result = ares;
+                       }
+
+                       public void Accept ()
+                       {
+                               lock (result) {
+                                       Socket acc_socket = null;
+                                       try {
+                                               acc_socket = result.Sock.Accept ();
+                                       } catch (Exception e) {
+                                               result.Complete (e);
+                                               return;
+                                       }
+
+                                       result.Complete (acc_socket);
+                               }
+                       }
+
+                       public void Connect ()
+                       {
+                               lock (result) {
+                                       try {
+                                               result.Sock.Connect (result.EndPoint);
+                                       } catch (SocketException se) {
+                                               if (result.Sock.blocking || se.ErrorCode != 10036) {
+                                                       result.Complete (se);
+                                                       return;
+                                               }
+                                               
+                                               try {
+                                                       result.Sock.Poll (-1, SelectMode.SelectWrite);
+                                                       result.Sock.Connect (result.EndPoint);
+                                               } catch (Exception k) {
+                                                       result.Complete (k);
+                                                       return;
+                                               }
+                                       } catch (Exception e) {
+                                               result.Complete (e);
+                                               return;
+                                       }
+
+                                       result.Complete ();
+                               }
+                       }
+
+                       public void Receive ()
+                       {
+                               lock (result) {
+                                       int total = 0;
+                                       try {
+                                               if (!result.Sock.blocking)
+                                                       result.Sock.Poll (-1, SelectMode.SelectRead);
+
+                                               total = result.Sock.Receive_nochecks (result.Buffer,
+                                                                            result.Offset,
+                                                                            result.Size,
+                                                                            result.SockFlags);
+                                       } catch (Exception e) {
+                                               result.Complete (e);
+                                               return;
+                                       }
+
+                                       result.Complete (total);
+                               }
+                       }
+
+                       public void ReceiveFrom ()
+                       {
+                               lock (result) {
+                                       int total = 0;
+                                       try {
+                                               if (!result.Sock.blocking)
+                                                       result.Sock.Poll (-1, SelectMode.SelectRead);
+
+                                               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 Send ()
+                       {
+                               lock (result) {
+                                       int total = 0;
+                                       try {
+                                               if (!result.Sock.blocking)
+                                                       result.Sock.Poll (-1, SelectMode.SelectWrite);
+
+                                               total = result.Sock.Send_nochecks (result.Buffer,
+                                                                         result.Offset,
+                                                                         result.Size,
+                                                                         result.SockFlags);
+                                       } catch (Exception e) {
+                                               result.Complete (e);
+                                               return;
+                                       }
+
+                                       result.Complete (total);
+                               }
+                       }
+
+                       public void SendTo() {
+                               lock (result) {
+                                       int total = 0;
+                                       try {
+                                               if (!result.Sock.blocking)
+                                                       result.Sock.Poll (-1, SelectMode.SelectWrite);
+
+                                               total = result.Sock.SendTo_nochecks (result.Buffer,
+                                                                           result.Offset,
+                                                                           result.Size,
+                                                                           result.SockFlags,
+                                                                           result.EndPoint);
+                                       } catch (Exception e) {
+                                               result.Complete (e);
+                                               return;
+                                       }
+
+                                       result.Complete (total);
+                               }
+                       }
+               }
+                       
+               /* the field "socket" is looked up by name by the runtime */
+               private IntPtr socket;
+               private AddressFamily address_family;
+               private SocketType socket_type;
+               private ProtocolType protocol_type;
+               internal bool blocking=true;
+               private int pendingEnds;
+               private int closeDelayed;
+               static readonly bool supportsAsync = FakeGetSupportsAsync ();
+
+               delegate void SocketAsyncCall ();
+               /*
+                *      These two fields are looked up by name by the runtime, don't change
+                *  their name without also updating the runtime code.
+                */
+               private static int ipv4Supported = -1, ipv6Supported = -1;
+
+               /* When true, the socket was connected at the time of
+                * the last IO operation
+                */
+               private bool connected=false;
+               /* true if we called Close_internal */
+               private bool closed;
+
+               /* Used in LocalEndPoint and RemoteEndPoint if the
+                * Mono.Posix assembly is available
+                */
+               private static object unixendpoint=null;
+               private static Type unixendpointtype=null;
+               
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private extern static void Select_internal(ref Socket[] read,
+                                                          ref Socket[] write,
+                                                          ref Socket[] err,
+                                                          int timeout,
+                                                          out int error);
+
+               public static void Select(IList read_list, IList write_list,
+                                         IList err_list, int time_us) {
+                       if(read_list==null &&
+                          write_list==null &&
+                          err_list==null) {
+                               throw new ArgumentNullException();
+                       }
+
+                       int read_count = 0, write_count = 0, err_count = 0;
+                       Socket[] read_arr = null;
+                       Socket[] write_arr = null;
+                       Socket[] err_arr = null;
+
+                       if (read_list!=null)
+                               read_count=read_list.Count;
+
+                       if (read_count != 0)
+                               read_arr=new Socket[read_count];
+
+                       if (write_list!=null)
+                               write_count=write_list.Count;
+
+                       if (write_count != 0)
+                               write_arr=new Socket[write_count];
+
+                       if (err_list!=null)
+                               err_count=err_list.Count;
+
+                       if (err_count != 0)
+                               err_arr=new Socket[err_count];
+                       
+                       int i;
+
+                       if (read_count != 0) {
+                               i=0;
+                               
+                               foreach (Socket s in read_list) {
+                                       read_arr[i]=s;
+                                       i++;
+                               }
+                       }
+
+                       if (write_count != 0) {
+                               i=0;
+                               foreach (Socket s in write_list) {
+                                       write_arr[i]=s;
+                                       i++;
+                               }
+                       }
+                       
+                       if (err_count != 0) {
+                               i=0;
+                               foreach (Socket s in err_list) {
+                                       err_arr[i]=s;
+                                       i++;
+                               }
+                       }
+
+                       int error;
+                       
+                       Select_internal(ref read_arr, ref write_arr,
+                                       ref err_arr, time_us, out error);
+
+                       if(error != 0) {
+                               throw new SocketException (error);
+                       }
+
+                       if(read_list!=null) {
+                               read_list.Clear();
+                               for(i=0; i<read_arr.Length; i++) {
+                                       read_list.Add(read_arr[i]);
+                               }
+                       }
+                       
+                       if(write_list!=null) {
+                               write_list.Clear();
+                               for(i=0; i<write_arr.Length; i++) {
+                                       write_list.Add(write_arr[i]);
+                               }
+                       }
+                       
+                       if(err_list!=null) {
+                               err_list.Clear();
+                               for(i=0; i<err_arr.Length; i++) {
+                                       err_list.Add(err_arr[i]);
+                               }
+                       }
+               }
+
+               static Socket() {
+                       Assembly ass;
+                       
+                       try {
+                               ass = Assembly.Load (Consts.AssemblyMono_Posix);
+                       } catch (FileNotFoundException) {
+                               return;
+                       }
+                               
+                       unixendpointtype=ass.GetType("Mono.Posix.UnixEndPoint");
+
+                       /* The endpoint Create() method is an instance
+                        * method :-(
+                        */
+                       Type[] arg_types=new Type[1];
+                       arg_types[0]=typeof(string);
+                       ConstructorInfo cons=unixendpointtype.GetConstructor(arg_types);
+
+                       object[] args=new object[1];
+                       args[0]="";
+
+                       unixendpoint=cons.Invoke(args);
+               }
+
+               // private constructor used by Accept, which already
+               // has a socket handle to use
+               private Socket(AddressFamily family, SocketType type,
+                              ProtocolType proto, IntPtr sock) {
+                       address_family=family;
+                       socket_type=type;
+                       protocol_type=proto;
+                       
+                       socket=sock;
+                       connected=true;
+               }
+               
+               // Creates a new system socket, returning the handle
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private extern IntPtr Socket_internal(AddressFamily family,
+                                                     SocketType type,
+                                                     ProtocolType proto,
+                                                     out int error);
+               
+               public Socket(AddressFamily family, SocketType type,
+                             ProtocolType proto) {
+                       address_family=family;
+                       socket_type=type;
+                       protocol_type=proto;
+                       
+                       int error;
+                       
+                       socket=Socket_internal(family, type, proto, out error);
+                       if (error != 0) {
+                               throw new SocketException (error);
+                       }
+               }
+
+               public AddressFamily AddressFamily {
                        get {
-                               throw new NotImplementedException();
-                               //return 0;
+                               return(address_family);
                        }
                }
 
-               /// <summary>\r
-               /// A flag to indicate whether the socket is a blocking\r
-               /// socket or not.  Returns true if blocking.\r
-               /// \r
-               /// A non-blocking socket (Blocking == false) will return\r
-               /// control to the application immediately if any calls are\r
-               /// made that may take a while to complete.  Blocking\r
-               /// sockets will block the app until whatever they are doing\r
-               /// is finished.\r
-               /// </summary>
-               public bool Blocking \r
-               {
+               // Returns the amount of data waiting to be read on socket
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private extern static int Available_internal(IntPtr socket,
+                                                            out int error);
+               
+               public int Available {
                        get {
-                               throw new NotImplementedException();
-                               //return false;
+                               if (disposed && closed)
+                                       throw new ObjectDisposedException (GetType ().ToString ());
+
+                               int ret, error;
+                               
+                               ret = Available_internal(socket, out error);
+
+                               if (error != 0) {
+                                       throw new SocketException (error);
+                               }
+
+                               return(ret);
                        }
-                       set { }
                }
 
-               /// <summary>\r
-               /// A flag to say whether the socket is connected to something\r
-               /// or not.\r
-               /// \r
-               /// Returns true if connected.\r
-               /// </summary>
-               public bool Connected \r
-               {
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private extern static void Blocking_internal(IntPtr socket,
+                                                            bool block,
+                                                            out int error);
+
+               public bool Blocking {
                        get {
-                               throw new NotImplementedException();
-                               //return false;
+                               return(blocking);
+                       }
+                       set {
+                               int error;
+                               
+                               Blocking_internal(socket, value, out error);
+
+                               if (error != 0) {
+                                       throw new SocketException (error);
+                               }
+                               
+                               blocking=value;
                        }
                }
 
-               /// <summary>\r
-               /// A handle to the socket (its file descriptor?)\r
-               /// </summary>
-               public IntPtr Handle \r
-               {
+               public bool Connected {
                        get {
-                               throw new NotImplementedException();
-                               //return new IntPtr(0);
+                               return(connected);
                        }
                }
 
-               /// <summary>\r
-               /// The socket's local endpoint (where it's coming from)\r
-               /// </summary>
-               public EndPoint LocalEndPoint \r
-               {
+               public IntPtr Handle {
                        get {
-                               throw new NotImplementedException();
-                               //return new IPEndPoint(0,0);
+                               return(socket);
                        }
                }
 
-               /// <summary>\r
-               /// Protocol type (e.g. Tcp, Udp)\r
-               /// </summary>
-               public ProtocolType ProtocolType \r
-               {
+               // Returns the local endpoint details in addr and port
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private extern static SocketAddress LocalEndPoint_internal(IntPtr socket, out int error);
+
+               [MonoTODO("Support non-IP endpoints")]
+               public EndPoint LocalEndPoint {
                        get {
-                               throw new NotImplementedException();
-                               //return ProtocolType.Tcp;
+                               if (disposed && closed)
+                                       throw new ObjectDisposedException (GetType ().ToString ());
+
+                               SocketAddress sa;
+                               int error;
+                               
+                               sa=LocalEndPoint_internal(socket, out error);
+
+                               if (error != 0) {
+                                       throw new SocketException (error);
+                               }
+
+                               if(sa.Family==AddressFamily.InterNetwork || sa.Family==AddressFamily.InterNetworkV6) {
+                                       // Stupidly, EndPoint.Create() is an
+                                       // instance method
+                                       return new IPEndPoint(0, 0).Create(sa);
+                               } else if (sa.Family==AddressFamily.Unix &&
+                                          unixendpoint!=null) {
+                                       return((EndPoint)unixendpointtype.InvokeMember("Create", BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public, null, unixendpoint, new object[] {sa}));
+                               } else {
+                                       throw new NotImplementedException();
+                               }
                        }
                }
 
-               /// <summary>\r
-               /// The socket's remote endpoint (where it's connected to)\r
-               /// </summary>
-               public EndPoint RemoteEndPoint \r
-               {
+               public ProtocolType ProtocolType {
                        get {
-                               throw new NotImplementedException();
-                               //return new IPEndPoint(0,0);
+                               return(protocol_type);
                        }
                }
 
-               /// <summary>\r
-               /// Socket type (e.g. datagram, stream)\r
-               /// </summary>
-               public SocketType SocketType \r
-               {
+               // Returns the remote endpoint details in addr and port
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private extern static SocketAddress RemoteEndPoint_internal(IntPtr socket, out int error);
+
+               [MonoTODO("Support non-IP endpoints")]
+               public EndPoint RemoteEndPoint {
+                       get {
+                               if (disposed && closed)
+                                       throw new ObjectDisposedException (GetType ().ToString ());
+
+                               SocketAddress sa;
+                               int error;
+                               
+                               sa=RemoteEndPoint_internal(socket, out error);
+
+                               if (error != 0) {
+                                       throw new SocketException (error);
+                               }
+
+                               if(sa.Family==AddressFamily.InterNetwork || sa.Family==AddressFamily.InterNetworkV6 ) {
+                                       // Stupidly, EndPoint.Create() is an
+                                       // instance method
+                                       return new IPEndPoint(0, 0).Create(sa);
+                               } else if (sa.Family==AddressFamily.Unix &&
+                                          unixendpoint!=null) {
+                                       return((EndPoint)unixendpointtype.InvokeMember("Create", BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public, null, unixendpoint, new object[] {sa}));
+                               } else {
+                                       throw new NotImplementedException();
+                               }
+                       }
+               }
+
+               public SocketType SocketType {
                        get {
-                               throw new NotImplementedException();
-                               //return SocketType.Stream;
-                       }
-               }
-
-               // public methods:
-
-               /// <summary>\r
-               /// Accepts a new connection\r
-               /// </summary>\r
-               /// <returns>A new socket to handle the connection</returns>
-               public Socket Accept () \r
-               {
-                       throw new NotImplementedException();
-                       //return new Socket(AddressFamily.InterNetwork,
-                       //      SocketType.Stream, ProtocolType.Tcp);
-               }
-
-               /// <summary>\r
-               /// Accepts the connection in the background,\r
-               /// calling the application back when finished.\r
-               /// </summary>\r
-               /// <param name="callback">A delegate to be called\r
-               /// when the accept is finished</param>\r
-               /// <param name="state">State information for this call</param>\r
-               /// <returns></returns>
-               public IAsyncResult BeginAccept (
-                       AsyncCallback callback,
-                       object state)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Connects to a remote endpoint in the background,\r
-               /// calling back when finished.\r
-               /// </summary>\r
-               /// <param name="remote_end_point">The endpoint to\r
-               /// connect to</param>\r
-               /// <param name="callback">Where to call when done</param>\r
-               /// <param name="state">State information for this call</param>\r
-               /// <returns></returns>
-               public IAsyncResult BeginConnect (
-                       EndPoint remote_end_point,
-                       AsyncCallback callback,
-                       object state)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Receives data in the background, calling\r
-               /// back when finished.\r
-               /// </summary>\r
-               /// <param name="buffer">A buffer to put the data into as it\r
-               /// arrives</param>\r
-               /// <param name="offset">Where to put the data (offset into\r
-               /// the buffer)</param>\r
-               /// <param name="size">Buffer size</param>\r
-               /// <param name="socket_flags">Socket flags</param>\r
-               /// <param name="callback">Where to call when the\r
-               /// operation is finished</param>\r
-               /// <param name="state">State info for this call</param>\r
-               /// <returns></returns>
-               public IAsyncResult BeginReceive (
-                       byte[] buffer,
-                       int offset,
-                       int size,
-                       SocketFlags socket_flags,
-                       AsyncCallback callback,
-                       object state)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Receives data in the background from a specific\r
-               /// point, calling back when finished.\r
-               /// </summary>\r
-               /// <param name="buffer">A buffer to put the data into as it\r
-               /// arrives</param>\r
-               /// <param name="offset">Where to put the data (offset into\r
-               /// the buffer)</param>\r
-               /// <param name="size">Buffer size</param>\r
-               /// <param name="socket_flags">Socket flags</param>\r
-               /// <param name="remote_end_point">Where to receive from</param>\r
-               /// <param name="callback">Where to call when the\r
-               /// operation is finished</param>\r
-               /// <param name="state">State info for this call</param>\r
-               /// <returns></returns>
-               public IAsyncResult BeginReceiveFrom (
-                       byte[] buffer,
-                       int offset,
-                       int size,
-                       SocketFlags socket_flags,
-                       ref EndPoint remote_end_point,
-                       AsyncCallback callback,
-                       object state)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Starts sending data somewhere, in the background.\r
-               /// </summary>\r
-               /// <param name="buffer">Buffer containing the data to send</param>\r
-               /// <param name="offset">Where in the buffer to start sending from</param>\r
-               /// <param name="size">Buffer size</param>\r
-               /// <param name="socket_flags">Socket flags</param>\r
-               /// <param name="callback">Where to call back to when finished</param>\r
-               /// <param name="state">State info for this call</param>\r
-               /// <returns></returns>
-               public IAsyncResult BeginSend (
-                       byte[] buffer,
-                       int offset,
-                       int size,
-                       SocketFlags socket_flags,
-                       AsyncCallback callback,
-                       object state)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Starts sending data to a specific point, in the background\r
-               /// </summary>\r
-               /// <param name="buffer"></param>\r
-               /// <param name="offset"></param>\r
-               /// <param name="size"></param>\r
-               /// <param name="socket_flags"></param>\r
-               /// <param name="remote_end_point"></param>\r
-               /// <param name="callback">Where to call back to when\r
-               /// finished sending</param>\r
-               /// <param name="state"></param>\r
-               /// <returns></returns>
-               public IAsyncResult BeginSendTo (
-                       byte[] buffer,
-                       int offset,
-                       int size,
-                       SocketFlags socket_flags,
-                       EndPoint remote_end_point,
-                       AsyncCallback callback,
-                       object state)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Binds the socket to a local endpoint\r
-               /// </summary>\r
-               /// <param name="local_end_point">What to
-               /// bind it to</param>
-               public void Bind (EndPoint local_end_point)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Closes the socket\r
-               /// </summary>
-               public void Close ()
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Connects to a remote system\r
-               /// </summary>\r
-               /// <param name="remote_end_point">Where to connect to</param>
-               public void Connect (EndPoint remote_end_point)
-               {
-                       throw new NotImplementedException();
+                               return(socket_type);
+                       }
+               }
+
+#if NET_1_1
+               public static bool SupportsIPv4 {
+                       get {
+                               CheckProtocolSupport();
+                               return ipv4Supported == 1;
+                       }
+               }
+
+               public static bool SupportsIPv6 {
+                       get {
+                               CheckProtocolSupport();
+                               return ipv6Supported == 1;
+                       }
+               }
+#else
+               internal static bool SupportsIPv4 
+               {
+                       get 
+                       {
+                               return true;
+                       }
                }
+
+               internal static bool SupportsIPv6 
+               {
+                       get 
+                       {
+                               return false;
+                       }
+               }
+#endif
+
+               internal static void CheckProtocolSupport()
+               {
+                       if(ipv4Supported == -1) {
+                               try  {
+                                       Socket tmp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+                                       tmp.Close();
+
+                                       ipv4Supported = 1;
+                               }
+                               catch {
+                                       ipv4Supported = 0;
+                               }
+                       }
+
+                       if(ipv6Supported == -1) {
+                               NetConfig config = (NetConfig)System.Configuration.ConfigurationSettings.GetConfig("system.net/settings");
+
+                               if(config != null)
+                                       ipv6Supported = config.ipv6Enabled?-1:0;
+
+                               if(ipv6Supported != 0) {
+                                       try {
+                                               Socket tmp = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
+                                               tmp.Close();
+
+                                               ipv6Supported = 1;
+                                       }
+                                       catch { }
+                               }
+                       }
+               }
+
+               // Creates a new system socket, returning the handle
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private extern static IntPtr Accept_internal(IntPtr sock,
+                                                            out int error);
                
-               /// <summary>\r
-               /// Completes an Accept() operation started\r
-               /// with a BeginAccept() call\r
-               /// </summary>\r
-               /// <param name="result"></param>\r
-               /// <returns></returns>
-               public Socket EndAccept (IAsyncResult result)
-               {
-                       throw new NotImplementedException();
+               public Socket Accept() {
+                       if (disposed && closed)
+                               throw new ObjectDisposedException (GetType ().ToString ());
+
+                       int error;
+                       IntPtr sock=Accept_internal(socket, out error);
+
+                       if (error != 0) {
+                               throw new SocketException (error);
+                       }
+                       
+                       return(new Socket(this.AddressFamily, this.SocketType,
+                                         this.ProtocolType, sock));
+               }
+
+               public IAsyncResult BeginAccept(AsyncCallback callback,
+                                               object state) {
+
+                       if (disposed && closed)
+                               throw new ObjectDisposedException (GetType ().ToString ());
+
+                       Interlocked.Increment (ref pendingEnds);
+                       SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
+                       Worker worker = new Worker (req);
+                       SocketAsyncCall sac = new SocketAsyncCall (worker.Accept);
+                       sac.BeginInvoke (null, null);
+                       return(req);
+               }
+
+               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");
+
+                       Interlocked.Increment (ref pendingEnds);
+                       SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
+                       req.EndPoint = end_point;
+                       Worker worker = new Worker (req);
+                       SocketAsyncCall sac = new SocketAsyncCall (worker.Connect);
+                       sac.BeginInvoke (null, null);
+                       return(req);
+               }
+
+               public IAsyncResult BeginReceive(byte[] buffer, int offset,
+                                                int size,
+                                                SocketFlags socket_flags,
+                                                AsyncCallback callback,
+                                                object state) {
+
+                       if (disposed && closed)
+                               throw new ObjectDisposedException (GetType ().ToString ());
+
+                       if (buffer == null)
+                               throw new ArgumentNullException ("buffer");
+
+                       if (offset < 0 || offset > buffer.Length)
+                               throw new ArgumentOutOfRangeException ("offset");
+
+                       if (size < 0 || offset + size > buffer.Length)
+                               throw new ArgumentOutOfRangeException ("size");
+
+                       Interlocked.Increment (ref pendingEnds);
+                       SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
+                       req.Buffer = buffer;
+                       req.Offset = offset;
+                       req.Size = size;
+                       req.SockFlags = socket_flags;
+                       if (supportsAsync && socket_type == SocketType.Stream) {
+                               int error;
+                               req.CreateAsyncDelegate ();
+                               KeepReference (req);
+                               AsyncReceiveInternal (req, out error);
+                               if (error != 10036) // WSAEINPROGRESS
+                                       throw new SocketException (error);
+                       } else {
+                               Worker worker = new Worker (req);
+                               SocketAsyncCall sac = new SocketAsyncCall (worker.Receive);
+                               sac.BeginInvoke (null, null);
+                       }
+
+                       return req;
+               }
+
+               public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset,
+                                                    int size,
+                                                    SocketFlags socket_flags,
+                                                    ref EndPoint remote_end,
+                                                    AsyncCallback callback,
+                                                    object state) {
+                       if (disposed && closed)
+                               throw new ObjectDisposedException (GetType ().ToString ());
+
+                       if (buffer == null)
+                               throw new ArgumentNullException ("buffer");
+
+                       if (offset < 0)
+                               throw new ArgumentOutOfRangeException ("offset must be >= 0");
+
+                       if (size < 0)
+                               throw new ArgumentOutOfRangeException ("size must be >= 0");
+
+                       if (offset + size > buffer.Length)
+                               throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
+
+                       Interlocked.Increment (ref pendingEnds);
+                       SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
+                       req.Buffer = buffer;
+                       req.Offset = offset;
+                       req.Size = size;
+                       req.SockFlags = socket_flags;
+                       req.EndPoint = remote_end;
+                       Worker worker = new Worker (req);
+                       SocketAsyncCall sac = new SocketAsyncCall (worker.ReceiveFrom);
+                       sac.BeginInvoke (null, null);
+                       return req;
+               }
+
+               public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socket_flags,
+                                              AsyncCallback callback, object state)
+               {
+                       if (disposed && closed)
+                               throw new ObjectDisposedException (GetType ().ToString ());
+
+                       if (buffer == null)
+                               throw new ArgumentNullException ("buffer");
+
+                       if (offset < 0)
+                               throw new ArgumentOutOfRangeException ("offset must be >= 0");
+
+                       if (size < 0)
+                               throw new ArgumentOutOfRangeException ("size must be >= 0");
+
+                       if (offset + size > buffer.Length)
+                               throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
+
+                       Interlocked.Increment (ref pendingEnds);
+                       SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
+                       req.Buffer = buffer;
+                       req.Offset = offset;
+                       req.Size = size;
+                       req.SockFlags = socket_flags;
+                       if (supportsAsync && socket_type == SocketType.Stream) {
+                               int error;
+                               req.CreateAsyncDelegate ();
+                               KeepReference (req);
+                               AsyncSendInternal (req, out error);
+                               if (error != 10036) // WSAEINPROGRESS
+                                       throw new SocketException (error);
+                       } else {
+                               Worker worker = new Worker (req);
+                               SocketAsyncCall sac = new SocketAsyncCall (worker.Send);
+                               sac.BeginInvoke (null, null);
+                       }
+                       return req;
+               }
+
+               public IAsyncResult BeginSendTo(byte[] buffer, int offset,
+                                               int size,
+                                               SocketFlags socket_flags,
+                                               EndPoint remote_end,
+                                               AsyncCallback callback,
+                                               object state) {
+                       if (disposed && closed)
+                               throw new ObjectDisposedException (GetType ().ToString ());
+
+                       if (buffer == null)
+                               throw new ArgumentNullException ("buffer");
+
+                       if (offset < 0)
+                               throw new ArgumentOutOfRangeException ("offset must be >= 0");
+
+                       if (size < 0)
+                               throw new ArgumentOutOfRangeException ("size must be >= 0");
+
+                       if (offset + size > buffer.Length)
+                               throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
+
+                       Interlocked.Increment (ref pendingEnds);
+                       SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
+                       req.Buffer = buffer;
+                       req.Offset = offset;
+                       req.Size = size;
+                       req.SockFlags = socket_flags;
+                       req.EndPoint = remote_end;
+                       Worker worker = new Worker(req);
+                       SocketAsyncCall sac = new SocketAsyncCall (worker.SendTo);
+                       sac.BeginInvoke (null, null);
+                       return req;
+               }
+
+               // Creates a new system socket, returning the handle
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private extern static void Bind_internal(IntPtr sock,
+                                                        SocketAddress sa,
+                                                        out int error);
+
+               public void Bind(EndPoint local_end) {
+                       if (disposed && closed)
+                               throw new ObjectDisposedException (GetType ().ToString ());
+
+                       if(local_end==null) {
+                               throw new ArgumentNullException("local_end");
+                       }
+                       
+                       int error;
+                       
+                       Bind_internal(socket, local_end.Serialize(),
+                                     out error);
+
+                       if (error != 0) {
+                               throw new SocketException (error);
+                       }
+               }
+
+               // Closes the socket
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private extern static void Close_internal(IntPtr socket,
+                                                         out int error);
+               
+               public void Close() {
+                       ((IDisposable) this).Dispose ();
+               }
+
+               // Connects to the remote address
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private extern static void Connect_internal(IntPtr sock,
+                                                           SocketAddress sa,
+                                                           out int error);
+
+               public void Connect(EndPoint remote_end) {
+                       if (disposed && closed)
+                               throw new ObjectDisposedException (GetType ().ToString ());
+
+                       if(remote_end==null) {
+                               throw new ArgumentNullException("remote_end");
+                       }
+
+                       int error;
+                       
+                       SocketAddress serial = remote_end.Serialize ();
+                       Connect_internal(socket, serial, out error);
+                       if (!blocking && error == 10036) {
+                               Poll (-1, SelectMode.SelectWrite);
+                               Connect_internal (socket, serial, out error);
+                       }
+
+                       if (error != 0)
+                               throw new SocketException (error);
+                       
+                       connected=true;
+               }
+               
+               public Socket EndAccept(IAsyncResult result) {
+                       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 (!result.IsCompleted)
+                               result.AsyncWaitHandle.WaitOne();
+
+                       Interlocked.Decrement (ref pendingEnds);
+                       CheckIfClose ();
+                       req.CheckIfThrowDelayedException();
+                       return req.Socket;
+               }
+
+               public void EndConnect(IAsyncResult result) {
+                       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 (!result.IsCompleted)
+                               result.AsyncWaitHandle.WaitOne();
+
+                       Interlocked.Decrement (ref pendingEnds);
+                       CheckIfClose ();
+                       req.CheckIfThrowDelayedException();
+               }
+
+               public int EndReceive(IAsyncResult result) {
+                       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");
+
+                       RemoveReference (req);
+                       if (!result.IsCompleted)
+                               result.AsyncWaitHandle.WaitOne();
+
+                       Interlocked.Decrement (ref pendingEnds);
+                       CheckIfClose ();
+                       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 (!result.IsCompleted)
+                               result.AsyncWaitHandle.WaitOne();
+
+                       Interlocked.Decrement (ref pendingEnds);
+                       CheckIfClose ();
+                       req.CheckIfThrowDelayedException();
+                       end_point = req.EndPoint;
+                       return req.Total;
+               }
+
+               public int EndSend(IAsyncResult result) {
+                       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");
+
+                       RemoveReference (req);
+                       if (!result.IsCompleted)
+                               result.AsyncWaitHandle.WaitOne();
+
+                       Interlocked.Decrement (ref pendingEnds);
+                       CheckIfClose ();
+                       req.CheckIfThrowDelayedException();
+                       return req.Total;
+               }
+
+               public int EndSendTo(IAsyncResult result) {
+                       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 (!result.IsCompleted)
+                               result.AsyncWaitHandle.WaitOne();
+
+                       Interlocked.Decrement (ref pendingEnds);
+                       CheckIfClose ();
+                       req.CheckIfThrowDelayedException();
+                       return req.Total;
+               }
+
+               void CheckIfClose ()
+               {
+                       if (Interlocked.CompareExchange (ref closeDelayed, 0, 1) == 1 &&
+                           Interlocked.CompareExchange (ref pendingEnds, 0, 0) == 0) {
+                               closed = true;
+
+                               int error;
+                               
+                               Close_internal(socket, out error);
+
+                               if (error != 0) {
+                                       throw new SocketException (error);
+                               }
+                       }
+               }
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private extern static void GetSocketOption_obj_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, out object obj_val, out int error);
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private extern static void GetSocketOption_arr_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val, out int error);
+
+               public object GetSocketOption(SocketOptionLevel level,
+                                             SocketOptionName name) {
+                       object obj_val;
+                       int error;
+                       
+                       GetSocketOption_obj_internal(socket, level, name,
+                                                    out obj_val, out error);
+
+                       if (error != 0) {
+                               throw new SocketException (error);
+                       }
+                       
+                       if(name==SocketOptionName.Linger) {
+                               return((LingerOption)obj_val);
+                       } else if (name==SocketOptionName.AddMembership ||
+                                  name==SocketOptionName.DropMembership) {
+                               return((MulticastOption)obj_val);
+                       } else {
+                               return((int)obj_val);
+                       }
+               }
+
+               public void GetSocketOption(SocketOptionLevel level,
+                                           SocketOptionName name,
+                                           byte[] opt_value) {
+                       int opt_value_len=opt_value.Length;
+                       int error;
+                       
+                       GetSocketOption_arr_internal(socket, level, name,
+                                                    ref opt_value, out error);
+
+                       if (error != 0) {
+                               throw new SocketException (error);
+                       }
+               }
+
+               public byte[] GetSocketOption(SocketOptionLevel level,
+                                             SocketOptionName name,
+                                             int length) {
+                       byte[] byte_val=new byte[length];
+                       int error;
+                       
+                       GetSocketOption_arr_internal(socket, level, name,
+                                                    ref byte_val, out error);
+
+                       if (error != 0) {
+                               throw new SocketException (error);
+                       }
+
+                       return(byte_val);
+               }
+
+               // 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.
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               extern static int WSAIoctl (IntPtr sock, int ioctl_code,
+                                           byte [] input, byte [] output,
+                                           out int error);
+
+               public int IOControl (int ioctl_code, byte [] in_value, byte [] out_value)
+               {
+                       if (disposed)
+                               throw new ObjectDisposedException (GetType ().ToString ());
+
+                       int error;
+                       int result = WSAIoctl (socket, ioctl_code, in_value,
+                                              out_value, out error);
+
+                       if (error != 0) {
+                               throw new SocketException (error);
+                       }
+                       
+                       if (result == -1)
+                               throw new InvalidOperationException ("Must use Blocking property instead.");
+
+                       return result;
+               }
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private extern static void Listen_internal(IntPtr sock,
+                                                          int backlog,
+                                                          out int error);
+
+               public void Listen(int backlog) {
+                       int error;
+                       
+                       Listen_internal(socket, backlog, out error);
+
+                       if (error != 0) {
+                               throw new SocketException (error);
+                       }
                }
 
-               /// <summary>\r
-               /// Completes an asynchronous Connect() operation\r
-               /// started with a BeginConnect() call\r
-               /// </summary>\r
-               /// <param name="result"></param>
-               public void EndConnect (IAsyncResult result)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Completes an asynchronous Receive() operation\r
-               /// started with a BeginReceive() call\r
-               /// </summary>\r
-               /// <param name="result"></param>\r
-               /// <returns></returns>
-               public int EndReceive (IAsyncResult result)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Completes an asynchronous ReceiveFrom() operation\r
-               /// started with a BeginReceiveFrom() call\r
-               /// </summary>\r
-               /// <param name="result"></param>\r
-               /// <param name="end_point"></param>\r
-               /// <returns></returns>
-               public int EndReceiveFrom (
-                       IAsyncResult result,
-                       ref EndPoint end_point)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Completes an asynchronous Send() operation\r
-               /// started with a BeginSend() call\r
-               /// </summary>\r
-               /// <param name="result"></param>\r
-               /// <returns></returns>
-               public int EndSend (IAsyncResult result)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Completes an asynchronous SendTo() operation\r
-               /// started with a BeginSendTo() call\r
-               /// </summary>\r
-               /// <param name="result"></param>\r
-               /// <returns></returns>
-               public int EndSendTo (IAsyncResult result)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Gets a socket option\r
-               /// </summary>\r
-               /// <param name="level"></param>\r
-               /// <param name="name"></param>\r
-               /// <returns></returns>
-               public object GetSocketOption (
-                       SocketOptionLevel level,
-                       SocketOptionName name)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Gets a socket option\r
-               /// </summary>\r
-               /// <param name="level"></param>\r
-               /// <param name="name"></param>\r
-               /// <param name="opt_value"></param>
-               public void GetSocketOption (
-                       SocketOptionLevel level,
-                       SocketOptionName name,
-                       byte[] opt_value)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Gets a socket option\r
-               /// </summary>\r
-               /// <param name="level"></param>\r
-               /// <param name="name"></param>\r
-               /// <param name="length"></param>\r
-               /// <returns></returns>
-               public byte[] GetSocketOption (
-                       SocketOptionLevel level,
-                       SocketOptionName name,
-                       int length)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Does something to the socket, a la ioctl()\r
-               /// </summary>\r
-               /// <param name="ioctl_code">Code of the operation\r
-               /// to perform on the socket</param>\r
-               /// <param name="in_value">Data to pass to ioctl()</param>\r
-               /// <param name="out_value">Data returned from ioctl()</param>\r
-               /// <returns></returns>
-               public int IOControl (
-                       int ioctl_code,
-                       byte[] in_value,
-                       byte[] out_value)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Tells the socket to start listening\r
-               /// </summary>\r
-               /// <param name="backlog">Connection backlog - the number 
-               /// of pending (not Accept()ed) connections that will be
-               /// allowed before new connections are automatically
-               /// refused</param>
-               public void Listen (int backlog)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Blocks the application until the socket is either\r
-               /// readable, writeable or has an error condition\r
-               /// </summary>\r
-               /// <param name="time_us">How long to wait, in microseconds</param>\r
-               /// <param name="mode">What to wait for (reading, writing, error)</param>\r
-               /// <returns></returns>
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               extern static bool Poll_internal (IntPtr socket, SelectMode mode, int timeout, out int error);
+
                public bool Poll (int time_us, SelectMode mode)
                {
-                       throw new NotImplementedException();
+                       if (mode != SelectMode.SelectRead &&
+                           mode != SelectMode.SelectWrite &&
+                           mode != SelectMode.SelectError)
+                               throw new NotSupportedException ("'mode' parameter is not valid.");
+
+                       int error;
+                       bool result = Poll_internal (socket, mode, time_us, out error);
+                       if (error != 0)
+                               throw new SocketException (error);
+
+                       return result;
                }
                
-               /// <summary>\r
-               /// Receives data from the socket\r
-               /// </summary>\r
-               /// <param name="buf"></param>\r
-               /// <returns></returns>
-               public int Receive (
-                       byte[] buf)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Receives data from the socket\r
-               /// </summary>\r
-               /// <param name="buf"></param>\r
-               /// <param name="flags"></param>\r
-               /// <returns></returns>
-               public int Receive (
-                       byte[] buf,
-                       SocketFlags flags)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Receives data from the socket\r
-               /// </summary>\r
-               /// <param name="buf"></param>\r
-               /// <param name="size"></param>\r
-               /// <param name="flags"></param>\r
-               /// <returns></returns>
-               public int Receive (
-                       byte[] buf,
-                       int size,
-                       SocketFlags flags)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Receives data from the socket\r
-               /// </summary>\r
-               /// <param name="buf"></param>\r
-               /// <param name="offset"></param>\r
-               /// <param name="size"></param>\r
-               /// <param name="flags"></param>\r
-               /// <returns></returns>
-               public int Receive (
-                       byte[] buf,
-                       int offset,
-                       int size,
-                       SocketFlags flags)
-               {
-                       throw new NotImplementedException();
+               public int Receive (byte [] buf)
+               {
+                       if (buf == null)
+                               throw new ArgumentNullException ("buf");
+
+                       return Receive_nochecks (buf, 0, buf.Length, SocketFlags.None);
+               }
+
+               public int Receive (byte [] buf, SocketFlags flags)
+               {
+                       if (buf == null)
+                               throw new ArgumentNullException ("buf");
+
+                       return Receive_nochecks (buf, 0, buf.Length, flags);
+               }
+
+               public int Receive (byte [] buf, int size, SocketFlags flags)
+               {
+                       if (buf == null)
+                               throw new ArgumentNullException ("buf");
+
+                       if (size < 0 || size > buf.Length)
+                               throw new ArgumentOutOfRangeException ("size");
+
+                       return Receive_nochecks (buf, 0, size, flags);
+               }
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private extern static int Receive_internal(IntPtr sock,
+                                                          byte[] buffer,
+                                                          int offset,
+                                                          int count,
+                                                          SocketFlags flags,
+                                                          out int error);
+
+               public int Receive (byte [] buf, int offset, int size, SocketFlags flags)
+               {
+                       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);
+               }
+
+               int Receive_nochecks (byte [] buf, int offset, int size, SocketFlags flags)
+               {
+                       int ret, error;
+                       
+                       ret = Receive_internal (socket, buf, offset, size, flags, out error);
+
+                       if (error != 0) {
+                               connected = false;
+                               throw new SocketException (error);
+                       }
+                       
+                       connected = true;
+
+                       return ret;
                }
                
-               /// <summary>\r
-               /// Receives data from a specific point, \r
-               /// through the socket\r
-               /// </summary>\r
-               /// <param name="buf"></param>\r
-               /// <param name="remote_end_point"></param>\r
-               /// <returns></returns>
-               public int ReceiveFrom (
-                       byte[] buf,
-                       ref EndPoint remote_end_point)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Receives data from a specific point, \r
-               /// through the socket\r
-               /// </summary>\r
-               /// <param name="buf"></param>\r
-               /// <param name="flags"></param>\r
-               /// <param name="remote_end_point"></param>\r
-               /// <returns></returns>
-               public int ReceiveFrom (
-                       byte[] buf,
-                       SocketFlags flags,
-                       ref EndPoint remote_end_point)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Receives data from a specific point, \r
-               /// through the socket\r
-               /// </summary>\r
-               /// <param name="buf"></param>\r
-               /// <param name="size"></param>\r
-               /// <param name="flags"></param>\r
-               /// <param name="remote_end_point"></param>\r
-               /// <returns></returns>
-               public int ReceiveFrom (
-                       byte[] buf,
-                       int size,
-                       SocketFlags flags,
-                       ref EndPoint remote_end_point)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Receives data from a specific point, \r
-               /// through the socket\r
-               /// </summary>\r
-               /// <param name="buf"></param>\r
-               /// <param name="offset"></param>\r
-               /// <param name="size"></param>\r
-               /// <param name="flags"></param>\r
-               /// <param name="remote_end_point"></param>\r
-               /// <returns></returns>
-               public int ReceiveFrom (
-                       byte[] buf,
-                       int offset,
-                       int size,
-                       SocketFlags flags,
-                       ref EndPoint remote_end_point)
-               {
-                       throw new NotImplementedException();
-               }
-
-
-               /// <summary>\r
-               /// Sends data through the socket\r
-               /// </summary>\r
-               /// <param name="buffer"></param>\r
-               /// <returns></returns>
-               public int Send (
-                       byte[] buffer)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Sends data through the socket\r
-               /// </summary>\r
-               /// <param name="buffer"></param>\r
-               /// <param name="flags"></param>\r
-               /// <returns></returns>
-               public int Send (
-                       byte[] buffer,
-                       SocketFlags flags)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Sends data through the socket\r
-               /// </summary>\r
-               /// <param name="buffer"></param>\r
-               /// <param name="size"></param>\r
-               /// <param name="flags"></param>\r
-               /// <returns></returns>
-               public int Send (
-                       byte[] buffer,
-                       int size,
-                       SocketFlags flags)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Sends data through the socket\r
-               /// </summary>\r
-               /// <param name="buffer"></param>\r
-               /// <param name="offset"></param>\r
-               /// <param name="size"></param>\r
-               /// <param name="flags"></param>\r
-               /// <returns></returns>
-               public int Send (
-                       byte[] buffer,
-                       int offset,
-                       int size,
-                       SocketFlags flags)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Sends data to a specific point,\r
-               /// through the socket\r
-               /// </summary>\r
-               /// <param name="buffer"></param>\r
-               /// <param name="remote_end_point"></param>\r
-               /// <returns></returns>
-               public int SendTo (
-                       byte[] buffer,
-                       EndPoint remote_end_point)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Sends data to a specific point,\r
-               /// through the socket\r
-               /// </summary>\r
-               /// <param name="buffer"></param>\r
-               /// <param name="flags"></param>\r
-               /// <param name="remote_end_point"></param>\r
-               /// <returns></returns>
-               public int SendTo (
-                       byte[] buffer,
-                       SocketFlags flags,
-                       EndPoint remote_end_point)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Sends data to a specific point,\r
-               /// through the socket\r
-               /// </summary>\r
-               /// <param name="buffer"></param>\r
-               /// <param name="size"></param>\r
-               /// <param name="flags"></param>\r
-               /// <param name="remote_end_point"></param>\r
-               /// <returns></returns>
-               public int SendTo (
-                       byte[] buffer,
-                       int size,
-                       SocketFlags flags,
-                       EndPoint remote_end_point)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Sends data to a specific point,\r
-               /// through the socket\r
-               /// </summary>\r
-               /// <param name="buffer"></param>\r
-               /// <param name="offset"></param>\r
-               /// <param name="size"></param>\r
-               /// <param name="flags"></param>\r
-               /// <param name="remote_end_point"></param>\r
-               /// <returns></returns>
-               public int SendTo (
-                       byte[] buffer,
-                       int offset,
-                       int size,
-                       SocketFlags flags,
-                       EndPoint remote_end_point)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Sets a socket option (like setsockopt())\r
-               /// </summary>\r
-               /// <param name="level"></param>\r
-               /// <param name="name"></param>\r
-               /// <param name="opt_value"></param>
-               public void SetSocketOption (
-                       SocketOptionLevel level,
-                       SocketOptionName name,
-                       byte[] opt_value)
-               {
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>\r
-               /// Sets a socket option (like setsockopt())\r
-               /// </summary>\r
-               /// <param name="level"></param>\r
-               /// <param name="name"></param>\r
-               /// <param name="opt_value"></param>
-               public void SetSocketOption (
-                       SocketOptionLevel level,
-                       SocketOptionName name,
-                       int opt_value)
-               {
-                       throw new NotImplementedException();
+               public int ReceiveFrom (byte [] buf, ref EndPoint remote_end)
+               {
+                       if (buf == null)
+                               throw new ArgumentNullException ("buf");
+
+                       if (remote_end == null)
+                               throw new ArgumentNullException ("remote_end");
+
+                       return ReceiveFrom_nochecks (buf, 0, buf.Length, SocketFlags.None, ref remote_end);
                }
 
-               /// <summary>\r
-               /// Sets a socket option (like setsockopt())\r
-               /// </summary>\r
-               /// <param name="level"></param>\r
-               /// <param name="name"></param>\r
-               /// <param name="opt_value"></param>
-               public void SetSocketOption (
-                       SocketOptionLevel level,
-                       SocketOptionName name,
-                       object opt_value)
+               public int ReceiveFrom (byte [] buf, SocketFlags flags, ref EndPoint remote_end)
                {
-                       throw new NotImplementedException();
+                       if (buf == null)
+                               throw new ArgumentNullException ("buf");
+
+                       if (remote_end == null)
+                               throw new ArgumentNullException ("remote_end");
+
+
+                       return ReceiveFrom_nochecks (buf, 0, buf.Length, flags, ref remote_end);
                }
 
-               /// <summary>\r
-               /// Stops anyone from being able to read or write to the socket\r
-               /// </summary>\r
-               /// <param name="how">What people aren't allowed to do any
-               /// more (you can disable just reading or just writing, or both)</param>
-               public void Shutdown (SocketShutdown how)
-               {
-                       throw new NotImplementedException();
+               public int ReceiveFrom (byte [] buf, int size, SocketFlags flags,
+                                       ref EndPoint remote_end)
+               {
+                       if (buf == null)
+                               throw new ArgumentNullException ("buf");
+
+                       if (remote_end == null)
+                               throw new ArgumentNullException ("remote_end");
+
+                       if (size < 0 || size > buf.Length)
+                               throw new ArgumentOutOfRangeException ("size");
+
+                       return ReceiveFrom_nochecks (buf, 0, size, flags, ref remote_end);
                }
 
-               /// <summary>\r
-               /// A stringified representation of the socket\r
-               /// </summary>\r
-               /// <returns></returns>
-               public override string ToString ()
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private extern static int RecvFrom_internal(IntPtr sock,
+                                                           byte[] buffer,
+                                                           int offset,
+                                                           int count,
+                                                           SocketFlags flags,
+                                                           ref SocketAddress sockaddr,
+                                                           out int error);
+
+               public int ReceiveFrom (byte [] buf, int offset, int size, SocketFlags flags,
+                                       ref EndPoint remote_end)
                {
-                       throw new NotImplementedException();
-                       //return "foo";
+                       if (buf == null)
+                               throw new ArgumentNullException ("buf");
+
+                       if (remote_end == null)
+                               throw new ArgumentNullException ("remote_end");
+
+                       if (offset < 0 || offset > buf.Length)
+                               throw new ArgumentOutOfRangeException ("offset");
+
+                       if (size < 0 || offset + size > buf.Length)
+                               throw new ArgumentOutOfRangeException ("size");
+
+                       return ReceiveFrom_nochecks (buf, offset, size, flags, ref remote_end);
                }
 
+               int ReceiveFrom_nochecks (byte [] buf, int offset, int size, SocketFlags flags,
+                                         ref EndPoint remote_end)
+               {
+                       SocketAddress sockaddr = remote_end.Serialize();
+                       int cnt, error;
+
+                       cnt = RecvFrom_internal (socket, buf, offset, size, flags, ref sockaddr, out error);
+
+                       if (error != 0) {
+                               connected = false;
+                               throw new SocketException (error);
+                       }
 
+                       connected = true;
+                       
+                       // Stupidly, EndPoint.Create() is an
+                       // instance method
+                       remote_end = remote_end.Create (sockaddr);
 
-               // protected methods:
+                       return cnt;
+               }
 
-               /// <summary>\r
-               /// Disposes of all unmanaged resources, and\r
-               /// managed resources too if requested\r
-               /// </summary>\r
-               /// <param name="disposing">Set this to true
-               /// to dispose of managed resources</param>
-               protected virtual void Dispose (bool disposing)
+               public int Send (byte [] buf)
                {
-                       // file descriptor / socket
-                       // other things to dispose of?
+                       if (buf == null)
+                               throw new ArgumentNullException ("buf");
 
-                       // managed things?
+                       return Send_nochecks (buf, 0, buf.Length, SocketFlags.None);
+               }
 
-                       throw new NotImplementedException();
+               public int Send (byte [] buf, SocketFlags flags)
+               {
+                       if (buf == null)
+                               throw new ArgumentNullException ("buf");
+
+                       return Send_nochecks (buf, 0, buf.Length, flags);
                }
 
-               /// <summary>\r
-               /// Disposes of everything (managed and\r
-               /// unmanaged resources)\r
-               /// </summary>
-               public void Dispose ()
+               public int Send (byte [] buf, int size, SocketFlags flags)
                {
-                       Dispose(true);
+                       if (buf == null)
+                               throw new ArgumentNullException ("buf");
+
+                       if (size < 0 || size > buf.Length)
+                               throw new ArgumentOutOfRangeException ("size");
+
+                       return Send_nochecks (buf, 0, size, flags);
+               }
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private extern static int Send_internal(IntPtr sock,
+                                                       byte[] buf, int offset,
+                                                       int count,
+                                                       SocketFlags flags,
+                                                       out int error);
+
+               public int Send (byte [] buf, int offset, int size, SocketFlags flags)
+               {
+                       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");
+
+                       return Send_nochecks (buf, offset, size, flags);
+               }
+
+               int Send_nochecks (byte [] buf, int offset, int size, SocketFlags flags)
+               {
+                       if (size == 0)
+                               return 0;
+
+                       int ret, error;
+
+                       ret = Send_internal (socket, buf, offset, size, flags, out error);
+
+                       if (error != 0) {
+                               connected = false;
+                               throw new SocketException (error);
+                       }
+
+                       connected = true;
+
+                       return ret;
+               }
+
+               public int SendTo (byte [] buffer, EndPoint remote_end)
+               {
+                       if (buffer == null)
+                               throw new ArgumentNullException ("buffer");
+
+                       if (remote_end == null)
+                               throw new ArgumentNullException ("remote_end");
+
+                       return SendTo_nochecks (buffer, 0, buffer.Length, SocketFlags.None, remote_end);
                }
 
-               /// <summary>\r
-               /// Destructor - disposes of unmanaged resources\r
-               /// </summary>
-               ~Socket ()
+               public int SendTo (byte [] buffer, SocketFlags flags, EndPoint remote_end)
                {
+                       if (buffer == null)
+                               throw new ArgumentNullException ("buffer");
+
+                       if (remote_end == null)
+                               throw new ArgumentNullException ("remote_end");
+                               
+                       return SendTo_nochecks (buffer, 0, buffer.Length, flags, remote_end);
+               }
+
+               public int SendTo (byte [] buffer, int size, SocketFlags flags, EndPoint remote_end)
+               {
+                       if (buffer == null)
+                               throw new ArgumentNullException ("buffer");
+
+                       if (remote_end == null)
+                               throw new ArgumentNullException ("remote_end");
+
+                       if (size < 0 || size > buffer.Length)
+                               throw new ArgumentOutOfRangeException ("size");
+
+                       return SendTo_nochecks (buffer, 0, size, flags, remote_end);
+               }
+
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private extern static int SendTo_internal(IntPtr sock,
+                                                         byte[] buffer,
+                                                         int offset,
+                                                         int count,
+                                                         SocketFlags flags,
+                                                         SocketAddress sa,
+                                                         out int error);
+
+               public int SendTo (byte [] buffer, int offset, int size, SocketFlags flags,
+                                  EndPoint remote_end)
+               {
+                       if (buffer == null)
+                               throw new ArgumentNullException ("buffer");
+
+                       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");
+
+                       return SendTo_nochecks (buffer, offset, size, flags, remote_end);
+               }
+
+               int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags,
+                                  EndPoint remote_end)
+               {
+                       SocketAddress sockaddr = remote_end.Serialize ();
+
+                       int ret, error;
+
+                       ret = SendTo_internal (socket, buffer, offset, size, flags, sockaddr, out error);
+
+                       if (error != 0) {
+                               connected = false;
+                               throw new SocketException (error);
+                       }
+
+                       connected = true;
+
+                       return ret;
+               }
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private extern static void SetSocketOption_internal (IntPtr socket, SocketOptionLevel level,
+                                                                    SocketOptionName name, object obj_val,
+                                                                    byte [] byte_val, int int_val,
+                                                                    out int error);
+
+               public void SetSocketOption(SocketOptionLevel level,
+                                           SocketOptionName name,
+                                           byte[] opt_value) {
+                       int error;
+                       
+                       SetSocketOption_internal(socket, level, name, null,
+                                                opt_value, 0, out error);
+
+                       if (error != 0) {
+                               throw new SocketException (error);
+                       }
+               }
+
+               public void SetSocketOption(SocketOptionLevel level,
+                                           SocketOptionName name,
+                                           int opt_value) {
+                       int error;
+                       
+                       SetSocketOption_internal(socket, level, name, null,
+                                                null, opt_value, out error);
+
+                       if (error != 0) {
+                               throw new SocketException (error);
+                       }
+               }
+
+               public void SetSocketOption(SocketOptionLevel level,
+                                           SocketOptionName name,
+                                           object opt_value) {
+                       if(opt_value==null) {
+                               throw new ArgumentNullException();
+                       }
+                       
+                       int error;
+                       
+                       /* Passing a bool as the third parameter to
+                        * SetSocketOption causes this overload to be
+                        * used when in fact we want to pass the value
+                        * to the runtime as an int.
+                        */
+                       if (opt_value is System.Boolean) {
+                               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 {
+                               SetSocketOption_internal (socket, level, name, opt_value, null, 0, out error);
+                       }
+
+                       if (error != 0) {
+                               throw new SocketException (error);
+                       }
+               }
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private extern static void Shutdown_internal(IntPtr socket, SocketShutdown how, out int error);
+               
+               public void Shutdown(SocketShutdown how) {
+                       int error;
+                       
+                       Shutdown_internal(socket, how, out error);
+
+                       if (error != 0) {
+                               throw new SocketException (error);
+                       }
+               }
+
+               public override int GetHashCode ()
+               { 
+                       return (int) socket; 
+               }
+
+               private bool disposed;
+               
+               protected virtual void Dispose(bool explicitDisposing) {
+                       if (!disposed) {
+                               int error;
+                               
+                               disposed = true;
+                               connected = false;
+                               if (!explicitDisposing) {
+                                       closed = true;
+                                       Close_internal (socket, out error);
+
+                                       if (error != 0) {
+                                               throw new SocketException (error);
+                                       }
+                                       
+                                       return;
+                               }
+                       
+                               if (Interlocked.CompareExchange (ref pendingEnds, 0, 0) == 0) {
+                                       closed = true;
+                                       Close_internal (socket, out error);
+
+                                       if (error != 0) {
+                                               throw new SocketException (error);
+                                       }
+                               } else {
+                                       Interlocked.CompareExchange (ref closeDelayed, 1, 0);
+                               }
+                       }
+               }
+
+               void IDisposable.Dispose ()
+               {
+                       Dispose (true);
+                       GC.SuppressFinalize (this);
+               }
+               
+               ~Socket () {
                        Dispose(false);
-                       throw new NotImplementedException();
                }
 
-       }
+               static Hashtable asyncObjects;
+
+               static void KeepReference (object o)
+               {
+                       lock (typeof (Socket)) {
+                               if (asyncObjects == null)
+                                       asyncObjects = new Hashtable ();
+
+                               asyncObjects [o] = o;
+                       }
+               }
 
+               static void RemoveReference (object o)
+               {
+                       lock (typeof (Socket)) {
+                               if (asyncObjects == null)
+                                       return;
+
+                               asyncObjects.Remove (o);
+                       }
+               }
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               extern static bool GetSupportsAsync ();
+
+               static bool FakeGetSupportsAsync ()
+               {
+                       if (Environment.GetEnvironmentVariable ("MONO_ENABLE_SOCKET_AIO") != null)
+                               return GetSupportsAsync ();
+                       
+                       return false;
+               }
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               extern static void AsyncReceiveInternal (SocketAsyncResult ares, out int error);
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               extern static void AsyncSendInternal (SocketAsyncResult ares, out int error);
+       }
 }
+