1 // System.Net.Sockets.Socket.cs
4 // Phillip Pearson (pp@myelin.co.nz)
5 // Dick Porter <dick@ximian.com>
7 // Copyright (C) 2001, 2002 Phillip Pearson and Ximian, Inc.
8 // http://www.myelin.co.nz
13 using System.Collections;
14 using System.Runtime.CompilerServices;
15 using System.Threading;
16 using System.Reflection;
19 namespace System.Net.Sockets
21 public class Socket : IDisposable
23 private sealed class SocketAsyncResult: IAsyncResult
26 private WaitHandle waithandle;
27 private bool completed_sync, completed;
28 private Worker worker;
29 private Exception delayedException = null;
31 public SocketAsyncResult(object state) {
33 completed_sync=completed=false;
36 public void SetDelayedException (Exception e) {
40 public void CheckIfThrowDelayedException () {
41 if (delayedException != null)
42 throw delayedException;
45 public object AsyncState {
51 public WaitHandle AsyncWaitHandle {
53 if (waithandle == null)
54 waithandle = new ManualResetEvent (completed);
63 public bool CompletedSynchronously {
65 return(completed_sync);
69 public bool IsCompleted {
75 if (waithandle != null && value) {
76 ((ManualResetEvent) waithandle).Set ();
81 public Worker Worker {
91 private sealed class Worker
93 private AsyncCallback callback;
94 private SocketAsyncResult result;
95 private Socket socket;
98 private EndPoint endpoint; // Connect,ReceiveFrom,SendTo
99 private byte[] buffer; // Receive,ReceiveFrom,Send,SendTo
100 private int offset; // Receive,ReceiveFrom,Send,SendTo
101 private int size; // Receive,ReceiveFrom,Send,SendTo
102 private SocketFlags sockflags; // Receive,ReceiveFrom,Send,SendTo
105 private Socket acc_socket;
110 public Worker(Socket req_sock,
111 AsyncCallback req_callback,
112 SocketAsyncResult req_result)
113 : this(req_sock, null, 0, 0, SocketFlags.None,
114 null, req_callback, req_result) {}
117 public Worker(Socket req_sock, EndPoint req_endpoint,
118 AsyncCallback req_callback,
119 SocketAsyncResult req_result)
120 : this(req_sock, null, 0, 0, SocketFlags.None,
121 req_endpoint, req_callback,
124 // For Receive and Send
125 public Worker(Socket req_sock, byte[] req_buffer,
126 int req_offset, int req_size,
127 SocketFlags req_sockflags,
128 AsyncCallback req_callback,
129 SocketAsyncResult req_result)
130 : this(req_sock, req_buffer, req_offset,
131 req_size, req_sockflags, null,
132 req_callback, req_result) {}
134 // For ReceiveFrom and SendTo
135 public Worker(Socket req_sock, byte[] req_buffer,
136 int req_offset, int req_size,
137 SocketFlags req_sockflags,
138 EndPoint req_endpoint,
139 AsyncCallback req_callback,
140 SocketAsyncResult req_result) {
145 sockflags=req_sockflags;
146 endpoint=req_endpoint;
147 callback=req_callback;
152 result.IsCompleted=true;
153 if (callback != null)
157 public void Accept() {
160 acc_socket=socket.Accept();
161 } catch (Exception e) {
162 result.SetDelayedException(e);
168 public void Connect() {
170 if (socket.Blocking) {
172 socket.Connect(endpoint);
173 } catch (Exception e) {
174 result.SetDelayedException(e);
180 SocketException rethrow = null;
182 socket.Connect (endpoint);
183 } catch (SocketException e) {
185 if (e.NativeErrorCode != 10036) {
186 result.SetDelayedException(e);
191 socket.Poll (-1, SelectMode.SelectWrite);
193 socket.Connect (endpoint);
194 } catch (SocketException e2) {
199 result.SetDelayedException(rethrow);
204 public void Receive() {
206 if (socket.Blocking) {
208 total=socket.Receive(buffer, offset,
210 } catch (Exception e) {
211 result.SetDelayedException(e);
217 SocketException rethrow = null;
219 total = socket.Receive (buffer, offset, size, sockflags);
220 } catch (SocketException e) {
222 if (e.NativeErrorCode != 10035) {
223 result.SetDelayedException(e);
228 socket.Poll (-1, SelectMode.SelectRead);
230 total = socket.Receive (buffer, offset, size, sockflags);
231 } catch (SocketException e2) {
236 result.SetDelayedException(rethrow);
241 public void ReceiveFrom() {
243 if (socket.Blocking) {
245 total=socket.ReceiveFrom(buffer,
249 } catch (Exception e) {
250 result.SetDelayedException(e);
256 SocketException rethrow = null;
258 total = socket.ReceiveFrom (buffer, offset, size,
259 sockflags, ref endpoint);
260 } catch (SocketException e) {
262 if (e.NativeErrorCode != 10035) {
263 result.SetDelayedException(e);
268 socket.Poll (-1, SelectMode.SelectRead);
270 total = socket.ReceiveFrom (buffer, offset, size,
271 sockflags, ref endpoint);
272 } catch (SocketException e2) {
277 result.SetDelayedException(rethrow);
284 if (socket.Blocking) {
286 total=socket.Send(buffer, offset, size,
288 } catch (Exception e) {
289 result.SetDelayedException(e);
295 SocketException rethrow = null;
297 total = socket.Send (buffer, offset, size, sockflags);
298 } catch (SocketException e) {
300 if (e.NativeErrorCode != 10035) {
301 result.SetDelayedException(e);
306 socket.Poll (-1, SelectMode.SelectWrite);
308 total = socket.Send (buffer, offset, size, sockflags);
309 } catch (SocketException e2) {
315 result.SetDelayedException(rethrow);
320 public void SendTo() {
322 if (socket.Blocking) {
324 total=socket.SendTo(buffer, offset,
327 } catch (Exception e) {
328 result.SetDelayedException(e);
334 SocketException rethrow = null;
336 total = socket.SendTo (buffer, offset, size,
337 sockflags, endpoint);
338 } catch (SocketException e) {
340 if (e.NativeErrorCode != 10035) {
341 result.SetDelayedException(e);
346 socket.Poll (-1, SelectMode.SelectWrite);
348 total = socket.SendTo (buffer, offset, size,
349 sockflags, endpoint);
350 } catch (SocketException e2) {
356 result.SetDelayedException(rethrow);
361 public EndPoint EndPoint {
367 public Socket Socket {
380 /* the field "socket" is looked up by name by the runtime */
381 private IntPtr socket;
382 private AddressFamily address_family;
383 private SocketType socket_type;
384 private ProtocolType protocol_type;
385 private bool blocking=true;
386 private int pendingEnds;
387 private int closeDelayed;
390 * These two fields are looked up by name by the runtime, don't change
\r
391 * their name without also updating the runtime code.
\r
393 private static int ipv4Supported = -1, ipv6Supported = -1;
395 /* When true, the socket was connected at the time of
396 * the last IO operation
398 private bool connected=false;
399 /* true if we called Close_internal */
402 /* Used in LocalEndPoint and RemoteEndPoint if the
403 * Mono.Posix assembly is available
405 private static object unixendpoint=null;
406 private static Type unixendpointtype=null;
408 [MethodImplAttribute(MethodImplOptions.InternalCall)]
409 private extern static void Select_internal(ref Socket[] read,
414 public static void Select(IList read_list, IList write_list,
415 IList err_list, int time_us) {
416 if(read_list==null &&
419 throw new ArgumentNullException();
422 int read_count = 0, write_count = 0, err_count = 0;
423 Socket[] read_arr = null;
424 Socket[] write_arr = null;
425 Socket[] err_arr = null;
428 read_count=read_list.Count;
431 read_arr=new Socket[read_count];
433 if (write_list!=null)
434 write_count=write_list.Count;
436 if (write_count != 0)
437 write_arr=new Socket[write_count];
440 err_count=err_list.Count;
443 err_arr=new Socket[err_count];
447 if (read_count != 0) {
450 foreach (Socket s in read_list) {
456 if (write_count != 0) {
458 foreach (Socket s in write_list) {
464 if (err_count != 0) {
466 foreach (Socket s in err_list) {
472 Select_internal(ref read_arr, ref write_arr,
473 ref err_arr, time_us);
475 if(read_list!=null) {
477 for(i=0; i<read_arr.Length; i++) {
478 read_list.Add(read_arr[i]);
482 if(write_list!=null) {
484 for(i=0; i<write_arr.Length; i++) {
485 write_list.Add(write_arr[i]);
491 for(i=0; i<err_arr.Length; i++) {
492 err_list.Add(err_arr[i]);
501 ass=Assembly.Load("Mono.Posix");
502 } catch (FileNotFoundException) {
506 unixendpointtype=ass.GetType("Mono.Posix.UnixEndPoint");
508 /* The endpoint Create() method is an instance
511 Type[] arg_types=new Type[1];
512 arg_types[0]=typeof(string);
513 ConstructorInfo cons=unixendpointtype.GetConstructor(arg_types);
515 object[] args=new object[1];
518 unixendpoint=cons.Invoke(args);
521 // private constructor used by Accept, which already
522 // has a socket handle to use
523 private Socket(AddressFamily family, SocketType type,
524 ProtocolType proto, IntPtr sock) {
525 address_family=family;
533 // Creates a new system socket, returning the handle
534 [MethodImplAttribute(MethodImplOptions.InternalCall)]
535 private extern IntPtr Socket_internal(AddressFamily family,
539 public Socket(AddressFamily family, SocketType type,
540 ProtocolType proto) {
541 address_family=family;
545 socket=Socket_internal(family, type, proto);
548 public AddressFamily AddressFamily {
550 return(address_family);
554 // Returns the amount of data waiting to be read on socket
555 [MethodImplAttribute(MethodImplOptions.InternalCall)]
556 private extern static int Available_internal(IntPtr socket);
558 public int Available {
560 if (disposed && closed)
561 throw new ObjectDisposedException (GetType ().ToString ());
563 return(Available_internal(socket));
567 [MethodImplAttribute(MethodImplOptions.InternalCall)]
568 private extern static void Blocking_internal(IntPtr socket,
571 public bool Blocking {
576 Blocking_internal(socket, value);
581 public bool Connected {
587 public IntPtr Handle {
593 // Returns the local endpoint details in addr and port
594 [MethodImplAttribute(MethodImplOptions.InternalCall)]
595 private extern static SocketAddress LocalEndPoint_internal(IntPtr socket);
597 [MonoTODO("Support non-IP endpoints")]
598 public EndPoint LocalEndPoint {
600 if (disposed && closed)
601 throw new ObjectDisposedException (GetType ().ToString ());
605 sa=LocalEndPoint_internal(socket);
607 if(sa.Family==AddressFamily.InterNetwork || sa.Family==AddressFamily.InterNetworkV6) {
608 // Stupidly, EndPoint.Create() is an
610 return new IPEndPoint(0, 0).Create(sa);
611 } else if (sa.Family==AddressFamily.Unix &&
612 unixendpoint!=null) {
613 return((EndPoint)unixendpointtype.InvokeMember("Create", BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public, null, unixendpoint, new object[] {sa}));
615 throw new NotImplementedException();
620 public ProtocolType ProtocolType {
622 return(protocol_type);
626 // Returns the remote endpoint details in addr and port
627 [MethodImplAttribute(MethodImplOptions.InternalCall)]
628 private extern static SocketAddress RemoteEndPoint_internal(IntPtr socket);
630 [MonoTODO("Support non-IP endpoints")]
631 public EndPoint RemoteEndPoint {
633 if (disposed && closed)
634 throw new ObjectDisposedException (GetType ().ToString ());
638 sa=RemoteEndPoint_internal(socket);
640 if(sa.Family==AddressFamily.InterNetwork || sa.Family==AddressFamily.InterNetworkV6 ) {
641 // Stupidly, EndPoint.Create() is an
643 return new IPEndPoint(0, 0).Create(sa);
644 } else if (sa.Family==AddressFamily.Unix &&
645 unixendpoint!=null) {
646 return((EndPoint)unixendpointtype.InvokeMember("Create", BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public, null, unixendpoint, new object[] {sa}));
648 throw new NotImplementedException();
653 public SocketType SocketType {
660 public static bool SupportsIPv4 {
\r
662 CheckProtocolSupport();
\r
663 return ipv4Supported == 1;
\r
667 public static bool SupportsIPv6 {
\r
669 CheckProtocolSupport();
\r
670 return ipv6Supported == 1;
\r
674 internal static bool SupportsIPv4
\r
682 internal static bool SupportsIPv6
\r
691 internal static void CheckProtocolSupport()
693 if(ipv4Supported == -1) {
\r
695 Socket tmp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
\r
705 if(ipv6Supported == -1) {
\r
706 NetConfig config = (NetConfig)System.Configuration.ConfigurationSettings.GetConfig("system.net/settings");
\r
709 ipv6Supported = config.ipv6Enabled?-1:0;
\r
711 if(ipv6Supported != 0) {
\r
713 Socket tmp = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
\r
723 // Creates a new system socket, returning the handle
724 [MethodImplAttribute(MethodImplOptions.InternalCall)]
725 private extern static IntPtr Accept_internal(IntPtr sock);
727 public Socket Accept() {
728 if (disposed && closed)
729 throw new ObjectDisposedException (GetType ().ToString ());
731 IntPtr sock=Accept_internal(socket);
733 return(new Socket(this.AddressFamily, this.SocketType,
734 this.ProtocolType, sock));
737 public IAsyncResult BeginAccept(AsyncCallback callback,
740 if (disposed && closed)
741 throw new ObjectDisposedException (GetType ().ToString ());
743 Interlocked.Increment (ref pendingEnds);
744 SocketAsyncResult req=new SocketAsyncResult(state);
745 Worker worker=new Worker(this, callback, req);
747 Thread child=new Thread(new ThreadStart(worker.Accept));
748 child.IsBackground = true;
753 public IAsyncResult BeginConnect(EndPoint end_point,
754 AsyncCallback callback,
757 if (disposed && closed)
758 throw new ObjectDisposedException (GetType ().ToString ());
760 if (end_point == null)
761 throw new ArgumentNullException ("end_point");
763 Interlocked.Increment (ref pendingEnds);
764 SocketAsyncResult req=new SocketAsyncResult(state);
765 Worker worker=new Worker(this, end_point, callback,
768 Thread child=new Thread(new ThreadStart(worker.Connect));
769 child.IsBackground = true;
774 public IAsyncResult BeginReceive(byte[] buffer, int offset,
776 SocketFlags socket_flags,
777 AsyncCallback callback,
780 if (disposed && closed)
781 throw new ObjectDisposedException (GetType ().ToString ());
784 throw new ArgumentNullException ("buffer");
787 throw new ArgumentOutOfRangeException ("offset must be >= 0");
790 throw new ArgumentOutOfRangeException ("size must be >= 0");
792 if (offset + size > buffer.Length)
793 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
795 Interlocked.Increment (ref pendingEnds);
796 SocketAsyncResult req=new SocketAsyncResult(state);
797 Worker worker=new Worker(this, buffer, offset, size,
798 socket_flags, callback, req);
800 Thread child=new Thread(new ThreadStart(worker.Receive));
801 child.IsBackground = true;
806 public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset,
808 SocketFlags socket_flags,
809 ref EndPoint remote_end,
810 AsyncCallback callback,
812 if (disposed && closed)
813 throw new ObjectDisposedException (GetType ().ToString ());
816 throw new ArgumentNullException ("buffer");
819 throw new ArgumentOutOfRangeException ("offset must be >= 0");
822 throw new ArgumentOutOfRangeException ("size must be >= 0");
824 if (offset + size > buffer.Length)
825 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
827 Interlocked.Increment (ref pendingEnds);
828 SocketAsyncResult req=new SocketAsyncResult(state);
829 Worker worker=new Worker(this, buffer, offset, size,
830 socket_flags, remote_end,
833 Thread child=new Thread(new ThreadStart(worker.ReceiveFrom));
834 child.IsBackground = true;
839 public IAsyncResult BeginSend(byte[] buffer, int offset,
841 SocketFlags socket_flags,
842 AsyncCallback callback,
844 if (disposed && closed)
845 throw new ObjectDisposedException (GetType ().ToString ());
848 throw new ArgumentNullException ("buffer");
851 throw new ArgumentOutOfRangeException ("offset must be >= 0");
854 throw new ArgumentOutOfRangeException ("size must be >= 0");
856 if (offset + size > buffer.Length)
857 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
859 Interlocked.Increment (ref pendingEnds);
860 SocketAsyncResult req=new SocketAsyncResult(state);
861 Worker worker=new Worker(this, buffer, offset, size,
862 socket_flags, callback, req);
864 Thread child=new Thread(new ThreadStart(worker.Send));
865 child.IsBackground = true;
870 public IAsyncResult BeginSendTo(byte[] buffer, int offset,
872 SocketFlags socket_flags,
874 AsyncCallback callback,
876 if (disposed && closed)
877 throw new ObjectDisposedException (GetType ().ToString ());
880 throw new ArgumentNullException ("buffer");
883 throw new ArgumentOutOfRangeException ("offset must be >= 0");
886 throw new ArgumentOutOfRangeException ("size must be >= 0");
888 if (offset + size > buffer.Length)
889 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
891 Interlocked.Increment (ref pendingEnds);
892 SocketAsyncResult req=new SocketAsyncResult(state);
893 Worker worker=new Worker(this, buffer, offset, size,
894 socket_flags, remote_end,
897 Thread child=new Thread(new ThreadStart(worker.SendTo));
898 child.IsBackground = true;
903 // Creates a new system socket, returning the handle
904 [MethodImplAttribute(MethodImplOptions.InternalCall)]
905 private extern static void Bind_internal(IntPtr sock,
908 public void Bind(EndPoint local_end) {
909 if (disposed && closed)
910 throw new ObjectDisposedException (GetType ().ToString ());
912 if(local_end==null) {
913 throw new ArgumentNullException("local_end");
916 Bind_internal(socket, local_end.Serialize());
920 [MethodImplAttribute(MethodImplOptions.InternalCall)]
921 private extern static void Close_internal(IntPtr socket);
923 public void Close() {
924 ((IDisposable) this).Dispose ();
927 // Connects to the remote address
928 [MethodImplAttribute(MethodImplOptions.InternalCall)]
929 private extern static void Connect_internal(IntPtr sock,
932 public void Connect(EndPoint remote_end) {
933 if (disposed && closed)
934 throw new ObjectDisposedException (GetType ().ToString ());
936 if(remote_end==null) {
937 throw new ArgumentNullException("remote_end");
940 Connect_internal(socket, remote_end.Serialize());
944 public Socket EndAccept(IAsyncResult result) {
945 if (disposed && closed)
946 throw new ObjectDisposedException (GetType ().ToString ());
949 throw new ArgumentNullException ("result");
951 SocketAsyncResult req = result as SocketAsyncResult;
953 throw new ArgumentException ("Invalid IAsyncResult");
955 if (!result.IsCompleted)
956 result.AsyncWaitHandle.WaitOne();
958 Interlocked.Decrement (ref pendingEnds);
960 req.CheckIfThrowDelayedException();
961 return(req.Worker.Socket);
964 public void EndConnect(IAsyncResult result) {
965 if (disposed && closed)
966 throw new ObjectDisposedException (GetType ().ToString ());
969 throw new ArgumentNullException ("result");
971 SocketAsyncResult req = result as SocketAsyncResult;
973 throw new ArgumentException ("Invalid IAsyncResult");
975 if (!result.IsCompleted)
976 result.AsyncWaitHandle.WaitOne();
978 Interlocked.Decrement (ref pendingEnds);
980 req.CheckIfThrowDelayedException();
983 public int EndReceive(IAsyncResult result) {
984 if (disposed && closed)
985 throw new ObjectDisposedException (GetType ().ToString ());
988 throw new ArgumentNullException ("result");
990 SocketAsyncResult req = result as SocketAsyncResult;
992 throw new ArgumentException ("Invalid IAsyncResult");
994 if (!result.IsCompleted)
995 result.AsyncWaitHandle.WaitOne();
997 Interlocked.Decrement (ref pendingEnds);
999 req.CheckIfThrowDelayedException();
1000 return(req.Worker.Total);
1003 public int EndReceiveFrom(IAsyncResult result,
1004 ref EndPoint end_point) {
1005 if (disposed && closed)
1006 throw new ObjectDisposedException (GetType ().ToString ());
1009 throw new ArgumentNullException ("result");
1011 SocketAsyncResult req = result as SocketAsyncResult;
1013 throw new ArgumentException ("Invalid IAsyncResult");
1015 if (!result.IsCompleted)
1016 result.AsyncWaitHandle.WaitOne();
1018 Interlocked.Decrement (ref pendingEnds);
1020 req.CheckIfThrowDelayedException();
1021 end_point=req.Worker.EndPoint;
1022 return(req.Worker.Total);
1025 public int EndSend(IAsyncResult result) {
1026 if (disposed && closed)
1027 throw new ObjectDisposedException (GetType ().ToString ());
1030 throw new ArgumentNullException ("result");
1032 SocketAsyncResult req = result as SocketAsyncResult;
1034 throw new ArgumentException ("Invalid IAsyncResult");
1036 if (!result.IsCompleted)
1037 result.AsyncWaitHandle.WaitOne();
1039 Interlocked.Decrement (ref pendingEnds);
1041 req.CheckIfThrowDelayedException();
1042 return(req.Worker.Total);
1045 public int EndSendTo(IAsyncResult result) {
1046 if (disposed && closed)
1047 throw new ObjectDisposedException (GetType ().ToString ());
1050 throw new ArgumentNullException ("result");
1052 SocketAsyncResult req = result as SocketAsyncResult;
1054 throw new ArgumentException ("Invalid IAsyncResult");
1056 if (!result.IsCompleted)
1057 result.AsyncWaitHandle.WaitOne();
1059 Interlocked.Decrement (ref pendingEnds);
1061 req.CheckIfThrowDelayedException();
1062 return(req.Worker.Total);
1065 void CheckIfClose ()
1067 if (Interlocked.CompareExchange (ref closeDelayed, 0, 1) == 1 &&
1068 Interlocked.CompareExchange (ref pendingEnds, 0, 0) == 0) {
1070 Close_internal(socket);
1074 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1075 private extern static void GetSocketOption_obj_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, out object obj_val);
1076 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1077 private extern static void GetSocketOption_arr_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val);
1079 public object GetSocketOption(SocketOptionLevel level,
1080 SocketOptionName name) {
1083 GetSocketOption_obj_internal(socket, level, name,
1086 if(name==SocketOptionName.Linger) {
1087 return((LingerOption)obj_val);
1088 } else if (name==SocketOptionName.AddMembership ||
1089 name==SocketOptionName.DropMembership) {
1090 return((MulticastOption)obj_val);
1092 return((int)obj_val);
1096 public void GetSocketOption(SocketOptionLevel level,
1097 SocketOptionName name,
1099 int opt_value_len=opt_value.Length;
1101 GetSocketOption_arr_internal(socket, level, name,
1105 public byte[] GetSocketOption(SocketOptionLevel level,
1106 SocketOptionName name,
1108 byte[] byte_val=new byte[length];
1110 GetSocketOption_arr_internal(socket, level, name,
1116 [MonoTODO("Totally undocumented")]
1117 public int IOControl(int ioctl_code, byte[] in_value,
1119 throw new NotImplementedException();
1122 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1123 private extern static void Listen_internal(IntPtr sock,
1126 public void Listen(int backlog) {
1127 Listen_internal(socket, backlog);
1130 /* The docs for Poll() are a bit lightweight too, but
1131 * it seems to be just a simple wrapper around Select.
1133 public bool Poll(int time_us, SelectMode mode) {
1134 Socket [] socketlist = new Socket []{this};
1138 case SelectMode.SelectError:
1139 Select_internal (ref n, ref n, ref socketlist, time_us);
1141 case SelectMode.SelectRead:
1142 Select_internal (ref socketlist, ref n, ref n, time_us);
1144 case SelectMode.SelectWrite:
1145 Select_internal (ref n, ref socketlist, ref n, time_us);
1148 throw new NotSupportedException();
1151 return (socketlist.Length == 1);
1154 public int Receive(byte[] buf) {
1155 return(Receive(buf, 0, buf.Length, SocketFlags.None));
1158 public int Receive(byte[] buf, SocketFlags flags) {
1159 return(Receive(buf, 0, buf.Length, flags));
1162 public int Receive(byte[] buf, int size, SocketFlags flags) {
1163 return(Receive(buf, 0, size, flags));
1166 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1167 private extern static int Receive_internal(IntPtr sock,
1173 public int Receive(byte[] buf, int offset, int size,
1174 SocketFlags flags) {
1176 throw new ArgumentNullException("buffer is null");
1178 if(offset<0 || offset > buf.Length) {
1179 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
1181 if(size<0 || offset+size > buf.Length) {
1182 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
1188 ret=Receive_internal(socket, buf, offset,
1190 } catch(SocketException) {
1199 public int ReceiveFrom(byte[] buf, ref EndPoint remote_end) {
1200 return(ReceiveFrom(buf, 0, buf.Length,
1201 SocketFlags.None, ref remote_end));
1204 public int ReceiveFrom(byte[] buf, SocketFlags flags,
1205 ref EndPoint remote_end) {
1206 return(ReceiveFrom(buf, 0, buf.Length, flags,
1210 public int ReceiveFrom(byte[] buf, int size, SocketFlags flags,
1211 ref EndPoint remote_end) {
1212 return(ReceiveFrom(buf, 0, size, flags,
1217 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1218 private extern static int RecvFrom_internal(IntPtr sock,
1223 ref SocketAddress sockaddr);
1225 public int ReceiveFrom(byte[] buf, int offset, int size,
1227 ref EndPoint remote_end) {
1229 throw new ArgumentNullException("buffer is null");
1231 if(remote_end==null) {
1232 throw new ArgumentNullException("remote endpoint is null");
1234 if(offset<0 || offset>buf.Length) {
1235 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
1237 if(size<0 || offset+size>buf.Length) {
1238 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
1241 SocketAddress sockaddr=remote_end.Serialize();
1245 count=RecvFrom_internal(socket, buf, offset,
1248 } catch(SocketException) {
1254 // Stupidly, EndPoint.Create() is an
1256 remote_end=remote_end.Create(sockaddr);
1261 public int Send(byte[] buf) {
1262 return(Send(buf, 0, buf.Length, SocketFlags.None));
1265 public int Send(byte[] buf, SocketFlags flags) {
1266 return(Send(buf, 0, buf.Length, flags));
1269 public int Send(byte[] buf, int size, SocketFlags flags) {
1270 return(Send(buf, 0, size, flags));
1273 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1274 private extern static int Send_internal(IntPtr sock,
1275 byte[] buf, int offset,
1279 public int Send (byte[] buf, int offset, int size, SocketFlags flags)
1282 throw new ArgumentNullException ("buffer");
1284 if (offset < 0 || offset > buf.Length)
1285 throw new ArgumentOutOfRangeException ("offset");
1287 if (size < 0 || offset + size > buf.Length)
1288 throw new ArgumentOutOfRangeException ("size");
1296 ret = Send_internal (socket, buf, offset, size, flags);
1297 } catch (SocketException) {
1306 public int SendTo(byte[] buffer, EndPoint remote_end) {
1307 return(SendTo(buffer, 0, buffer.Length,
1308 SocketFlags.None, remote_end));
1311 public int SendTo(byte[] buffer, SocketFlags flags,
1312 EndPoint remote_end) {
1313 return(SendTo(buffer, 0, buffer.Length, flags,
1317 public int SendTo(byte[] buffer, int size, SocketFlags flags,
1318 EndPoint remote_end) {
1319 return(SendTo(buffer, 0, size, flags, remote_end));
1323 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1324 private extern static int SendTo_internal(IntPtr sock,
1331 public int SendTo(byte[] buffer, int offset, int size,
1332 SocketFlags flags, EndPoint remote_end) {
1334 throw new ArgumentNullException("buffer is null");
1336 if(remote_end==null) {
1337 throw new ArgumentNullException("remote endpoint is null");
1339 if(offset<0 || offset>buffer.Length) {
1340 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
1342 if(size<0 || offset+size>buffer.Length) {
1343 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
1346 SocketAddress sockaddr=remote_end.Serialize();
1351 ret=SendTo_internal(socket, buffer, offset,
1352 size, flags, sockaddr);
1354 catch(SocketException) {
1363 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1364 private extern static void SetSocketOption_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, object obj_val, byte[] byte_val, int int_val);
1366 public void SetSocketOption(SocketOptionLevel level,
1367 SocketOptionName name,
1369 SetSocketOption_internal(socket, level, name, null,
1373 public void SetSocketOption(SocketOptionLevel level,
1374 SocketOptionName name,
1376 SetSocketOption_internal(socket, level, name, null,
1380 public void SetSocketOption(SocketOptionLevel level,
1381 SocketOptionName name,
1383 if(opt_value==null) {
1384 throw new ArgumentNullException();
1387 /* Passing a bool as the third parameter to
1388 * SetSocketOption causes this overload to be
1389 * used when in fact we want to pass the value
1390 * to the runtime as an int.
1392 if(opt_value is System.Boolean) {
1393 bool bool_val=(bool)opt_value;
1395 /* Stupid casting rules :-( */
1396 if(bool_val==true) {
1397 SetSocketOption_internal(socket, level,
1401 SetSocketOption_internal(socket, level,
1406 SetSocketOption_internal(socket, level, name,
1407 opt_value, null, 0);
1411 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1412 private extern static void Shutdown_internal(IntPtr socket, SocketShutdown how);
1414 public void Shutdown(SocketShutdown how) {
1415 Shutdown_internal(socket, how);
1418 public override int GetHashCode ()
1420 return (int) socket;
1423 private bool disposed;
1425 protected virtual void Dispose(bool explicitDisposing) {
1426 // Check to see if Dispose has already been called
1427 if(!this.disposed) {
1428 // If this is a call to Dispose,
1429 // dispose all managed resources.
1430 if(explicitDisposing) {
1431 // Free up stuff here
1434 // Release unmanaged resources
1438 if (Interlocked.CompareExchange (ref pendingEnds, 0, 0) == 0) {
1440 Close_internal(socket);
1442 Interlocked.CompareExchange (ref closeDelayed, 1, 0);
1447 void IDisposable.Dispose ()
1450 GC.SuppressFinalize (this);