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 Connect_internal(socket, remote_end.Serialize(), out error);
935 throw new SocketException (error);
941 public Socket EndAccept(IAsyncResult result) {
942 if (disposed && closed)
943 throw new ObjectDisposedException (GetType ().ToString ());
946 throw new ArgumentNullException ("result");
948 SocketAsyncResult req = result as SocketAsyncResult;
950 throw new ArgumentException ("Invalid IAsyncResult", "result");
952 if (!result.IsCompleted)
953 result.AsyncWaitHandle.WaitOne();
955 Interlocked.Decrement (ref pendingEnds);
957 req.CheckIfThrowDelayedException();
961 public void EndConnect(IAsyncResult result) {
962 if (disposed && closed)
963 throw new ObjectDisposedException (GetType ().ToString ());
966 throw new ArgumentNullException ("result");
968 SocketAsyncResult req = result as SocketAsyncResult;
970 throw new ArgumentException ("Invalid IAsyncResult", "result");
972 if (!result.IsCompleted)
973 result.AsyncWaitHandle.WaitOne();
975 Interlocked.Decrement (ref pendingEnds);
977 req.CheckIfThrowDelayedException();
980 public int EndReceive(IAsyncResult result) {
981 if (disposed && closed)
982 throw new ObjectDisposedException (GetType ().ToString ());
985 throw new ArgumentNullException ("result");
987 SocketAsyncResult req = result as SocketAsyncResult;
989 throw new ArgumentException ("Invalid IAsyncResult", "result");
991 RemoveReference (req);
992 if (!result.IsCompleted)
993 result.AsyncWaitHandle.WaitOne();
995 Interlocked.Decrement (ref pendingEnds);
997 req.CheckIfThrowDelayedException();
1001 public int EndReceiveFrom(IAsyncResult result,
1002 ref EndPoint end_point) {
1003 if (disposed && closed)
1004 throw new ObjectDisposedException (GetType ().ToString ());
1007 throw new ArgumentNullException ("result");
1009 SocketAsyncResult req = result as SocketAsyncResult;
1011 throw new ArgumentException ("Invalid IAsyncResult", "result");
1013 if (!result.IsCompleted)
1014 result.AsyncWaitHandle.WaitOne();
1016 Interlocked.Decrement (ref pendingEnds);
1018 req.CheckIfThrowDelayedException();
1019 end_point = req.EndPoint;
1023 public int EndSend(IAsyncResult result) {
1024 if (disposed && closed)
1025 throw new ObjectDisposedException (GetType ().ToString ());
1028 throw new ArgumentNullException ("result");
1030 SocketAsyncResult req = result as SocketAsyncResult;
1032 throw new ArgumentException ("Invalid IAsyncResult", "result");
1034 RemoveReference (req);
1035 if (!result.IsCompleted)
1036 result.AsyncWaitHandle.WaitOne();
1038 Interlocked.Decrement (ref pendingEnds);
1040 req.CheckIfThrowDelayedException();
1044 public int EndSendTo(IAsyncResult result) {
1045 if (disposed && closed)
1046 throw new ObjectDisposedException (GetType ().ToString ());
1049 throw new ArgumentNullException ("result");
1051 SocketAsyncResult req = result as SocketAsyncResult;
1053 throw new ArgumentException ("Invalid IAsyncResult", "result");
1055 if (!result.IsCompleted)
1056 result.AsyncWaitHandle.WaitOne();
1058 Interlocked.Decrement (ref pendingEnds);
1060 req.CheckIfThrowDelayedException();
1064 void CheckIfClose ()
1066 if (Interlocked.CompareExchange (ref closeDelayed, 0, 1) == 1 &&
1067 Interlocked.CompareExchange (ref pendingEnds, 0, 0) == 0) {
1072 Close_internal(socket, out error);
1075 throw new SocketException (error);
1080 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1081 private extern static void GetSocketOption_obj_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, out object obj_val, out int error);
1082 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1083 private extern static void GetSocketOption_arr_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val, out int error);
1085 public object GetSocketOption(SocketOptionLevel level,
1086 SocketOptionName name) {
1090 GetSocketOption_obj_internal(socket, level, name,
1091 out obj_val, out error);
1094 throw new SocketException (error);
1097 if(name==SocketOptionName.Linger) {
1098 return((LingerOption)obj_val);
1099 } else if (name==SocketOptionName.AddMembership ||
1100 name==SocketOptionName.DropMembership) {
1101 return((MulticastOption)obj_val);
1103 return((int)obj_val);
1107 public void GetSocketOption(SocketOptionLevel level,
1108 SocketOptionName name,
1110 int opt_value_len=opt_value.Length;
1113 GetSocketOption_arr_internal(socket, level, name,
1114 ref opt_value, out error);
1117 throw new SocketException (error);
1121 public byte[] GetSocketOption(SocketOptionLevel level,
1122 SocketOptionName name,
1124 byte[] byte_val=new byte[length];
1127 GetSocketOption_arr_internal(socket, level, name,
1128 ref byte_val, out error);
1131 throw new SocketException (error);
1137 // See Socket.IOControl, WSAIoctl documentation in MSDN. The
1138 // common options between UNIX and Winsock are FIONREAD,
1139 // FIONBIO and SIOCATMARK. Anything else will depend on the
1141 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1142 extern static int WSAIoctl (IntPtr sock, int ioctl_code,
1143 byte [] input, byte [] output,
1146 public int IOControl (int ioctl_code, byte [] in_value, byte [] out_value)
1149 throw new ObjectDisposedException (GetType ().ToString ());
1152 int result = WSAIoctl (socket, ioctl_code, in_value,
1153 out_value, out error);
1156 throw new SocketException (error);
1160 throw new InvalidOperationException ("Must use Blocking property instead.");
1165 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1166 private extern static void Listen_internal(IntPtr sock,
1170 public void Listen(int backlog) {
1173 Listen_internal(socket, backlog, out error);
1176 throw new SocketException (error);
1180 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1181 extern static bool Poll_internal (IntPtr socket, SelectMode mode, int timeout, out int error);
1183 public bool Poll (int time_us, SelectMode mode)
1185 if (mode != SelectMode.SelectRead &&
1186 mode != SelectMode.SelectWrite &&
1187 mode != SelectMode.SelectError)
1188 throw new NotSupportedException ("'mode' parameter is not valid.");
1191 bool result = Poll_internal (socket, mode, time_us, out error);
1193 throw new SocketException (error);
1198 public int Receive (byte [] buf)
1201 throw new ArgumentNullException ("buf");
1203 return Receive_nochecks (buf, 0, buf.Length, SocketFlags.None);
1206 public int Receive (byte [] buf, SocketFlags flags)
1209 throw new ArgumentNullException ("buf");
1211 return Receive_nochecks (buf, 0, buf.Length, flags);
1214 public int Receive (byte [] buf, int size, SocketFlags flags)
1217 throw new ArgumentNullException ("buf");
1219 if (size < 0 || size > buf.Length)
1220 throw new ArgumentOutOfRangeException ("size");
1222 return Receive_nochecks (buf, 0, size, flags);
1225 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1226 private extern static int Receive_internal(IntPtr sock,
1233 public int Receive (byte [] buf, int offset, int size, SocketFlags flags)
1236 throw new ArgumentNullException ("buf");
1238 if (offset < 0 || offset > buf.Length)
1239 throw new ArgumentOutOfRangeException ("offset");
1241 if (size < 0 || offset + size > buf.Length)
1242 throw new ArgumentOutOfRangeException ("size");
1244 return Receive_nochecks (buf, offset, size, flags);
1247 int Receive_nochecks (byte [] buf, int offset, int size, SocketFlags flags)
1251 ret = Receive_internal (socket, buf, offset, size, flags, out error);
1255 throw new SocketException (error);
1263 public int ReceiveFrom (byte [] buf, ref EndPoint remote_end)
1266 throw new ArgumentNullException ("buf");
1268 if (remote_end == null)
1269 throw new ArgumentNullException ("remote_end");
1271 return ReceiveFrom_nochecks (buf, 0, buf.Length, SocketFlags.None, ref remote_end);
1274 public int ReceiveFrom (byte [] buf, SocketFlags flags, ref EndPoint remote_end)
1277 throw new ArgumentNullException ("buf");
1279 if (remote_end == null)
1280 throw new ArgumentNullException ("remote_end");
1283 return ReceiveFrom_nochecks (buf, 0, buf.Length, flags, ref remote_end);
1286 public int ReceiveFrom (byte [] buf, int size, SocketFlags flags,
1287 ref EndPoint remote_end)
1290 throw new ArgumentNullException ("buf");
1292 if (remote_end == null)
1293 throw new ArgumentNullException ("remote_end");
1295 if (size < 0 || size > buf.Length)
1296 throw new ArgumentOutOfRangeException ("size");
1298 return ReceiveFrom_nochecks (buf, 0, size, flags, ref remote_end);
1302 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1303 private extern static int RecvFrom_internal(IntPtr sock,
1308 ref SocketAddress sockaddr,
1311 public int ReceiveFrom (byte [] buf, int offset, int size, SocketFlags flags,
1312 ref EndPoint remote_end)
1315 throw new ArgumentNullException ("buf");
1317 if (remote_end == null)
1318 throw new ArgumentNullException ("remote_end");
1320 if (offset < 0 || offset > buf.Length)
1321 throw new ArgumentOutOfRangeException ("offset");
1323 if (size < 0 || offset + size > buf.Length)
1324 throw new ArgumentOutOfRangeException ("size");
1326 return ReceiveFrom_nochecks (buf, offset, size, flags, ref remote_end);
1329 int ReceiveFrom_nochecks (byte [] buf, int offset, int size, SocketFlags flags,
1330 ref EndPoint remote_end)
1332 SocketAddress sockaddr = remote_end.Serialize();
1335 cnt = RecvFrom_internal (socket, buf, offset, size, flags, ref sockaddr, out error);
1339 throw new SocketException (error);
1344 // Stupidly, EndPoint.Create() is an
1346 remote_end = remote_end.Create (sockaddr);
1351 public int Send (byte [] buf)
1354 throw new ArgumentNullException ("buf");
1356 return Send_nochecks (buf, 0, buf.Length, SocketFlags.None);
1359 public int Send (byte [] buf, SocketFlags flags)
1362 throw new ArgumentNullException ("buf");
1364 return Send_nochecks (buf, 0, buf.Length, flags);
1367 public int Send (byte [] buf, int size, SocketFlags flags)
1370 throw new ArgumentNullException ("buf");
1372 if (size < 0 || size > buf.Length)
1373 throw new ArgumentOutOfRangeException ("size");
1375 return Send_nochecks (buf, 0, size, flags);
1378 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1379 private extern static int Send_internal(IntPtr sock,
1380 byte[] buf, int offset,
1385 public int Send (byte [] buf, int offset, int size, SocketFlags flags)
1388 throw new ArgumentNullException ("buffer");
1390 if (offset < 0 || offset > buf.Length)
1391 throw new ArgumentOutOfRangeException ("offset");
1393 if (size < 0 || offset + size > buf.Length)
1394 throw new ArgumentOutOfRangeException ("size");
1396 return Send_nochecks (buf, offset, size, flags);
1399 int Send_nochecks (byte [] buf, int offset, int size, SocketFlags flags)
1406 ret = Send_internal (socket, buf, offset, size, flags, out error);
1410 throw new SocketException (error);
1418 public int SendTo (byte [] buffer, EndPoint remote_end)
1421 throw new ArgumentNullException ("buffer");
1423 if (remote_end == null)
1424 throw new ArgumentNullException ("remote_end");
1426 return SendTo_nochecks (buffer, 0, buffer.Length, SocketFlags.None, remote_end);
1429 public int SendTo (byte [] buffer, SocketFlags flags, EndPoint remote_end)
1432 throw new ArgumentNullException ("buffer");
1434 if (remote_end == null)
1435 throw new ArgumentNullException ("remote_end");
1437 return SendTo_nochecks (buffer, 0, buffer.Length, flags, remote_end);
1440 public int SendTo (byte [] buffer, int size, SocketFlags flags, EndPoint remote_end)
1443 throw new ArgumentNullException ("buffer");
1445 if (remote_end == null)
1446 throw new ArgumentNullException ("remote_end");
1448 if (size < 0 || size > buffer.Length)
1449 throw new ArgumentOutOfRangeException ("size");
1451 return SendTo_nochecks (buffer, 0, size, flags, remote_end);
1455 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1456 private extern static int SendTo_internal(IntPtr sock,
1464 public int SendTo (byte [] buffer, int offset, int size, SocketFlags flags,
1465 EndPoint remote_end)
1468 throw new ArgumentNullException ("buffer");
1470 if (remote_end == null)
1471 throw new ArgumentNullException("remote_end");
1473 if (offset < 0 || offset > buffer.Length)
1474 throw new ArgumentOutOfRangeException ("offset");
1476 if (size < 0 || offset + size > buffer.Length)
1477 throw new ArgumentOutOfRangeException ("size");
1479 return SendTo_nochecks (buffer, offset, size, flags, remote_end);
1482 int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags,
1483 EndPoint remote_end)
1485 SocketAddress sockaddr = remote_end.Serialize ();
1489 ret = SendTo_internal (socket, buffer, offset, size, flags, sockaddr, out error);
1493 throw new SocketException (error);
1501 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1502 private extern static void SetSocketOption_internal (IntPtr socket, SocketOptionLevel level,
1503 SocketOptionName name, object obj_val,
1504 byte [] byte_val, int int_val,
1507 public void SetSocketOption(SocketOptionLevel level,
1508 SocketOptionName name,
1512 SetSocketOption_internal(socket, level, name, null,
1513 opt_value, 0, out error);
1516 throw new SocketException (error);
1520 public void SetSocketOption(SocketOptionLevel level,
1521 SocketOptionName name,
1525 SetSocketOption_internal(socket, level, name, null,
1526 null, opt_value, out error);
1529 throw new SocketException (error);
1533 public void SetSocketOption(SocketOptionLevel level,
1534 SocketOptionName name,
1536 if(opt_value==null) {
1537 throw new ArgumentNullException();
1542 /* Passing a bool as the third parameter to
1543 * SetSocketOption causes this overload to be
1544 * used when in fact we want to pass the value
1545 * to the runtime as an int.
1547 if (opt_value is System.Boolean) {
1548 bool bool_val = (bool) opt_value;
1549 int int_val = (bool_val) ? 1 : 0;
1551 SetSocketOption_internal (socket, level, name, null, null, int_val, out error);
1553 SetSocketOption_internal (socket, level, name, opt_value, null, 0, out error);
1557 throw new SocketException (error);
1561 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1562 private extern static void Shutdown_internal(IntPtr socket, SocketShutdown how, out int error);
1564 public void Shutdown(SocketShutdown how) {
1567 Shutdown_internal(socket, how, out error);
1570 throw new SocketException (error);
1574 public override int GetHashCode ()
1576 return (int) socket;
1579 private bool disposed;
1581 protected virtual void Dispose(bool explicitDisposing) {
1587 if (!explicitDisposing) {
1589 Close_internal (socket, out error);
1592 throw new SocketException (error);
1598 if (Interlocked.CompareExchange (ref pendingEnds, 0, 0) == 0) {
1600 Close_internal (socket, out error);
1603 throw new SocketException (error);
1606 Interlocked.CompareExchange (ref closeDelayed, 1, 0);
1611 void IDisposable.Dispose ()
1614 GC.SuppressFinalize (this);
1621 static Hashtable asyncObjects;
1623 static void KeepReference (object o)
1625 lock (typeof (Socket)) {
1626 if (asyncObjects == null)
1627 asyncObjects = new Hashtable ();
1629 asyncObjects [o] = o;
1633 static void RemoveReference (object o)
1635 lock (typeof (Socket)) {
1636 if (asyncObjects == null)
1639 asyncObjects.Remove (o);
1643 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1644 extern static bool GetSupportsAsync ();
1646 static bool FakeGetSupportsAsync ()
1648 if (Environment.GetEnvironmentVariable ("MONO_ENABLE_SOCKET_AIO") != null)
1649 return GetSupportsAsync ();
1654 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1655 extern static void AsyncReceiveInternal (SocketAsyncResult ares, out int error);
1657 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1658 extern static void AsyncSendInternal (SocketAsyncResult ares, out int error);