1 // System.Net.Sockets.Socket.cs
4 // Phillip Pearson (pp@myelin.co.nz)
5 // Dick Porter <dick@ximian.com>
6 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
8 // Copyright (C) 2001, 2002 Phillip Pearson and Ximian, Inc.
9 // http://www.myelin.co.nz
10 // (c) 2004 Novell, Inc. (http://www.novell.com)
15 using System.Collections;
16 using System.Runtime.CompilerServices;
17 using System.Runtime.InteropServices;
18 using System.Threading;
19 using System.Reflection;
22 namespace System.Net.Sockets
24 public class Socket : IDisposable
26 [StructLayout (LayoutKind.Sequential)]
27 private sealed class SocketAsyncResult: IAsyncResult
29 /* Same structure in the runtime */
33 AsyncCallback callback;
34 WaitHandle waithandle;
36 Exception delayedException;
38 public EndPoint EndPoint; // Connect,ReceiveFrom,SendTo
39 public byte [] Buffer; // Receive,ReceiveFrom,Send,SendTo
40 public int Offset; // Receive,ReceiveFrom,Send,SendTo
41 public int Size; // Receive,ReceiveFrom,Send,SendTo
42 public SocketFlags SockFlags; // Receive,ReceiveFrom,Send,SendTo
50 AsyncCallback real_callback;
53 public SocketAsyncResult (Socket sock, object state, AsyncCallback callback)
56 this.handle = sock.socket;
58 this.real_callback = callback;
59 SockFlags = SocketFlags.None;
62 public void CreateAsyncDelegate ()
64 if (real_callback != null)
65 this.callback = new AsyncCallback (FakeCB);
68 static void FakeCB (IAsyncResult result)
70 SocketAsyncResult ares = (SocketAsyncResult) result;
71 ares.real_callback.BeginInvoke (ares, null, null);
74 public void CheckIfThrowDelayedException ()
76 if (delayedException != null)
77 throw delayedException;
80 throw new SocketException (error);
83 public void Complete ()
86 if (real_callback != null)
90 public void Complete (int total)
96 public void Complete (Exception e)
102 public void Complete (Socket s)
108 public object AsyncState {
114 public WaitHandle AsyncWaitHandle {
117 if (waithandle == null)
118 waithandle = new ManualResetEvent (completed);
128 public bool CompletedSynchronously {
130 return(completed_sync);
134 public bool IsCompleted {
141 if (waithandle != null && value) {
142 ((ManualResetEvent) waithandle).Set ();
148 public Socket Socket {
161 private sealed class Worker
163 SocketAsyncResult result;
165 public Worker (SocketAsyncResult ares)
170 public void Accept ()
173 Socket acc_socket = null;
175 acc_socket = result.Sock.Accept ();
176 } catch (Exception e) {
181 result.Complete (acc_socket);
185 public void Connect ()
189 if (!result.Sock.blocking)
190 result.Sock.Poll (-1, SelectMode.SelectWrite);
192 result.Sock.Connect (result.EndPoint);
193 } catch (Exception e) {
202 public void Receive ()
207 if (!result.Sock.blocking)
208 result.Sock.Poll (-1, SelectMode.SelectRead);
210 total = result.Sock.Receive_nochecks (result.Buffer,
214 } catch (Exception e) {
219 result.Complete (total);
223 public void ReceiveFrom ()
228 if (!result.Sock.blocking)
229 result.Sock.Poll (-1, SelectMode.SelectRead);
231 total = result.Sock.ReceiveFrom_nochecks (result.Buffer,
235 ref result.EndPoint);
236 } catch (Exception e) {
241 result.Complete (total);
250 if (!result.Sock.blocking)
251 result.Sock.Poll (-1, SelectMode.SelectWrite);
253 total = result.Sock.Send_nochecks (result.Buffer,
257 } catch (Exception e) {
262 result.Complete (total);
266 public void SendTo() {
270 if (!result.Sock.blocking)
271 result.Sock.Poll (-1, SelectMode.SelectWrite);
273 total = result.Sock.SendTo_nochecks (result.Buffer,
278 } catch (Exception e) {
283 result.Complete (total);
288 /* the field "socket" is looked up by name by the runtime */
289 private IntPtr socket;
290 private AddressFamily address_family;
291 private SocketType socket_type;
292 private ProtocolType protocol_type;
293 internal bool blocking=true;
294 private int pendingEnds;
295 private int closeDelayed;
296 static readonly bool supportsAsync = FakeGetSupportsAsync ();
298 delegate void SocketAsyncCall ();
300 * These two fields are looked up by name by the runtime, don't change
301 * their name without also updating the runtime code.
303 private static int ipv4Supported = -1, ipv6Supported = -1;
305 /* When true, the socket was connected at the time of
306 * the last IO operation
308 private bool connected=false;
309 /* true if we called Close_internal */
312 /* Used in LocalEndPoint and RemoteEndPoint if the
313 * Mono.Posix assembly is available
315 private static object unixendpoint=null;
316 private static Type unixendpointtype=null;
318 [MethodImplAttribute(MethodImplOptions.InternalCall)]
319 private extern static void Select_internal(ref Socket[] read,
325 public static void Select(IList read_list, IList write_list,
326 IList err_list, int time_us) {
327 if(read_list==null &&
330 throw new ArgumentNullException();
333 int read_count = 0, write_count = 0, err_count = 0;
334 Socket[] read_arr = null;
335 Socket[] write_arr = null;
336 Socket[] err_arr = null;
339 read_count=read_list.Count;
342 read_arr=new Socket[read_count];
344 if (write_list!=null)
345 write_count=write_list.Count;
347 if (write_count != 0)
348 write_arr=new Socket[write_count];
351 err_count=err_list.Count;
354 err_arr=new Socket[err_count];
358 if (read_count != 0) {
361 foreach (Socket s in read_list) {
367 if (write_count != 0) {
369 foreach (Socket s in write_list) {
375 if (err_count != 0) {
377 foreach (Socket s in err_list) {
385 Select_internal(ref read_arr, ref write_arr,
386 ref err_arr, time_us, out error);
389 throw new SocketException (error);
392 if(read_list!=null) {
394 for(i=0; i<read_arr.Length; i++) {
395 read_list.Add(read_arr[i]);
399 if(write_list!=null) {
401 for(i=0; i<write_arr.Length; i++) {
402 write_list.Add(write_arr[i]);
408 for(i=0; i<err_arr.Length; i++) {
409 err_list.Add(err_arr[i]);
418 ass=Assembly.Load("Mono.Posix");
419 } catch (FileNotFoundException) {
423 unixendpointtype=ass.GetType("Mono.Posix.UnixEndPoint");
425 /* The endpoint Create() method is an instance
428 Type[] arg_types=new Type[1];
429 arg_types[0]=typeof(string);
430 ConstructorInfo cons=unixendpointtype.GetConstructor(arg_types);
432 object[] args=new object[1];
435 unixendpoint=cons.Invoke(args);
438 // private constructor used by Accept, which already
439 // has a socket handle to use
440 private Socket(AddressFamily family, SocketType type,
441 ProtocolType proto, IntPtr sock) {
442 address_family=family;
450 // Creates a new system socket, returning the handle
451 [MethodImplAttribute(MethodImplOptions.InternalCall)]
452 private extern IntPtr Socket_internal(AddressFamily family,
457 public Socket(AddressFamily family, SocketType type,
458 ProtocolType proto) {
459 address_family=family;
465 socket=Socket_internal(family, type, proto, out error);
467 throw new SocketException (error);
471 public AddressFamily AddressFamily {
473 return(address_family);
477 // Returns the amount of data waiting to be read on socket
478 [MethodImplAttribute(MethodImplOptions.InternalCall)]
479 private extern static int Available_internal(IntPtr socket,
482 public int Available {
484 if (disposed && closed)
485 throw new ObjectDisposedException (GetType ().ToString ());
489 ret = Available_internal(socket, out error);
492 throw new SocketException (error);
499 [MethodImplAttribute(MethodImplOptions.InternalCall)]
500 private extern static void Blocking_internal(IntPtr socket,
504 public bool Blocking {
511 Blocking_internal(socket, value, out error);
514 throw new SocketException (error);
521 public bool Connected {
527 public IntPtr Handle {
533 // Returns the local endpoint details in addr and port
534 [MethodImplAttribute(MethodImplOptions.InternalCall)]
535 private extern static SocketAddress LocalEndPoint_internal(IntPtr socket, out int error);
537 [MonoTODO("Support non-IP endpoints")]
538 public EndPoint LocalEndPoint {
540 if (disposed && closed)
541 throw new ObjectDisposedException (GetType ().ToString ());
546 sa=LocalEndPoint_internal(socket, out error);
549 throw new SocketException (error);
552 if(sa.Family==AddressFamily.InterNetwork || sa.Family==AddressFamily.InterNetworkV6) {
553 // Stupidly, EndPoint.Create() is an
555 return new IPEndPoint(0, 0).Create(sa);
556 } else if (sa.Family==AddressFamily.Unix &&
557 unixendpoint!=null) {
558 return((EndPoint)unixendpointtype.InvokeMember("Create", BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public, null, unixendpoint, new object[] {sa}));
560 throw new NotImplementedException();
565 public ProtocolType ProtocolType {
567 return(protocol_type);
571 // Returns the remote endpoint details in addr and port
572 [MethodImplAttribute(MethodImplOptions.InternalCall)]
573 private extern static SocketAddress RemoteEndPoint_internal(IntPtr socket, out int error);
575 [MonoTODO("Support non-IP endpoints")]
576 public EndPoint RemoteEndPoint {
578 if (disposed && closed)
579 throw new ObjectDisposedException (GetType ().ToString ());
584 sa=RemoteEndPoint_internal(socket, out error);
587 throw new SocketException (error);
590 if(sa.Family==AddressFamily.InterNetwork || sa.Family==AddressFamily.InterNetworkV6 ) {
591 // Stupidly, EndPoint.Create() is an
593 return new IPEndPoint(0, 0).Create(sa);
594 } else if (sa.Family==AddressFamily.Unix &&
595 unixendpoint!=null) {
596 return((EndPoint)unixendpointtype.InvokeMember("Create", BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public, null, unixendpoint, new object[] {sa}));
598 throw new NotImplementedException();
603 public SocketType SocketType {
610 public static bool SupportsIPv4 {
612 CheckProtocolSupport();
613 return ipv4Supported == 1;
617 public static bool SupportsIPv6 {
619 CheckProtocolSupport();
620 return ipv6Supported == 1;
624 internal static bool SupportsIPv4
632 internal static bool SupportsIPv6
641 internal static void CheckProtocolSupport()
643 if(ipv4Supported == -1) {
645 Socket tmp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
655 if(ipv6Supported == -1) {
656 NetConfig config = (NetConfig)System.Configuration.ConfigurationSettings.GetConfig("system.net/settings");
659 ipv6Supported = config.ipv6Enabled?-1:0;
661 if(ipv6Supported != 0) {
663 Socket tmp = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
673 // Creates a new system socket, returning the handle
674 [MethodImplAttribute(MethodImplOptions.InternalCall)]
675 private extern static IntPtr Accept_internal(IntPtr sock,
678 public Socket Accept() {
679 if (disposed && closed)
680 throw new ObjectDisposedException (GetType ().ToString ());
683 IntPtr sock=Accept_internal(socket, out error);
686 throw new SocketException (error);
689 return(new Socket(this.AddressFamily, this.SocketType,
690 this.ProtocolType, sock));
693 public IAsyncResult BeginAccept(AsyncCallback callback,
696 if (disposed && closed)
697 throw new ObjectDisposedException (GetType ().ToString ());
699 Interlocked.Increment (ref pendingEnds);
700 SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
701 Worker worker = new Worker (req);
702 SocketAsyncCall sac = new SocketAsyncCall (worker.Accept);
703 sac.BeginInvoke (null, null);
707 public IAsyncResult BeginConnect(EndPoint end_point,
708 AsyncCallback callback,
711 if (disposed && closed)
712 throw new ObjectDisposedException (GetType ().ToString ());
714 if (end_point == null)
715 throw new ArgumentNullException ("end_point");
717 Interlocked.Increment (ref pendingEnds);
718 SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
719 req.EndPoint = end_point;
720 Worker worker = new Worker (req);
721 SocketAsyncCall sac = new SocketAsyncCall (worker.Connect);
722 sac.BeginInvoke (null, null);
726 public IAsyncResult BeginReceive(byte[] buffer, int offset,
728 SocketFlags socket_flags,
729 AsyncCallback callback,
732 if (disposed && closed)
733 throw new ObjectDisposedException (GetType ().ToString ());
736 throw new ArgumentNullException ("buffer");
738 if (offset < 0 || offset > buffer.Length)
739 throw new ArgumentOutOfRangeException ("offset");
741 if (size < 0 || offset + size > buffer.Length)
742 throw new ArgumentOutOfRangeException ("size");
744 Interlocked.Increment (ref pendingEnds);
745 SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
749 req.SockFlags = socket_flags;
750 if (supportsAsync && socket_type == SocketType.Stream) {
752 req.CreateAsyncDelegate ();
754 AsyncReceiveInternal (req, out error);
755 if (error != 10036) // WSAEINPROGRESS
756 throw new SocketException (error);
758 Worker worker = new Worker (req);
759 SocketAsyncCall sac = new SocketAsyncCall (worker.Receive);
760 sac.BeginInvoke (null, null);
766 public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset,
768 SocketFlags socket_flags,
769 ref EndPoint remote_end,
770 AsyncCallback callback,
772 if (disposed && closed)
773 throw new ObjectDisposedException (GetType ().ToString ());
776 throw new ArgumentNullException ("buffer");
779 throw new ArgumentOutOfRangeException ("offset must be >= 0");
782 throw new ArgumentOutOfRangeException ("size must be >= 0");
784 if (offset + size > buffer.Length)
785 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
787 Interlocked.Increment (ref pendingEnds);
788 SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
792 req.SockFlags = socket_flags;
793 req.EndPoint = remote_end;
794 Worker worker = new Worker (req);
795 SocketAsyncCall sac = new SocketAsyncCall (worker.ReceiveFrom);
796 sac.BeginInvoke (null, null);
800 public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socket_flags,
801 AsyncCallback callback, object state)
803 if (disposed && closed)
804 throw new ObjectDisposedException (GetType ().ToString ());
807 throw new ArgumentNullException ("buffer");
810 throw new ArgumentOutOfRangeException ("offset must be >= 0");
813 throw new ArgumentOutOfRangeException ("size must be >= 0");
815 if (offset + size > buffer.Length)
816 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
818 Interlocked.Increment (ref pendingEnds);
819 SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
823 req.SockFlags = socket_flags;
824 if (supportsAsync && socket_type == SocketType.Stream) {
826 req.CreateAsyncDelegate ();
828 AsyncSendInternal (req, out error);
829 if (error != 10036) // WSAEINPROGRESS
830 throw new SocketException (error);
832 Worker worker = new Worker (req);
833 SocketAsyncCall sac = new SocketAsyncCall (worker.Send);
834 sac.BeginInvoke (null, null);
839 public IAsyncResult BeginSendTo(byte[] buffer, int offset,
841 SocketFlags socket_flags,
843 AsyncCallback callback,
845 if (disposed && closed)
846 throw new ObjectDisposedException (GetType ().ToString ());
849 throw new ArgumentNullException ("buffer");
852 throw new ArgumentOutOfRangeException ("offset must be >= 0");
855 throw new ArgumentOutOfRangeException ("size must be >= 0");
857 if (offset + size > buffer.Length)
858 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
860 Interlocked.Increment (ref pendingEnds);
861 SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
865 req.SockFlags = socket_flags;
866 req.EndPoint = remote_end;
867 Worker worker = new Worker(req);
868 SocketAsyncCall sac = new SocketAsyncCall (worker.SendTo);
869 sac.BeginInvoke (null, null);
873 // Creates a new system socket, returning the handle
874 [MethodImplAttribute(MethodImplOptions.InternalCall)]
875 private extern static void Bind_internal(IntPtr sock,
879 public void Bind(EndPoint local_end) {
880 if (disposed && closed)
881 throw new ObjectDisposedException (GetType ().ToString ());
883 if(local_end==null) {
884 throw new ArgumentNullException("local_end");
889 Bind_internal(socket, local_end.Serialize(),
893 throw new SocketException (error);
898 [MethodImplAttribute(MethodImplOptions.InternalCall)]
899 private extern static void Close_internal(IntPtr socket,
902 public void Close() {
903 ((IDisposable) this).Dispose ();
906 // Connects to the remote address
907 [MethodImplAttribute(MethodImplOptions.InternalCall)]
908 private extern static void Connect_internal(IntPtr sock,
912 public void Connect(EndPoint remote_end) {
913 if (disposed && closed)
914 throw new ObjectDisposedException (GetType ().ToString ());
916 if(remote_end==null) {
917 throw new ArgumentNullException("remote_end");
922 Connect_internal(socket, remote_end.Serialize(), out error);
925 throw new SocketException (error);
931 public Socket EndAccept(IAsyncResult result) {
932 if (disposed && closed)
933 throw new ObjectDisposedException (GetType ().ToString ());
936 throw new ArgumentNullException ("result");
938 SocketAsyncResult req = result as SocketAsyncResult;
940 throw new ArgumentException ("Invalid IAsyncResult", "result");
942 if (!result.IsCompleted)
943 result.AsyncWaitHandle.WaitOne();
945 Interlocked.Decrement (ref pendingEnds);
947 req.CheckIfThrowDelayedException();
951 public void EndConnect(IAsyncResult result) {
952 if (disposed && closed)
953 throw new ObjectDisposedException (GetType ().ToString ());
956 throw new ArgumentNullException ("result");
958 SocketAsyncResult req = result as SocketAsyncResult;
960 throw new ArgumentException ("Invalid IAsyncResult", "result");
962 if (!result.IsCompleted)
963 result.AsyncWaitHandle.WaitOne();
965 Interlocked.Decrement (ref pendingEnds);
967 req.CheckIfThrowDelayedException();
970 public int EndReceive(IAsyncResult result) {
971 if (disposed && closed)
972 throw new ObjectDisposedException (GetType ().ToString ());
975 throw new ArgumentNullException ("result");
977 SocketAsyncResult req = result as SocketAsyncResult;
979 throw new ArgumentException ("Invalid IAsyncResult", "result");
981 RemoveReference (req);
982 if (!result.IsCompleted)
983 result.AsyncWaitHandle.WaitOne();
985 Interlocked.Decrement (ref pendingEnds);
987 req.CheckIfThrowDelayedException();
991 public int EndReceiveFrom(IAsyncResult result,
992 ref EndPoint end_point) {
993 if (disposed && closed)
994 throw new ObjectDisposedException (GetType ().ToString ());
997 throw new ArgumentNullException ("result");
999 SocketAsyncResult req = result as SocketAsyncResult;
1001 throw new ArgumentException ("Invalid IAsyncResult", "result");
1003 if (!result.IsCompleted)
1004 result.AsyncWaitHandle.WaitOne();
1006 Interlocked.Decrement (ref pendingEnds);
1008 req.CheckIfThrowDelayedException();
1009 end_point = req.EndPoint;
1013 public int EndSend(IAsyncResult result) {
1014 if (disposed && closed)
1015 throw new ObjectDisposedException (GetType ().ToString ());
1018 throw new ArgumentNullException ("result");
1020 SocketAsyncResult req = result as SocketAsyncResult;
1022 throw new ArgumentException ("Invalid IAsyncResult", "result");
1024 RemoveReference (req);
1025 if (!result.IsCompleted)
1026 result.AsyncWaitHandle.WaitOne();
1028 Interlocked.Decrement (ref pendingEnds);
1030 req.CheckIfThrowDelayedException();
1034 public int EndSendTo(IAsyncResult result) {
1035 if (disposed && closed)
1036 throw new ObjectDisposedException (GetType ().ToString ());
1039 throw new ArgumentNullException ("result");
1041 SocketAsyncResult req = result as SocketAsyncResult;
1043 throw new ArgumentException ("Invalid IAsyncResult", "result");
1045 if (!result.IsCompleted)
1046 result.AsyncWaitHandle.WaitOne();
1048 Interlocked.Decrement (ref pendingEnds);
1050 req.CheckIfThrowDelayedException();
1054 void CheckIfClose ()
1056 if (Interlocked.CompareExchange (ref closeDelayed, 0, 1) == 1 &&
1057 Interlocked.CompareExchange (ref pendingEnds, 0, 0) == 0) {
1062 Close_internal(socket, out error);
1065 throw new SocketException (error);
1070 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1071 private extern static void GetSocketOption_obj_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, out object obj_val, out int error);
1072 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1073 private extern static void GetSocketOption_arr_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val, out int error);
1075 public object GetSocketOption(SocketOptionLevel level,
1076 SocketOptionName name) {
1080 GetSocketOption_obj_internal(socket, level, name,
1081 out obj_val, out error);
1084 throw new SocketException (error);
1087 if(name==SocketOptionName.Linger) {
1088 return((LingerOption)obj_val);
1089 } else if (name==SocketOptionName.AddMembership ||
1090 name==SocketOptionName.DropMembership) {
1091 return((MulticastOption)obj_val);
1093 return((int)obj_val);
1097 public void GetSocketOption(SocketOptionLevel level,
1098 SocketOptionName name,
1100 int opt_value_len=opt_value.Length;
1103 GetSocketOption_arr_internal(socket, level, name,
1104 ref opt_value, out error);
1107 throw new SocketException (error);
1111 public byte[] GetSocketOption(SocketOptionLevel level,
1112 SocketOptionName name,
1114 byte[] byte_val=new byte[length];
1117 GetSocketOption_arr_internal(socket, level, name,
1118 ref byte_val, out error);
1121 throw new SocketException (error);
1127 // See Socket.IOControl, WSAIoctl documentation in MSDN. The
1128 // common options between UNIX and Winsock are FIONREAD,
1129 // FIONBIO and SIOCATMARK. Anything else will depend on the
1131 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1132 extern static int WSAIoctl (IntPtr sock, int ioctl_code,
1133 byte [] input, byte [] output,
1136 public int IOControl (int ioctl_code, byte [] in_value, byte [] out_value)
1139 throw new ObjectDisposedException (GetType ().ToString ());
1142 int result = WSAIoctl (socket, ioctl_code, in_value,
1143 out_value, out error);
1146 throw new SocketException (error);
1150 throw new InvalidOperationException ("Must use Blocking property instead.");
1155 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1156 private extern static void Listen_internal(IntPtr sock,
1160 public void Listen(int backlog) {
1163 Listen_internal(socket, backlog, out error);
1166 throw new SocketException (error);
1170 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1171 extern static bool Poll_internal (IntPtr socket, SelectMode mode, int timeout, out int error);
1173 public bool Poll (int time_us, SelectMode mode)
1175 if (mode != SelectMode.SelectRead &&
1176 mode != SelectMode.SelectWrite &&
1177 mode != SelectMode.SelectError)
1178 throw new NotSupportedException ("'mode' parameter is not valid.");
1181 bool result = Poll_internal (socket, mode, time_us, out error);
1183 throw new SocketException (error);
1188 public int Receive (byte [] buf)
1191 throw new ArgumentNullException ("buf");
1193 return Receive_nochecks (buf, 0, buf.Length, SocketFlags.None);
1196 public int Receive (byte [] buf, SocketFlags flags)
1199 throw new ArgumentNullException ("buf");
1201 return Receive_nochecks (buf, 0, buf.Length, flags);
1204 public int Receive (byte [] buf, int size, SocketFlags flags)
1207 throw new ArgumentNullException ("buf");
1209 if (size < 0 || size > buf.Length)
1210 throw new ArgumentOutOfRangeException ("size");
1212 return Receive_nochecks (buf, 0, size, flags);
1215 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1216 private extern static int Receive_internal(IntPtr sock,
1223 public int Receive (byte [] buf, int offset, int size, SocketFlags flags)
1226 throw new ArgumentNullException ("buf");
1228 if (offset < 0 || offset > buf.Length)
1229 throw new ArgumentOutOfRangeException ("offset");
1231 if (size < 0 || offset + size > buf.Length)
1232 throw new ArgumentOutOfRangeException ("size");
1234 return Receive_nochecks (buf, offset, size, flags);
1237 int Receive_nochecks (byte [] buf, int offset, int size, SocketFlags flags)
1241 ret = Receive_internal (socket, buf, offset, size, flags, out error);
1245 throw new SocketException (error);
1253 public int ReceiveFrom (byte [] buf, ref EndPoint remote_end)
1256 throw new ArgumentNullException ("buf");
1258 if (remote_end == null)
1259 throw new ArgumentNullException ("remote_end");
1261 return ReceiveFrom_nochecks (buf, 0, buf.Length, SocketFlags.None, ref remote_end);
1264 public int ReceiveFrom (byte [] buf, SocketFlags flags, ref EndPoint remote_end)
1267 throw new ArgumentNullException ("buf");
1269 if (remote_end == null)
1270 throw new ArgumentNullException ("remote_end");
1273 return ReceiveFrom_nochecks (buf, 0, buf.Length, flags, ref remote_end);
1276 public int ReceiveFrom (byte [] buf, int size, SocketFlags flags,
1277 ref EndPoint remote_end)
1280 throw new ArgumentNullException ("buf");
1282 if (remote_end == null)
1283 throw new ArgumentNullException ("remote_end");
1285 if (size < 0 || size > buf.Length)
1286 throw new ArgumentOutOfRangeException ("size");
1288 return ReceiveFrom_nochecks (buf, 0, size, flags, ref remote_end);
1292 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1293 private extern static int RecvFrom_internal(IntPtr sock,
1298 ref SocketAddress sockaddr,
1301 public int ReceiveFrom (byte [] buf, int offset, int size, SocketFlags flags,
1302 ref EndPoint remote_end)
1305 throw new ArgumentNullException ("buf");
1307 if (remote_end == null)
1308 throw new ArgumentNullException ("remote_end");
1310 if (offset < 0 || offset > buf.Length)
1311 throw new ArgumentOutOfRangeException ("offset");
1313 if (size < 0 || offset + size > buf.Length)
1314 throw new ArgumentOutOfRangeException ("size");
1316 return ReceiveFrom_nochecks (buf, offset, size, flags, ref remote_end);
1319 int ReceiveFrom_nochecks (byte [] buf, int offset, int size, SocketFlags flags,
1320 ref EndPoint remote_end)
1322 SocketAddress sockaddr = remote_end.Serialize();
1325 cnt = RecvFrom_internal (socket, buf, offset, size, flags, ref sockaddr, out error);
1329 throw new SocketException (error);
1334 // Stupidly, EndPoint.Create() is an
1336 remote_end = remote_end.Create (sockaddr);
1341 public int Send (byte [] buf)
1344 throw new ArgumentNullException ("buf");
1346 return Send_nochecks (buf, 0, buf.Length, SocketFlags.None);
1349 public int Send (byte [] buf, SocketFlags flags)
1352 throw new ArgumentNullException ("buf");
1354 return Send_nochecks (buf, 0, buf.Length, flags);
1357 public int Send (byte [] buf, int size, SocketFlags flags)
1360 throw new ArgumentNullException ("buf");
1362 if (size < 0 || size > buf.Length)
1363 throw new ArgumentOutOfRangeException ("size");
1365 return Send_nochecks (buf, 0, size, flags);
1368 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1369 private extern static int Send_internal(IntPtr sock,
1370 byte[] buf, int offset,
1375 public int Send (byte [] buf, int offset, int size, SocketFlags flags)
1378 throw new ArgumentNullException ("buffer");
1380 if (offset < 0 || offset > buf.Length)
1381 throw new ArgumentOutOfRangeException ("offset");
1383 if (size < 0 || offset + size > buf.Length)
1384 throw new ArgumentOutOfRangeException ("size");
1386 return Send_nochecks (buf, offset, size, flags);
1389 int Send_nochecks (byte [] buf, int offset, int size, SocketFlags flags)
1396 ret = Send_internal (socket, buf, offset, size, flags, out error);
1400 throw new SocketException (error);
1408 public int SendTo (byte [] buffer, EndPoint remote_end)
1411 throw new ArgumentNullException ("buffer");
1413 if (remote_end == null)
1414 throw new ArgumentNullException ("remote_end");
1416 return SendTo_nochecks (buffer, 0, buffer.Length, SocketFlags.None, remote_end);
1419 public int SendTo (byte [] buffer, SocketFlags flags, EndPoint remote_end)
1422 throw new ArgumentNullException ("buffer");
1424 if (remote_end == null)
1425 throw new ArgumentNullException ("remote_end");
1427 return SendTo_nochecks (buffer, 0, buffer.Length, flags, remote_end);
1430 public int SendTo (byte [] buffer, int size, SocketFlags flags, EndPoint remote_end)
1433 throw new ArgumentNullException ("buffer");
1435 if (remote_end == null)
1436 throw new ArgumentNullException ("remote_end");
1438 if (size < 0 || size > buffer.Length)
1439 throw new ArgumentOutOfRangeException ("size");
1441 return SendTo_nochecks (buffer, 0, size, flags, remote_end);
1445 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1446 private extern static int SendTo_internal(IntPtr sock,
1454 public int SendTo (byte [] buffer, int offset, int size, SocketFlags flags,
1455 EndPoint remote_end)
1458 throw new ArgumentNullException ("buffer");
1460 if (remote_end == null)
1461 throw new ArgumentNullException("remote_end");
1463 if (offset < 0 || offset > buffer.Length)
1464 throw new ArgumentOutOfRangeException ("offset");
1466 if (size < 0 || offset + size > buffer.Length)
1467 throw new ArgumentOutOfRangeException ("size");
1469 return SendTo_nochecks (buffer, offset, size, flags, remote_end);
1472 int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags,
1473 EndPoint remote_end)
1475 SocketAddress sockaddr = remote_end.Serialize ();
1479 ret = SendTo_internal (socket, buffer, offset, size, flags, sockaddr, out error);
1483 throw new SocketException (error);
1491 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1492 private extern static void SetSocketOption_internal (IntPtr socket, SocketOptionLevel level,
1493 SocketOptionName name, object obj_val,
1494 byte [] byte_val, int int_val,
1497 public void SetSocketOption(SocketOptionLevel level,
1498 SocketOptionName name,
1502 SetSocketOption_internal(socket, level, name, null,
1503 opt_value, 0, out error);
1506 throw new SocketException (error);
1510 public void SetSocketOption(SocketOptionLevel level,
1511 SocketOptionName name,
1515 SetSocketOption_internal(socket, level, name, null,
1516 null, opt_value, out error);
1519 throw new SocketException (error);
1523 public void SetSocketOption(SocketOptionLevel level,
1524 SocketOptionName name,
1526 if(opt_value==null) {
1527 throw new ArgumentNullException();
1532 /* Passing a bool as the third parameter to
1533 * SetSocketOption causes this overload to be
1534 * used when in fact we want to pass the value
1535 * to the runtime as an int.
1537 if (opt_value is System.Boolean) {
1538 bool bool_val = (bool) opt_value;
1539 int int_val = (bool_val) ? 1 : 0;
1541 SetSocketOption_internal (socket, level, name, null, null, int_val, out error);
1543 SetSocketOption_internal (socket, level, name, opt_value, null, 0, out error);
1547 throw new SocketException (error);
1551 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1552 private extern static void Shutdown_internal(IntPtr socket, SocketShutdown how, out int error);
1554 public void Shutdown(SocketShutdown how) {
1557 Shutdown_internal(socket, how, out error);
1560 throw new SocketException (error);
1564 public override int GetHashCode ()
1566 return (int) socket;
1569 private bool disposed;
1571 protected virtual void Dispose(bool explicitDisposing) {
1577 if (!explicitDisposing) {
1579 Close_internal (socket, out error);
1582 throw new SocketException (error);
1588 if (Interlocked.CompareExchange (ref pendingEnds, 0, 0) == 0) {
1590 Close_internal (socket, out error);
1593 throw new SocketException (error);
1596 Interlocked.CompareExchange (ref closeDelayed, 1, 0);
1601 void IDisposable.Dispose ()
1604 GC.SuppressFinalize (this);
1611 static Hashtable asyncObjects;
1613 static void KeepReference (object o)
1615 lock (typeof (Socket)) {
1616 if (asyncObjects == null)
1617 asyncObjects = new Hashtable ();
1619 asyncObjects [o] = o;
1623 static void RemoveReference (object o)
1625 lock (typeof (Socket)) {
1626 if (asyncObjects == null)
1629 asyncObjects.Remove (o);
1633 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1634 extern static bool GetSupportsAsync ();
1636 static bool FakeGetSupportsAsync ()
1638 if (Environment.GetEnvironmentVariable ("MONO_ENABLE_SOCKET_AIO") != null)
1639 return GetSupportsAsync ();
1644 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1645 extern static void AsyncReceiveInternal (SocketAsyncResult ares, out int error);
1647 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1648 extern static void AsyncSendInternal (SocketAsyncResult ares, out int error);