// System.Net.Sockets.Socket.cs // // Authors: // Phillip Pearson (pp@myelin.co.nz) // Dick Porter // // Copyright (C) 2001, 2002 Phillip Pearson and Ximian, Inc. // http://www.myelin.co.nz // using System; using System.Net; using System.Collections; using System.Runtime.CompilerServices; using System.Threading; using System.Reflection; using System.IO; namespace System.Net.Sockets { public class Socket : IDisposable { private sealed class SocketAsyncResult: IAsyncResult { private object state; private WaitHandle waithandle; private bool completed_sync, completed; private Worker worker; private Exception delayedException = null; public SocketAsyncResult(object state) { this.state=state; completed_sync=completed=false; } public void SetDelayedException (Exception e) { delayedException = e; } public void CheckIfThrowDelayedException () { if (delayedException != null) throw delayedException; } 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 Worker Worker { get { return(worker); } set { worker=value; } } } private sealed class Worker { private AsyncCallback callback; private SocketAsyncResult result; private Socket socket; // Parameters private EndPoint endpoint; // Connect,ReceiveFrom,SendTo private byte[] buffer; // Receive,ReceiveFrom,Send,SendTo private int offset; // Receive,ReceiveFrom,Send,SendTo private int size; // Receive,ReceiveFrom,Send,SendTo private SocketFlags sockflags; // Receive,ReceiveFrom,Send,SendTo // Return values private Socket acc_socket; private int total; // For Accept public Worker(Socket req_sock, AsyncCallback req_callback, SocketAsyncResult req_result) : this(req_sock, null, 0, 0, SocketFlags.None, null, req_callback, req_result) {} // For Connect public Worker(Socket req_sock, EndPoint req_endpoint, AsyncCallback req_callback, SocketAsyncResult req_result) : this(req_sock, null, 0, 0, SocketFlags.None, req_endpoint, req_callback, req_result) {} // For Receive and Send public Worker(Socket req_sock, byte[] req_buffer, int req_offset, int req_size, SocketFlags req_sockflags, AsyncCallback req_callback, SocketAsyncResult req_result) : this(req_sock, req_buffer, req_offset, req_size, req_sockflags, null, req_callback, req_result) {} // For ReceiveFrom and SendTo public Worker(Socket req_sock, byte[] req_buffer, int req_offset, int req_size, SocketFlags req_sockflags, EndPoint req_endpoint, AsyncCallback req_callback, SocketAsyncResult req_result) { socket=req_sock; buffer=req_buffer; offset=req_offset; size=req_size; sockflags=req_sockflags; endpoint=req_endpoint; callback=req_callback; result=req_result; } private void End() { result.IsCompleted=true; if (callback != null) callback(result); } public void Accept() { lock(result) { try { acc_socket=socket.Accept(); } catch (Exception e) { result.SetDelayedException(e); } End(); } } public void Connect() { lock(result) { if (socket.Blocking) { try { socket.Connect(endpoint); } catch (Exception e) { result.SetDelayedException(e); } End (); return; } Exception rethrow = null; try { socket.Connect (endpoint); } catch (SocketException e) { //WSAEINPROGRESS if (e.NativeErrorCode != 10036) { result.SetDelayedException(e); End (); return; } socket.Poll (-1, SelectMode.SelectWrite); try { socket.Connect (endpoint); } catch (SocketException e2) { rethrow = e2; } } catch (Exception e3) { rethrow = e3; } if (rethrow != null) result.SetDelayedException(rethrow); End (); } } public void Receive() { lock(result) { if (socket.Blocking) { try { total=socket.Receive(buffer, offset, size, sockflags); } catch (Exception e) { result.SetDelayedException(e); } End(); return; } Exception rethrow = null; try { total = socket.Receive (buffer, offset, size, sockflags); } catch (SocketException e) { //WSAEWOULDBLOCK if (e.NativeErrorCode != 10035) { result.SetDelayedException(e); End (); return; } socket.Poll (-1, SelectMode.SelectRead); try { total = socket.Receive (buffer, offset, size, sockflags); } catch (SocketException e2) { rethrow = e2; } } catch (Exception e3) { rethrow = e3; } if (rethrow != null) result.SetDelayedException(rethrow); End (); } } public void ReceiveFrom() { lock(result) { if (socket.Blocking) { try { total=socket.ReceiveFrom(buffer, offset, size, sockflags, ref endpoint); } catch (Exception e) { result.SetDelayedException(e); } End(); return; } Exception rethrow = null; try { total = socket.ReceiveFrom (buffer, offset, size, sockflags, ref endpoint); } catch (SocketException e) { //WSAEWOULDBLOCK if (e.NativeErrorCode != 10035) { result.SetDelayedException(e); End (); return; } socket.Poll (-1, SelectMode.SelectRead); try { total = socket.ReceiveFrom (buffer, offset, size, sockflags, ref endpoint); } catch (SocketException e2) { rethrow = e2; } } catch (Exception e3) { rethrow = e3; } if (rethrow != null) result.SetDelayedException(rethrow); End (); } } public void Send() { lock(result) { if (socket.Blocking) { try { total=socket.Send(buffer, offset, size, sockflags); } catch (Exception e) { result.SetDelayedException(e); } End(); return; } Exception rethrow = null; try { total = socket.Send (buffer, offset, size, sockflags); } catch (SocketException e) { //WSAEWOULDBLOCK if (e.NativeErrorCode != 10035) { result.SetDelayedException(e); End (); return; } socket.Poll (-1, SelectMode.SelectWrite); try { total = socket.Send (buffer, offset, size, sockflags); } catch (SocketException e2) { rethrow = e2; } } catch (Exception e3) { rethrow = e3; } if (rethrow != null) result.SetDelayedException(rethrow); End (); } } public void SendTo() { lock(result) { if (socket.Blocking) { try { total=socket.SendTo(buffer, offset, size, sockflags, endpoint); } catch (Exception e) { result.SetDelayedException(e); } End(); return; } Exception rethrow = null; try { total = socket.SendTo (buffer, offset, size, sockflags, endpoint); } catch (SocketException e) { //WSAEWOULDBLOCK if (e.NativeErrorCode != 10035) { result.SetDelayedException(e); End (); return; } socket.Poll (-1, SelectMode.SelectWrite); try { total = socket.SendTo (buffer, offset, size, sockflags, endpoint); } catch (SocketException e2) { rethrow = e2; } } catch (Exception e3) { rethrow = e3; } if (rethrow != null) result.SetDelayedException(rethrow); End (); } } public EndPoint EndPoint { get { return(endpoint); } } public Socket Socket { get { return(acc_socket); } } public int Total { get { return(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; private bool blocking=true; private int pendingEnds; private int closeDelayed; 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); 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++; } } Select_internal(ref read_arr, ref write_arr, ref err_arr, time_us); if(read_list!=null) { read_list.Clear(); for(i=0; i= 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(state); Worker worker=new Worker(this, buffer, offset, size, socket_flags, callback, req); req.Worker=worker; 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(state); Worker worker=new Worker(this, buffer, offset, size, socket_flags, remote_end, callback, req); req.Worker=worker; 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(state); Worker worker=new Worker(this, buffer, offset, size, socket_flags, callback, req); req.Worker=worker; 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(state); Worker worker=new Worker(this, buffer, offset, size, socket_flags, remote_end, callback, req); req.Worker=worker; 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); public void Bind(EndPoint local_end) { if (disposed && closed) throw new ObjectDisposedException (GetType ().ToString ()); if(local_end==null) { throw new ArgumentNullException("local_end"); } Bind_internal(socket, local_end.Serialize()); } // Closes the socket [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern static void Close_internal(IntPtr socket); public void Close() { ((IDisposable) this).Dispose (); } // Connects to the remote address [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern static void Connect_internal(IntPtr sock, SocketAddress sa); public void Connect(EndPoint remote_end) { if (disposed && closed) throw new ObjectDisposedException (GetType ().ToString ()); if(remote_end==null) { throw new ArgumentNullException("remote_end"); } Connect_internal(socket, remote_end.Serialize()); 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"); if (!result.IsCompleted) result.AsyncWaitHandle.WaitOne(); Interlocked.Decrement (ref pendingEnds); CheckIfClose (); req.CheckIfThrowDelayedException(); return(req.Worker.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"); 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"); if (!result.IsCompleted) result.AsyncWaitHandle.WaitOne(); Interlocked.Decrement (ref pendingEnds); CheckIfClose (); req.CheckIfThrowDelayedException(); return(req.Worker.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"); if (!result.IsCompleted) result.AsyncWaitHandle.WaitOne(); Interlocked.Decrement (ref pendingEnds); CheckIfClose (); req.CheckIfThrowDelayedException(); end_point=req.Worker.EndPoint; return(req.Worker.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"); if (!result.IsCompleted) result.AsyncWaitHandle.WaitOne(); Interlocked.Decrement (ref pendingEnds); CheckIfClose (); req.CheckIfThrowDelayedException(); return(req.Worker.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"); if (!result.IsCompleted) result.AsyncWaitHandle.WaitOne(); Interlocked.Decrement (ref pendingEnds); CheckIfClose (); req.CheckIfThrowDelayedException(); return(req.Worker.Total); } void CheckIfClose () { if (Interlocked.CompareExchange (ref closeDelayed, 0, 1) == 1 && Interlocked.CompareExchange (ref pendingEnds, 0, 0) == 0) { closed = true; Close_internal(socket); } } [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern static void GetSocketOption_obj_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, out object obj_val); [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern static void GetSocketOption_arr_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val); public object GetSocketOption(SocketOptionLevel level, SocketOptionName name) { object obj_val; GetSocketOption_obj_internal(socket, level, name, out obj_val); 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; GetSocketOption_arr_internal(socket, level, name, ref opt_value); } public byte[] GetSocketOption(SocketOptionLevel level, SocketOptionName name, int length) { byte[] byte_val=new byte[length]; GetSocketOption_arr_internal(socket, level, name, ref byte_val); 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); public int IOControl (int ioctl_code, byte [] in_value, byte [] out_value) { if (disposed) throw new ObjectDisposedException (GetType ().ToString ()); int result = WSAIoctl (socket, ioctl_code, in_value, out_value); 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); public void Listen(int backlog) { Listen_internal(socket, backlog); } /* The docs for Poll() are a bit lightweight too, but * it seems to be just a simple wrapper around Select. */ public bool Poll(int time_us, SelectMode mode) { Socket [] socketlist = new Socket []{this}; Socket [] n = null; switch(mode) { case SelectMode.SelectError: Select_internal (ref n, ref n, ref socketlist, time_us); break; case SelectMode.SelectRead: Select_internal (ref socketlist, ref n, ref n, time_us); break; case SelectMode.SelectWrite: Select_internal (ref n, ref socketlist, ref n, time_us); break; default: throw new NotSupportedException(); } return (socketlist.Length == 1); } public int Receive(byte[] buf) { return(Receive(buf, 0, buf.Length, SocketFlags.None)); } public int Receive(byte[] buf, SocketFlags flags) { return(Receive(buf, 0, buf.Length, flags)); } public int Receive(byte[] buf, int size, SocketFlags flags) { return(Receive(buf, 0, size, flags)); } [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern static int Receive_internal(IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags); public int Receive(byte[] buf, int offset, int size, SocketFlags flags) { if(buf==null) { throw new ArgumentNullException("buffer is null"); } if(offset<0 || offset > buf.Length) { throw new ArgumentOutOfRangeException("offset exceeds the size of buffer"); } if(size<0 || offset+size > buf.Length) { throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer"); } int ret; try { ret=Receive_internal(socket, buf, offset, size, flags); } catch(SocketException) { connected=false; throw; } connected=true; return(ret); } public int ReceiveFrom(byte[] buf, ref EndPoint remote_end) { return(ReceiveFrom(buf, 0, buf.Length, SocketFlags.None, ref remote_end)); } public int ReceiveFrom(byte[] buf, SocketFlags flags, ref EndPoint remote_end) { return(ReceiveFrom(buf, 0, buf.Length, flags, ref remote_end)); } public int ReceiveFrom(byte[] buf, int size, SocketFlags flags, ref EndPoint remote_end) { return(ReceiveFrom(buf, 0, size, flags, ref remote_end)); } [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern static int RecvFrom_internal(IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags, ref SocketAddress sockaddr); public int ReceiveFrom(byte[] buf, int offset, int size, SocketFlags flags, ref EndPoint remote_end) { if(buf==null) { throw new ArgumentNullException("buffer is null"); } if(remote_end==null) { throw new ArgumentNullException("remote endpoint is null"); } if(offset<0 || offset>buf.Length) { throw new ArgumentOutOfRangeException("offset exceeds the size of buffer"); } if(size<0 || offset+size>buf.Length) { throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer"); } SocketAddress sockaddr=remote_end.Serialize(); int count; try { count=RecvFrom_internal(socket, buf, offset, size, flags, ref sockaddr); } catch(SocketException) { connected=false; throw; } connected=true; // Stupidly, EndPoint.Create() is an // instance method remote_end=remote_end.Create(sockaddr); return(count); } public int Send(byte[] buf) { return(Send(buf, 0, buf.Length, SocketFlags.None)); } public int Send(byte[] buf, SocketFlags flags) { return(Send(buf, 0, buf.Length, flags)); } public int Send(byte[] buf, int size, SocketFlags flags) { return(Send(buf, 0, size, flags)); } [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern static int Send_internal(IntPtr sock, byte[] buf, int offset, int count, SocketFlags flags); 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"); if (size == 0) return 0; int ret; try { ret = Send_internal (socket, buf, offset, size, flags); } catch (SocketException) { connected = false; throw; } connected = true; return ret; } public int SendTo(byte[] buffer, EndPoint remote_end) { return(SendTo(buffer, 0, buffer.Length, SocketFlags.None, remote_end)); } public int SendTo(byte[] buffer, SocketFlags flags, EndPoint remote_end) { return(SendTo(buffer, 0, buffer.Length, flags, remote_end)); } public int SendTo(byte[] buffer, int size, SocketFlags flags, EndPoint remote_end) { return(SendTo(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); public int SendTo(byte[] buffer, int offset, int size, SocketFlags flags, EndPoint remote_end) { if(buffer==null) { throw new ArgumentNullException("buffer is null"); } if(remote_end==null) { throw new ArgumentNullException("remote endpoint is null"); } if(offset<0 || offset>buffer.Length) { throw new ArgumentOutOfRangeException("offset exceeds the size of buffer"); } if(size<0 || offset+size>buffer.Length) { throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer"); } SocketAddress sockaddr=remote_end.Serialize(); int ret; try { ret=SendTo_internal(socket, buffer, offset, size, flags, sockaddr); } catch(SocketException) { connected=false; throw; } 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); public void SetSocketOption(SocketOptionLevel level, SocketOptionName name, byte[] opt_value) { SetSocketOption_internal(socket, level, name, null, opt_value, 0); } public void SetSocketOption(SocketOptionLevel level, SocketOptionName name, int opt_value) { SetSocketOption_internal(socket, level, name, null, null, opt_value); } public void SetSocketOption(SocketOptionLevel level, SocketOptionName name, object opt_value) { if(opt_value==null) { throw new ArgumentNullException(); } /* 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; /* Stupid casting rules :-( */ if(bool_val==true) { SetSocketOption_internal(socket, level, name, null, null, 1); } else { SetSocketOption_internal(socket, level, name, null, null, 0); } } else { SetSocketOption_internal(socket, level, name, opt_value, null, 0); } } [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern static void Shutdown_internal(IntPtr socket, SocketShutdown how); public void Shutdown(SocketShutdown how) { Shutdown_internal(socket, how); } public override int GetHashCode () { return (int) socket; } private bool disposed; protected virtual void Dispose(bool explicitDisposing) { if (!disposed) { disposed = true; connected = false; if (!explicitDisposing) { closed = true; Close_internal (socket); return; } if (Interlocked.CompareExchange (ref pendingEnds, 0, 0) == 0) { closed = true; Close_internal (socket); } else { Interlocked.CompareExchange (ref closeDelayed, 1, 0); } } } void IDisposable.Dispose () { Dispose (true); GC.SuppressFinalize (this); } ~Socket () { Dispose(false); } } }