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 result.Sock.Connect (result.EndPoint);
190 } catch (SocketException se) {
191 if (result.Sock.blocking || se.ErrorCode != 10036) {
192 result.Complete (se);
197 result.Sock.Poll (-1, SelectMode.SelectWrite);
198 result.Sock.Connect (result.EndPoint);
199 } catch (Exception k) {
203 } catch (Exception e) {
212 public void Receive ()
217 if (!result.Sock.blocking)
218 result.Sock.Poll (-1, SelectMode.SelectRead);
220 total = result.Sock.Receive_nochecks (result.Buffer,
224 } catch (Exception e) {
229 result.Complete (total);
233 public void ReceiveFrom ()
238 if (!result.Sock.blocking)
239 result.Sock.Poll (-1, SelectMode.SelectRead);
241 total = result.Sock.ReceiveFrom_nochecks (result.Buffer,
245 ref result.EndPoint);
246 } catch (Exception e) {
251 result.Complete (total);
260 if (!result.Sock.blocking)
261 result.Sock.Poll (-1, SelectMode.SelectWrite);
263 total = result.Sock.Send_nochecks (result.Buffer,
267 } catch (Exception e) {
272 result.Complete (total);
276 public void SendTo() {
280 if (!result.Sock.blocking)
281 result.Sock.Poll (-1, SelectMode.SelectWrite);
283 total = result.Sock.SendTo_nochecks (result.Buffer,
288 } catch (Exception e) {
293 result.Complete (total);
298 /* the field "socket" is looked up by name by the runtime */
299 private IntPtr socket;
300 private AddressFamily address_family;
301 private SocketType socket_type;
302 private ProtocolType protocol_type;
303 internal bool blocking=true;
304 private int pendingEnds;
305 private int closeDelayed;
306 static readonly bool supportsAsync = FakeGetSupportsAsync ();
308 delegate void SocketAsyncCall ();
310 * These two fields are looked up by name by the runtime, don't change
311 * their name without also updating the runtime code.
313 private static int ipv4Supported = -1, ipv6Supported = -1;
315 /* When true, the socket was connected at the time of
316 * the last IO operation
318 private bool connected=false;
319 /* true if we called Close_internal */
322 /* Used in LocalEndPoint and RemoteEndPoint if the
323 * Mono.Posix assembly is available
325 private static object unixendpoint=null;
326 private static Type unixendpointtype=null;
328 [MethodImplAttribute(MethodImplOptions.InternalCall)]
329 private extern static void Select_internal(ref Socket[] read,
335 public static void Select(IList read_list, IList write_list,
336 IList err_list, int time_us) {
337 if(read_list==null &&
340 throw new ArgumentNullException();
343 int read_count = 0, write_count = 0, err_count = 0;
344 Socket[] read_arr = null;
345 Socket[] write_arr = null;
346 Socket[] err_arr = null;
349 read_count=read_list.Count;
352 read_arr=new Socket[read_count];
354 if (write_list!=null)
355 write_count=write_list.Count;
357 if (write_count != 0)
358 write_arr=new Socket[write_count];
361 err_count=err_list.Count;
364 err_arr=new Socket[err_count];
368 if (read_count != 0) {
371 foreach (Socket s in read_list) {
377 if (write_count != 0) {
379 foreach (Socket s in write_list) {
385 if (err_count != 0) {
387 foreach (Socket s in err_list) {
395 Select_internal(ref read_arr, ref write_arr,
396 ref err_arr, time_us, out error);
399 throw new SocketException (error);
402 if(read_list!=null) {
404 for(i=0; i<read_arr.Length; i++) {
405 read_list.Add(read_arr[i]);
409 if(write_list!=null) {
411 for(i=0; i<write_arr.Length; i++) {
412 write_list.Add(write_arr[i]);
418 for(i=0; i<err_arr.Length; i++) {
419 err_list.Add(err_arr[i]);
428 ass = Assembly.Load (Consts.AssemblyMono_Posix);
429 } catch (FileNotFoundException) {
433 unixendpointtype=ass.GetType("Mono.Posix.UnixEndPoint");
435 /* The endpoint Create() method is an instance
438 Type[] arg_types=new Type[1];
439 arg_types[0]=typeof(string);
440 ConstructorInfo cons=unixendpointtype.GetConstructor(arg_types);
442 object[] args=new object[1];
445 unixendpoint=cons.Invoke(args);
448 // private constructor used by Accept, which already
449 // has a socket handle to use
450 private Socket(AddressFamily family, SocketType type,
451 ProtocolType proto, IntPtr sock) {
452 address_family=family;
460 // Creates a new system socket, returning the handle
461 [MethodImplAttribute(MethodImplOptions.InternalCall)]
462 private extern IntPtr Socket_internal(AddressFamily family,
467 public Socket(AddressFamily family, SocketType type,
468 ProtocolType proto) {
469 address_family=family;
475 socket=Socket_internal(family, type, proto, out error);
477 throw new SocketException (error);
481 public AddressFamily AddressFamily {
483 return(address_family);
487 // Returns the amount of data waiting to be read on socket
488 [MethodImplAttribute(MethodImplOptions.InternalCall)]
489 private extern static int Available_internal(IntPtr socket,
492 public int Available {
494 if (disposed && closed)
495 throw new ObjectDisposedException (GetType ().ToString ());
499 ret = Available_internal(socket, out error);
502 throw new SocketException (error);
509 [MethodImplAttribute(MethodImplOptions.InternalCall)]
510 private extern static void Blocking_internal(IntPtr socket,
514 public bool Blocking {
521 Blocking_internal(socket, value, out error);
524 throw new SocketException (error);
531 public bool Connected {
537 public IntPtr Handle {
543 // Returns the local endpoint details in addr and port
544 [MethodImplAttribute(MethodImplOptions.InternalCall)]
545 private extern static SocketAddress LocalEndPoint_internal(IntPtr socket, out int error);
547 [MonoTODO("Support non-IP endpoints")]
548 public EndPoint LocalEndPoint {
550 if (disposed && closed)
551 throw new ObjectDisposedException (GetType ().ToString ());
556 sa=LocalEndPoint_internal(socket, out error);
559 throw new SocketException (error);
562 if(sa.Family==AddressFamily.InterNetwork || sa.Family==AddressFamily.InterNetworkV6) {
563 // Stupidly, EndPoint.Create() is an
565 return new IPEndPoint(0, 0).Create(sa);
566 } else if (sa.Family==AddressFamily.Unix &&
567 unixendpoint!=null) {
568 return((EndPoint)unixendpointtype.InvokeMember("Create", BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public, null, unixendpoint, new object[] {sa}));
570 throw new NotImplementedException();
575 public ProtocolType ProtocolType {
577 return(protocol_type);
581 // Returns the remote endpoint details in addr and port
582 [MethodImplAttribute(MethodImplOptions.InternalCall)]
583 private extern static SocketAddress RemoteEndPoint_internal(IntPtr socket, out int error);
585 [MonoTODO("Support non-IP endpoints")]
586 public EndPoint RemoteEndPoint {
588 if (disposed && closed)
589 throw new ObjectDisposedException (GetType ().ToString ());
594 sa=RemoteEndPoint_internal(socket, out error);
597 throw new SocketException (error);
600 if(sa.Family==AddressFamily.InterNetwork || sa.Family==AddressFamily.InterNetworkV6 ) {
601 // Stupidly, EndPoint.Create() is an
603 return new IPEndPoint(0, 0).Create(sa);
604 } else if (sa.Family==AddressFamily.Unix &&
605 unixendpoint!=null) {
606 return((EndPoint)unixendpointtype.InvokeMember("Create", BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public, null, unixendpoint, new object[] {sa}));
608 throw new NotImplementedException();
613 public SocketType SocketType {
620 public static bool SupportsIPv4 {
622 CheckProtocolSupport();
623 return ipv4Supported == 1;
627 public static bool SupportsIPv6 {
629 CheckProtocolSupport();
630 return ipv6Supported == 1;
634 internal static bool SupportsIPv4
642 internal static bool SupportsIPv6
651 internal static void CheckProtocolSupport()
653 if(ipv4Supported == -1) {
655 Socket tmp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
665 if(ipv6Supported == -1) {
666 NetConfig config = (NetConfig)System.Configuration.ConfigurationSettings.GetConfig("system.net/settings");
669 ipv6Supported = config.ipv6Enabled?-1:0;
671 if(ipv6Supported != 0) {
673 Socket tmp = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
683 // Creates a new system socket, returning the handle
684 [MethodImplAttribute(MethodImplOptions.InternalCall)]
685 private extern static IntPtr Accept_internal(IntPtr sock,
688 public Socket Accept() {
689 if (disposed && closed)
690 throw new ObjectDisposedException (GetType ().ToString ());
693 IntPtr sock=Accept_internal(socket, out error);
696 throw new SocketException (error);
699 return(new Socket(this.AddressFamily, this.SocketType,
700 this.ProtocolType, sock));
703 public IAsyncResult BeginAccept(AsyncCallback callback,
706 if (disposed && closed)
707 throw new ObjectDisposedException (GetType ().ToString ());
709 Interlocked.Increment (ref pendingEnds);
710 SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
711 Worker worker = new Worker (req);
712 SocketAsyncCall sac = new SocketAsyncCall (worker.Accept);
713 sac.BeginInvoke (null, null);
717 public IAsyncResult BeginConnect(EndPoint end_point,
718 AsyncCallback callback,
721 if (disposed && closed)
722 throw new ObjectDisposedException (GetType ().ToString ());
724 if (end_point == null)
725 throw new ArgumentNullException ("end_point");
727 Interlocked.Increment (ref pendingEnds);
728 SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
729 req.EndPoint = end_point;
730 Worker worker = new Worker (req);
731 SocketAsyncCall sac = new SocketAsyncCall (worker.Connect);
732 sac.BeginInvoke (null, null);
736 public IAsyncResult BeginReceive(byte[] buffer, int offset,
738 SocketFlags socket_flags,
739 AsyncCallback callback,
742 if (disposed && closed)
743 throw new ObjectDisposedException (GetType ().ToString ());
746 throw new ArgumentNullException ("buffer");
748 if (offset < 0 || offset > buffer.Length)
749 throw new ArgumentOutOfRangeException ("offset");
751 if (size < 0 || offset + size > buffer.Length)
752 throw new ArgumentOutOfRangeException ("size");
754 Interlocked.Increment (ref pendingEnds);
755 SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
759 req.SockFlags = socket_flags;
760 if (supportsAsync && socket_type == SocketType.Stream) {
762 req.CreateAsyncDelegate ();
764 AsyncReceiveInternal (req, out error);
765 if (error != 10036) // WSAEINPROGRESS
766 throw new SocketException (error);
768 Worker worker = new Worker (req);
769 SocketAsyncCall sac = new SocketAsyncCall (worker.Receive);
770 sac.BeginInvoke (null, null);
776 public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset,
778 SocketFlags socket_flags,
779 ref EndPoint remote_end,
780 AsyncCallback callback,
782 if (disposed && closed)
783 throw new ObjectDisposedException (GetType ().ToString ());
786 throw new ArgumentNullException ("buffer");
789 throw new ArgumentOutOfRangeException ("offset must be >= 0");
792 throw new ArgumentOutOfRangeException ("size must be >= 0");
794 if (offset + size > buffer.Length)
795 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
797 Interlocked.Increment (ref pendingEnds);
798 SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
802 req.SockFlags = socket_flags;
803 req.EndPoint = remote_end;
804 Worker worker = new Worker (req);
805 SocketAsyncCall sac = new SocketAsyncCall (worker.ReceiveFrom);
806 sac.BeginInvoke (null, null);
810 public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socket_flags,
811 AsyncCallback callback, object state)
813 if (disposed && closed)
814 throw new ObjectDisposedException (GetType ().ToString ());
817 throw new ArgumentNullException ("buffer");
820 throw new ArgumentOutOfRangeException ("offset must be >= 0");
823 throw new ArgumentOutOfRangeException ("size must be >= 0");
825 if (offset + size > buffer.Length)
826 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
828 Interlocked.Increment (ref pendingEnds);
829 SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
833 req.SockFlags = socket_flags;
834 if (supportsAsync && socket_type == SocketType.Stream) {
836 req.CreateAsyncDelegate ();
838 AsyncSendInternal (req, out error);
839 if (error != 10036) // WSAEINPROGRESS
840 throw new SocketException (error);
842 Worker worker = new Worker (req);
843 SocketAsyncCall sac = new SocketAsyncCall (worker.Send);
844 sac.BeginInvoke (null, null);
849 public IAsyncResult BeginSendTo(byte[] buffer, int offset,
851 SocketFlags socket_flags,
853 AsyncCallback callback,
855 if (disposed && closed)
856 throw new ObjectDisposedException (GetType ().ToString ());
859 throw new ArgumentNullException ("buffer");
862 throw new ArgumentOutOfRangeException ("offset must be >= 0");
865 throw new ArgumentOutOfRangeException ("size must be >= 0");
867 if (offset + size > buffer.Length)
868 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
870 Interlocked.Increment (ref pendingEnds);
871 SocketAsyncResult req = new SocketAsyncResult (this, state, callback);
875 req.SockFlags = socket_flags;
876 req.EndPoint = remote_end;
877 Worker worker = new Worker(req);
878 SocketAsyncCall sac = new SocketAsyncCall (worker.SendTo);
879 sac.BeginInvoke (null, null);
883 // Creates a new system socket, returning the handle
884 [MethodImplAttribute(MethodImplOptions.InternalCall)]
885 private extern static void Bind_internal(IntPtr sock,
889 public void Bind(EndPoint local_end) {
890 if (disposed && closed)
891 throw new ObjectDisposedException (GetType ().ToString ());
893 if(local_end==null) {
894 throw new ArgumentNullException("local_end");
899 Bind_internal(socket, local_end.Serialize(),
903 throw new SocketException (error);
908 [MethodImplAttribute(MethodImplOptions.InternalCall)]
909 private extern static void Close_internal(IntPtr socket,
912 public void Close() {
913 ((IDisposable) this).Dispose ();
916 // Connects to the remote address
917 [MethodImplAttribute(MethodImplOptions.InternalCall)]
918 private extern static void Connect_internal(IntPtr sock,
922 public void Connect(EndPoint remote_end) {
923 if (disposed && closed)
924 throw new ObjectDisposedException (GetType ().ToString ());
926 if(remote_end==null) {
927 throw new ArgumentNullException("remote_end");
932 SocketAddress serial = remote_end.Serialize ();
933 Connect_internal(socket, serial, out error);
934 if (!blocking && error == 10036) {
935 Poll (-1, SelectMode.SelectWrite);
936 Connect_internal (socket, serial, out error);
940 throw new SocketException (error);
945 public Socket EndAccept(IAsyncResult result) {
946 if (disposed && closed)
947 throw new ObjectDisposedException (GetType ().ToString ());
950 throw new ArgumentNullException ("result");
952 SocketAsyncResult req = result as SocketAsyncResult;
954 throw new ArgumentException ("Invalid IAsyncResult", "result");
956 if (!result.IsCompleted)
957 result.AsyncWaitHandle.WaitOne();
959 Interlocked.Decrement (ref pendingEnds);
961 req.CheckIfThrowDelayedException();
965 public void EndConnect(IAsyncResult result) {
966 if (disposed && closed)
967 throw new ObjectDisposedException (GetType ().ToString ());
970 throw new ArgumentNullException ("result");
972 SocketAsyncResult req = result as SocketAsyncResult;
974 throw new ArgumentException ("Invalid IAsyncResult", "result");
976 if (!result.IsCompleted)
977 result.AsyncWaitHandle.WaitOne();
979 Interlocked.Decrement (ref pendingEnds);
981 req.CheckIfThrowDelayedException();
984 public int EndReceive(IAsyncResult result) {
985 if (disposed && closed)
986 throw new ObjectDisposedException (GetType ().ToString ());
989 throw new ArgumentNullException ("result");
991 SocketAsyncResult req = result as SocketAsyncResult;
993 throw new ArgumentException ("Invalid IAsyncResult", "result");
995 RemoveReference (req);
996 if (!result.IsCompleted)
997 result.AsyncWaitHandle.WaitOne();
999 Interlocked.Decrement (ref pendingEnds);
1001 req.CheckIfThrowDelayedException();
1005 public int EndReceiveFrom(IAsyncResult result,
1006 ref EndPoint end_point) {
1007 if (disposed && closed)
1008 throw new ObjectDisposedException (GetType ().ToString ());
1011 throw new ArgumentNullException ("result");
1013 SocketAsyncResult req = result as SocketAsyncResult;
1015 throw new ArgumentException ("Invalid IAsyncResult", "result");
1017 if (!result.IsCompleted)
1018 result.AsyncWaitHandle.WaitOne();
1020 Interlocked.Decrement (ref pendingEnds);
1022 req.CheckIfThrowDelayedException();
1023 end_point = req.EndPoint;
1027 public int EndSend(IAsyncResult result) {
1028 if (disposed && closed)
1029 throw new ObjectDisposedException (GetType ().ToString ());
1032 throw new ArgumentNullException ("result");
1034 SocketAsyncResult req = result as SocketAsyncResult;
1036 throw new ArgumentException ("Invalid IAsyncResult", "result");
1038 RemoveReference (req);
1039 if (!result.IsCompleted)
1040 result.AsyncWaitHandle.WaitOne();
1042 Interlocked.Decrement (ref pendingEnds);
1044 req.CheckIfThrowDelayedException();
1048 public int EndSendTo(IAsyncResult result) {
1049 if (disposed && closed)
1050 throw new ObjectDisposedException (GetType ().ToString ());
1053 throw new ArgumentNullException ("result");
1055 SocketAsyncResult req = result as SocketAsyncResult;
1057 throw new ArgumentException ("Invalid IAsyncResult", "result");
1059 if (!result.IsCompleted)
1060 result.AsyncWaitHandle.WaitOne();
1062 Interlocked.Decrement (ref pendingEnds);
1064 req.CheckIfThrowDelayedException();
1068 void CheckIfClose ()
1070 if (Interlocked.CompareExchange (ref closeDelayed, 0, 1) == 1 &&
1071 Interlocked.CompareExchange (ref pendingEnds, 0, 0) == 0) {
1076 Close_internal(socket, out error);
1079 throw new SocketException (error);
1084 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1085 private extern static void GetSocketOption_obj_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, out object obj_val, out int error);
1086 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1087 private extern static void GetSocketOption_arr_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val, out int error);
1089 public object GetSocketOption(SocketOptionLevel level,
1090 SocketOptionName name) {
1094 GetSocketOption_obj_internal(socket, level, name,
1095 out obj_val, out error);
1098 throw new SocketException (error);
1101 if(name==SocketOptionName.Linger) {
1102 return((LingerOption)obj_val);
1103 } else if (name==SocketOptionName.AddMembership ||
1104 name==SocketOptionName.DropMembership) {
1105 return((MulticastOption)obj_val);
1107 return((int)obj_val);
1111 public void GetSocketOption(SocketOptionLevel level,
1112 SocketOptionName name,
1114 int opt_value_len=opt_value.Length;
1117 GetSocketOption_arr_internal(socket, level, name,
1118 ref opt_value, out error);
1121 throw new SocketException (error);
1125 public byte[] GetSocketOption(SocketOptionLevel level,
1126 SocketOptionName name,
1128 byte[] byte_val=new byte[length];
1131 GetSocketOption_arr_internal(socket, level, name,
1132 ref byte_val, out error);
1135 throw new SocketException (error);
1141 // See Socket.IOControl, WSAIoctl documentation in MSDN. The
1142 // common options between UNIX and Winsock are FIONREAD,
1143 // FIONBIO and SIOCATMARK. Anything else will depend on the
1145 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1146 extern static int WSAIoctl (IntPtr sock, int ioctl_code,
1147 byte [] input, byte [] output,
1150 public int IOControl (int ioctl_code, byte [] in_value, byte [] out_value)
1153 throw new ObjectDisposedException (GetType ().ToString ());
1156 int result = WSAIoctl (socket, ioctl_code, in_value,
1157 out_value, out error);
1160 throw new SocketException (error);
1164 throw new InvalidOperationException ("Must use Blocking property instead.");
1169 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1170 private extern static void Listen_internal(IntPtr sock,
1174 public void Listen(int backlog) {
1177 Listen_internal(socket, backlog, out error);
1180 throw new SocketException (error);
1184 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1185 extern static bool Poll_internal (IntPtr socket, SelectMode mode, int timeout, out int error);
1187 public bool Poll (int time_us, SelectMode mode)
1189 if (mode != SelectMode.SelectRead &&
1190 mode != SelectMode.SelectWrite &&
1191 mode != SelectMode.SelectError)
1192 throw new NotSupportedException ("'mode' parameter is not valid.");
1195 bool result = Poll_internal (socket, mode, time_us, out error);
1197 throw new SocketException (error);
1202 public int Receive (byte [] buf)
1205 throw new ArgumentNullException ("buf");
1207 return Receive_nochecks (buf, 0, buf.Length, SocketFlags.None);
1210 public int Receive (byte [] buf, SocketFlags flags)
1213 throw new ArgumentNullException ("buf");
1215 return Receive_nochecks (buf, 0, buf.Length, flags);
1218 public int Receive (byte [] buf, int size, SocketFlags flags)
1221 throw new ArgumentNullException ("buf");
1223 if (size < 0 || size > buf.Length)
1224 throw new ArgumentOutOfRangeException ("size");
1226 return Receive_nochecks (buf, 0, size, flags);
1229 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1230 private extern static int Receive_internal(IntPtr sock,
1237 public int Receive (byte [] buf, int offset, int size, SocketFlags flags)
1240 throw new ArgumentNullException ("buf");
1242 if (offset < 0 || offset > buf.Length)
1243 throw new ArgumentOutOfRangeException ("offset");
1245 if (size < 0 || offset + size > buf.Length)
1246 throw new ArgumentOutOfRangeException ("size");
1248 return Receive_nochecks (buf, offset, size, flags);
1251 int Receive_nochecks (byte [] buf, int offset, int size, SocketFlags flags)
1255 ret = Receive_internal (socket, buf, offset, size, flags, out error);
1259 throw new SocketException (error);
1267 public int ReceiveFrom (byte [] buf, ref EndPoint remote_end)
1270 throw new ArgumentNullException ("buf");
1272 if (remote_end == null)
1273 throw new ArgumentNullException ("remote_end");
1275 return ReceiveFrom_nochecks (buf, 0, buf.Length, SocketFlags.None, ref remote_end);
1278 public int ReceiveFrom (byte [] buf, SocketFlags flags, ref EndPoint remote_end)
1281 throw new ArgumentNullException ("buf");
1283 if (remote_end == null)
1284 throw new ArgumentNullException ("remote_end");
1287 return ReceiveFrom_nochecks (buf, 0, buf.Length, flags, ref remote_end);
1290 public int ReceiveFrom (byte [] buf, int size, SocketFlags flags,
1291 ref EndPoint remote_end)
1294 throw new ArgumentNullException ("buf");
1296 if (remote_end == null)
1297 throw new ArgumentNullException ("remote_end");
1299 if (size < 0 || size > buf.Length)
1300 throw new ArgumentOutOfRangeException ("size");
1302 return ReceiveFrom_nochecks (buf, 0, size, flags, ref remote_end);
1306 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1307 private extern static int RecvFrom_internal(IntPtr sock,
1312 ref SocketAddress sockaddr,
1315 public int ReceiveFrom (byte [] buf, int offset, int size, SocketFlags flags,
1316 ref EndPoint remote_end)
1319 throw new ArgumentNullException ("buf");
1321 if (remote_end == null)
1322 throw new ArgumentNullException ("remote_end");
1324 if (offset < 0 || offset > buf.Length)
1325 throw new ArgumentOutOfRangeException ("offset");
1327 if (size < 0 || offset + size > buf.Length)
1328 throw new ArgumentOutOfRangeException ("size");
1330 return ReceiveFrom_nochecks (buf, offset, size, flags, ref remote_end);
1333 int ReceiveFrom_nochecks (byte [] buf, int offset, int size, SocketFlags flags,
1334 ref EndPoint remote_end)
1336 SocketAddress sockaddr = remote_end.Serialize();
1339 cnt = RecvFrom_internal (socket, buf, offset, size, flags, ref sockaddr, out error);
1343 throw new SocketException (error);
1348 // Stupidly, EndPoint.Create() is an
1350 remote_end = remote_end.Create (sockaddr);
1355 public int Send (byte [] buf)
1358 throw new ArgumentNullException ("buf");
1360 return Send_nochecks (buf, 0, buf.Length, SocketFlags.None);
1363 public int Send (byte [] buf, SocketFlags flags)
1366 throw new ArgumentNullException ("buf");
1368 return Send_nochecks (buf, 0, buf.Length, flags);
1371 public int Send (byte [] buf, int size, SocketFlags flags)
1374 throw new ArgumentNullException ("buf");
1376 if (size < 0 || size > buf.Length)
1377 throw new ArgumentOutOfRangeException ("size");
1379 return Send_nochecks (buf, 0, size, flags);
1382 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1383 private extern static int Send_internal(IntPtr sock,
1384 byte[] buf, int offset,
1389 public int Send (byte [] buf, int offset, int size, SocketFlags flags)
1392 throw new ArgumentNullException ("buffer");
1394 if (offset < 0 || offset > buf.Length)
1395 throw new ArgumentOutOfRangeException ("offset");
1397 if (size < 0 || offset + size > buf.Length)
1398 throw new ArgumentOutOfRangeException ("size");
1400 return Send_nochecks (buf, offset, size, flags);
1403 int Send_nochecks (byte [] buf, int offset, int size, SocketFlags flags)
1410 ret = Send_internal (socket, buf, offset, size, flags, out error);
1414 throw new SocketException (error);
1422 public int SendTo (byte [] buffer, EndPoint remote_end)
1425 throw new ArgumentNullException ("buffer");
1427 if (remote_end == null)
1428 throw new ArgumentNullException ("remote_end");
1430 return SendTo_nochecks (buffer, 0, buffer.Length, SocketFlags.None, remote_end);
1433 public int SendTo (byte [] buffer, SocketFlags flags, EndPoint remote_end)
1436 throw new ArgumentNullException ("buffer");
1438 if (remote_end == null)
1439 throw new ArgumentNullException ("remote_end");
1441 return SendTo_nochecks (buffer, 0, buffer.Length, flags, remote_end);
1444 public int SendTo (byte [] buffer, int size, SocketFlags flags, EndPoint remote_end)
1447 throw new ArgumentNullException ("buffer");
1449 if (remote_end == null)
1450 throw new ArgumentNullException ("remote_end");
1452 if (size < 0 || size > buffer.Length)
1453 throw new ArgumentOutOfRangeException ("size");
1455 return SendTo_nochecks (buffer, 0, size, flags, remote_end);
1459 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1460 private extern static int SendTo_internal(IntPtr sock,
1468 public int SendTo (byte [] buffer, int offset, int size, SocketFlags flags,
1469 EndPoint remote_end)
1472 throw new ArgumentNullException ("buffer");
1474 if (remote_end == null)
1475 throw new ArgumentNullException("remote_end");
1477 if (offset < 0 || offset > buffer.Length)
1478 throw new ArgumentOutOfRangeException ("offset");
1480 if (size < 0 || offset + size > buffer.Length)
1481 throw new ArgumentOutOfRangeException ("size");
1483 return SendTo_nochecks (buffer, offset, size, flags, remote_end);
1486 int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags,
1487 EndPoint remote_end)
1489 SocketAddress sockaddr = remote_end.Serialize ();
1493 ret = SendTo_internal (socket, buffer, offset, size, flags, sockaddr, out error);
1497 throw new SocketException (error);
1505 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1506 private extern static void SetSocketOption_internal (IntPtr socket, SocketOptionLevel level,
1507 SocketOptionName name, object obj_val,
1508 byte [] byte_val, int int_val,
1511 public void SetSocketOption(SocketOptionLevel level,
1512 SocketOptionName name,
1516 SetSocketOption_internal(socket, level, name, null,
1517 opt_value, 0, out error);
1520 throw new SocketException (error);
1524 public void SetSocketOption(SocketOptionLevel level,
1525 SocketOptionName name,
1529 SetSocketOption_internal(socket, level, name, null,
1530 null, opt_value, out error);
1533 throw new SocketException (error);
1537 public void SetSocketOption(SocketOptionLevel level,
1538 SocketOptionName name,
1540 if(opt_value==null) {
1541 throw new ArgumentNullException();
1546 /* Passing a bool as the third parameter to
1547 * SetSocketOption causes this overload to be
1548 * used when in fact we want to pass the value
1549 * to the runtime as an int.
1551 if (opt_value is System.Boolean) {
1552 bool bool_val = (bool) opt_value;
1553 int int_val = (bool_val) ? 1 : 0;
1555 SetSocketOption_internal (socket, level, name, null, null, int_val, out error);
1557 SetSocketOption_internal (socket, level, name, opt_value, null, 0, out error);
1561 throw new SocketException (error);
1565 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1566 private extern static void Shutdown_internal(IntPtr socket, SocketShutdown how, out int error);
1568 public void Shutdown(SocketShutdown how) {
1571 Shutdown_internal(socket, how, out error);
1574 throw new SocketException (error);
1578 public override int GetHashCode ()
1580 return (int) socket;
1583 private bool disposed;
1585 protected virtual void Dispose(bool explicitDisposing) {
1591 if (!explicitDisposing) {
1593 Close_internal (socket, out error);
1596 throw new SocketException (error);
1602 if (Interlocked.CompareExchange (ref pendingEnds, 0, 0) == 0) {
1604 Close_internal (socket, out error);
1607 throw new SocketException (error);
1610 Interlocked.CompareExchange (ref closeDelayed, 1, 0);
1615 void IDisposable.Dispose ()
1618 GC.SuppressFinalize (this);
1625 static Hashtable asyncObjects;
1627 static void KeepReference (object o)
1629 lock (typeof (Socket)) {
1630 if (asyncObjects == null)
1631 asyncObjects = new Hashtable ();
1633 asyncObjects [o] = o;
1637 static void RemoveReference (object o)
1639 lock (typeof (Socket)) {
1640 if (asyncObjects == null)
1643 asyncObjects.Remove (o);
1647 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1648 extern static bool GetSupportsAsync ();
1650 static bool FakeGetSupportsAsync ()
1652 if (Environment.GetEnvironmentVariable ("MONO_ENABLE_SOCKET_AIO") != null)
1653 return GetSupportsAsync ();
1658 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1659 extern static void AsyncReceiveInternal (SocketAsyncResult ares, out int error);
1661 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1662 extern static void AsyncSendInternal (SocketAsyncResult ares, out int error);