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 waithandle=new ManualResetEvent(false);
34 completed_sync=completed=false;
37 public void SetDelayedException (Exception e) {
41 public void CheckIfThrowDelayedException () {
42 if (delayedException != null)
43 throw delayedException;
46 public object AsyncState {
52 public WaitHandle AsyncWaitHandle {
54 if (waithandle == null)
55 waithandle = new ManualResetEvent (completed);
64 public bool CompletedSynchronously {
66 return(completed_sync);
70 public bool IsCompleted {
76 if (waithandle != null && value) {
77 ((ManualResetEvent) waithandle).Set ();
82 public Worker Worker {
92 private sealed class Worker
94 private AsyncCallback callback;
95 private SocketAsyncResult result;
96 private Socket socket;
99 private EndPoint endpoint; // Connect,ReceiveFrom,SendTo
100 private byte[] buffer; // Receive,ReceiveFrom,Send,SendTo
101 private int offset; // Receive,ReceiveFrom,Send,SendTo
102 private int size; // Receive,ReceiveFrom,Send,SendTo
103 private SocketFlags sockflags; // Receive,ReceiveFrom,Send,SendTo
106 private Socket acc_socket;
111 public Worker(Socket req_sock,
112 AsyncCallback req_callback,
113 SocketAsyncResult req_result)
114 : this(req_sock, null, 0, 0, SocketFlags.None,
115 null, req_callback, req_result) {}
118 public Worker(Socket req_sock, EndPoint req_endpoint,
119 AsyncCallback req_callback,
120 SocketAsyncResult req_result)
121 : this(req_sock, null, 0, 0, SocketFlags.None,
122 req_endpoint, req_callback,
125 // For Receive and Send
126 public Worker(Socket req_sock, byte[] req_buffer,
127 int req_offset, int req_size,
128 SocketFlags req_sockflags,
129 AsyncCallback req_callback,
130 SocketAsyncResult req_result)
131 : this(req_sock, req_buffer, req_offset,
132 req_size, req_sockflags, null,
133 req_callback, req_result) {}
135 // For ReceiveFrom and SendTo
136 public Worker(Socket req_sock, byte[] req_buffer,
137 int req_offset, int req_size,
138 SocketFlags req_sockflags,
139 EndPoint req_endpoint,
140 AsyncCallback req_callback,
141 SocketAsyncResult req_result) {
146 sockflags=req_sockflags;
147 endpoint=req_endpoint;
148 callback=req_callback;
153 result.IsCompleted=true;
154 if (callback != null)
158 public void Accept() {
161 acc_socket=socket.Accept();
162 } catch (Exception e) {
163 result.SetDelayedException(e);
169 public void Connect() {
171 if (socket.Blocking) {
173 socket.Connect(endpoint);
174 } catch (Exception e) {
175 result.SetDelayedException(e);
181 SocketException rethrow = null;
183 socket.Connect (endpoint);
184 } catch (SocketException e) {
186 if (e.NativeErrorCode != 10036) {
187 result.SetDelayedException(e);
192 socket.Poll (-1, SelectMode.SelectWrite);
194 socket.Connect (endpoint);
195 } catch (SocketException e2) {
200 result.SetDelayedException(rethrow);
205 public void Receive() {
207 if (socket.Blocking) {
209 total=socket.Receive(buffer, offset,
211 } catch (Exception e) {
212 result.SetDelayedException(e);
218 SocketException rethrow = null;
220 total = socket.Receive (buffer, offset, size, sockflags);
221 } catch (SocketException e) {
223 if (e.NativeErrorCode != 10035) {
224 result.SetDelayedException(e);
229 socket.Poll (-1, SelectMode.SelectRead);
231 total = socket.Receive (buffer, offset, size, sockflags);
232 } catch (SocketException e2) {
237 result.SetDelayedException(rethrow);
242 public void ReceiveFrom() {
244 if (socket.Blocking) {
246 total=socket.ReceiveFrom(buffer,
250 } catch (Exception e) {
251 result.SetDelayedException(e);
257 SocketException rethrow = null;
259 total = socket.ReceiveFrom (buffer, offset, size,
260 sockflags, ref endpoint);
261 } catch (SocketException e) {
263 if (e.NativeErrorCode != 10035) {
264 result.SetDelayedException(e);
269 socket.Poll (-1, SelectMode.SelectRead);
271 total = socket.ReceiveFrom (buffer, offset, size,
272 sockflags, ref endpoint);
273 } catch (SocketException e2) {
278 result.SetDelayedException(rethrow);
285 if (socket.Blocking) {
287 total=socket.Send(buffer, offset, size,
289 } catch (Exception e) {
290 result.SetDelayedException(e);
296 SocketException rethrow = null;
298 total = socket.Send (buffer, offset, size, sockflags);
299 } catch (SocketException e) {
301 if (e.NativeErrorCode != 10035) {
302 result.SetDelayedException(e);
307 socket.Poll (-1, SelectMode.SelectWrite);
309 total = socket.Send (buffer, offset, size, sockflags);
310 } catch (SocketException e2) {
316 result.SetDelayedException(rethrow);
321 public void SendTo() {
323 if (socket.Blocking) {
325 total=socket.SendTo(buffer, offset,
328 } catch (Exception e) {
329 result.SetDelayedException(e);
335 SocketException rethrow = null;
337 total = socket.SendTo (buffer, offset, size,
338 sockflags, endpoint);
339 } catch (SocketException e) {
341 if (e.NativeErrorCode != 10035) {
342 result.SetDelayedException(e);
347 socket.Poll (-1, SelectMode.SelectWrite);
349 total = socket.SendTo (buffer, offset, size,
350 sockflags, endpoint);
351 } catch (SocketException e2) {
357 result.SetDelayedException(rethrow);
362 public EndPoint EndPoint {
368 public Socket Socket {
381 /* the field "socket" is looked up by name by the runtime */
382 private IntPtr socket;
383 private AddressFamily address_family;
384 private SocketType socket_type;
385 private ProtocolType protocol_type;
386 private bool blocking=true;
387 private int pendingEnds;
388 private int closeDelayed;
391 * These two fields are looked up by name by the runtime, don't change
\r
392 * their name without also updating the runtime code.
\r
394 private static int ipv4Supported = -1, ipv6Supported = -1;
396 /* When true, the socket was connected at the time of
397 * the last IO operation
399 private bool connected=false;
400 /* true if we called Close_internal */
403 /* Used in LocalEndPoint and RemoteEndPoint if the
404 * Mono.Posix assembly is available
406 private static object unixendpoint=null;
407 private static Type unixendpointtype=null;
409 [MethodImplAttribute(MethodImplOptions.InternalCall)]
410 private extern static void Select_internal(ref Socket[] read,
415 public static void Select(IList read_list, IList write_list,
416 IList err_list, int time_us) {
417 if(read_list==null &&
420 throw new ArgumentNullException();
423 int read_count = 0, write_count = 0, err_count = 0;
424 Socket[] read_arr = null;
425 Socket[] write_arr = null;
426 Socket[] err_arr = null;
429 read_count=read_list.Count;
432 read_arr=new Socket[read_count];
434 if (write_list!=null)
435 write_count=write_list.Count;
437 if (write_count != 0)
438 write_arr=new Socket[write_count];
441 err_count=err_list.Count;
444 err_arr=new Socket[err_count];
448 if (read_count != 0) {
451 foreach (Socket s in read_list) {
457 if (write_count != 0) {
459 foreach (Socket s in write_list) {
465 if (err_count != 0) {
467 foreach (Socket s in err_list) {
473 Select_internal(ref read_arr, ref write_arr,
474 ref err_arr, time_us);
476 if(read_list!=null) {
478 for(i=0; i<read_arr.Length; i++) {
479 read_list.Add(read_arr[i]);
483 if(write_list!=null) {
485 for(i=0; i<write_arr.Length; i++) {
486 write_list.Add(write_arr[i]);
492 for(i=0; i<err_arr.Length; i++) {
493 err_list.Add(err_arr[i]);
502 ass=Assembly.Load("Mono.Posix");
503 } catch (FileNotFoundException) {
507 unixendpointtype=ass.GetType("Mono.Posix.UnixEndPoint");
509 /* The endpoint Create() method is an instance
512 Type[] arg_types=new Type[1];
513 arg_types[0]=typeof(string);
514 ConstructorInfo cons=unixendpointtype.GetConstructor(arg_types);
516 object[] args=new object[1];
519 unixendpoint=cons.Invoke(args);
522 // private constructor used by Accept, which already
523 // has a socket handle to use
524 private Socket(AddressFamily family, SocketType type,
525 ProtocolType proto, IntPtr sock) {
526 address_family=family;
534 // Creates a new system socket, returning the handle
535 [MethodImplAttribute(MethodImplOptions.InternalCall)]
536 private extern IntPtr Socket_internal(AddressFamily family,
540 public Socket(AddressFamily family, SocketType type,
541 ProtocolType proto) {
542 address_family=family;
546 socket=Socket_internal(family, type, proto);
549 public AddressFamily AddressFamily {
551 return(address_family);
555 // Returns the amount of data waiting to be read on socket
556 [MethodImplAttribute(MethodImplOptions.InternalCall)]
557 private extern static int Available_internal(IntPtr socket);
559 public int Available {
561 if (disposed && closed)
562 throw new ObjectDisposedException (GetType ().ToString ());
564 return(Available_internal(socket));
568 [MethodImplAttribute(MethodImplOptions.InternalCall)]
569 private extern static void Blocking_internal(IntPtr socket,
572 public bool Blocking {
577 Blocking_internal(socket, value);
582 public bool Connected {
588 public IntPtr Handle {
594 // Returns the local endpoint details in addr and port
595 [MethodImplAttribute(MethodImplOptions.InternalCall)]
596 private extern static SocketAddress LocalEndPoint_internal(IntPtr socket);
598 [MonoTODO("Support non-IP endpoints")]
599 public EndPoint LocalEndPoint {
601 if (disposed && closed)
602 throw new ObjectDisposedException (GetType ().ToString ());
606 sa=LocalEndPoint_internal(socket);
608 if(sa.Family==AddressFamily.InterNetwork || sa.Family==AddressFamily.InterNetworkV6) {
609 // Stupidly, EndPoint.Create() is an
611 return new IPEndPoint(0, 0).Create(sa);
612 } else if (sa.Family==AddressFamily.Unix &&
613 unixendpoint!=null) {
614 return((EndPoint)unixendpointtype.InvokeMember("Create", BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public, null, unixendpoint, new object[] {sa}));
616 throw new NotImplementedException();
621 public ProtocolType ProtocolType {
623 return(protocol_type);
627 // Returns the remote endpoint details in addr and port
628 [MethodImplAttribute(MethodImplOptions.InternalCall)]
629 private extern static SocketAddress RemoteEndPoint_internal(IntPtr socket);
631 [MonoTODO("Support non-IP endpoints")]
632 public EndPoint RemoteEndPoint {
634 if (disposed && closed)
635 throw new ObjectDisposedException (GetType ().ToString ());
639 sa=RemoteEndPoint_internal(socket);
641 if(sa.Family==AddressFamily.InterNetwork || sa.Family==AddressFamily.InterNetworkV6 ) {
642 // Stupidly, EndPoint.Create() is an
644 return new IPEndPoint(0, 0).Create(sa);
645 } else if (sa.Family==AddressFamily.Unix &&
646 unixendpoint!=null) {
647 return((EndPoint)unixendpointtype.InvokeMember("Create", BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public, null, unixendpoint, new object[] {sa}));
649 throw new NotImplementedException();
654 public SocketType SocketType {
661 public static bool SupportsIPv4 {
\r
663 CheckProtocolSupport();
\r
664 return ipv4Supported == 1;
\r
668 public static bool SupportsIPv6 {
\r
670 CheckProtocolSupport();
\r
671 return ipv6Supported == 1;
\r
675 internal static bool SupportsIPv4
\r
683 internal static bool SupportsIPv6
\r
692 internal static void CheckProtocolSupport()
694 if(ipv4Supported == -1) {
\r
696 Socket tmp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
\r
706 if(ipv6Supported == -1) {
\r
707 NetConfig config = (NetConfig)System.Configuration.ConfigurationSettings.GetConfig("system.net/settings");
\r
710 ipv6Supported = config.ipv6Enabled?-1:0;
\r
712 if(ipv6Supported != 0) {
\r
714 Socket tmp = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
\r
724 // Creates a new system socket, returning the handle
725 [MethodImplAttribute(MethodImplOptions.InternalCall)]
726 private extern static IntPtr Accept_internal(IntPtr sock);
728 public Socket Accept() {
729 if (disposed && closed)
730 throw new ObjectDisposedException (GetType ().ToString ());
732 IntPtr sock=Accept_internal(socket);
734 return(new Socket(this.AddressFamily, this.SocketType,
735 this.ProtocolType, sock));
738 public IAsyncResult BeginAccept(AsyncCallback callback,
741 if (disposed && closed)
742 throw new ObjectDisposedException (GetType ().ToString ());
744 Interlocked.Increment (ref pendingEnds);
745 SocketAsyncResult req=new SocketAsyncResult(state);
746 Worker worker=new Worker(this, callback, req);
748 Thread child=new Thread(new ThreadStart(worker.Accept));
749 child.IsBackground = true;
754 public IAsyncResult BeginConnect(EndPoint end_point,
755 AsyncCallback callback,
758 if (disposed && closed)
759 throw new ObjectDisposedException (GetType ().ToString ());
761 if (end_point == null)
762 throw new ArgumentNullException ("end_point");
764 Interlocked.Increment (ref pendingEnds);
765 SocketAsyncResult req=new SocketAsyncResult(state);
766 Worker worker=new Worker(this, end_point, callback,
769 Thread child=new Thread(new ThreadStart(worker.Connect));
770 child.IsBackground = true;
775 public IAsyncResult BeginReceive(byte[] buffer, int offset,
777 SocketFlags socket_flags,
778 AsyncCallback callback,
781 if (disposed && closed)
782 throw new ObjectDisposedException (GetType ().ToString ());
785 throw new ArgumentNullException ("buffer");
788 throw new ArgumentOutOfRangeException ("offset must be >= 0");
791 throw new ArgumentOutOfRangeException ("size must be >= 0");
793 if (offset + size > buffer.Length)
794 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
796 Interlocked.Increment (ref pendingEnds);
797 SocketAsyncResult req=new SocketAsyncResult(state);
798 Worker worker=new Worker(this, buffer, offset, size,
799 socket_flags, callback, req);
801 Thread child=new Thread(new ThreadStart(worker.Receive));
802 child.IsBackground = true;
807 public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset,
809 SocketFlags socket_flags,
810 ref EndPoint remote_end,
811 AsyncCallback callback,
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(state);
830 Worker worker=new Worker(this, buffer, offset, size,
831 socket_flags, remote_end,
834 Thread child=new Thread(new ThreadStart(worker.ReceiveFrom));
835 child.IsBackground = true;
840 public IAsyncResult BeginSend(byte[] buffer, int offset,
842 SocketFlags socket_flags,
843 AsyncCallback callback,
845 if (disposed && closed)
846 throw new ObjectDisposedException (GetType ().ToString ());
849 throw new ArgumentNullException ("buffer");
852 throw new ArgumentOutOfRangeException ("offset must be >= 0");
855 throw new ArgumentOutOfRangeException ("size must be >= 0");
857 if (offset + size > buffer.Length)
858 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
860 Interlocked.Increment (ref pendingEnds);
861 SocketAsyncResult req=new SocketAsyncResult(state);
862 Worker worker=new Worker(this, buffer, offset, size,
863 socket_flags, callback, req);
865 Thread child=new Thread(new ThreadStart(worker.Send));
866 child.IsBackground = true;
871 public IAsyncResult BeginSendTo(byte[] buffer, int offset,
873 SocketFlags socket_flags,
875 AsyncCallback callback,
877 if (disposed && closed)
878 throw new ObjectDisposedException (GetType ().ToString ());
881 throw new ArgumentNullException ("buffer");
884 throw new ArgumentOutOfRangeException ("offset must be >= 0");
887 throw new ArgumentOutOfRangeException ("size must be >= 0");
889 if (offset + size > buffer.Length)
890 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
892 Interlocked.Increment (ref pendingEnds);
893 SocketAsyncResult req=new SocketAsyncResult(state);
894 Worker worker=new Worker(this, buffer, offset, size,
895 socket_flags, remote_end,
898 Thread child=new Thread(new ThreadStart(worker.SendTo));
899 child.IsBackground = true;
904 // Creates a new system socket, returning the handle
905 [MethodImplAttribute(MethodImplOptions.InternalCall)]
906 private extern static void Bind_internal(IntPtr sock,
909 public void Bind(EndPoint local_end) {
910 if (disposed && closed)
911 throw new ObjectDisposedException (GetType ().ToString ());
913 if(local_end==null) {
914 throw new ArgumentNullException("local_end");
917 Bind_internal(socket, local_end.Serialize());
921 [MethodImplAttribute(MethodImplOptions.InternalCall)]
922 private extern static void Close_internal(IntPtr socket);
924 public void Close() {
925 ((IDisposable) this).Dispose ();
928 // Connects to the remote address
929 [MethodImplAttribute(MethodImplOptions.InternalCall)]
930 private extern static void Connect_internal(IntPtr sock,
933 public void Connect(EndPoint remote_end) {
934 if (disposed && closed)
935 throw new ObjectDisposedException (GetType ().ToString ());
937 if(remote_end==null) {
938 throw new ArgumentNullException("remote_end");
941 Connect_internal(socket, remote_end.Serialize());
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");
956 if (!result.IsCompleted)
957 result.AsyncWaitHandle.WaitOne();
959 Interlocked.Decrement (ref pendingEnds);
961 req.CheckIfThrowDelayedException();
962 return(req.Worker.Socket);
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");
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");
995 if (!result.IsCompleted)
996 result.AsyncWaitHandle.WaitOne();
998 Interlocked.Decrement (ref pendingEnds);
1000 req.CheckIfThrowDelayedException();
1001 return(req.Worker.Total);
1004 public int EndReceiveFrom(IAsyncResult result,
1005 ref EndPoint end_point) {
1006 if (disposed && closed)
1007 throw new ObjectDisposedException (GetType ().ToString ());
1010 throw new ArgumentNullException ("result");
1012 SocketAsyncResult req = result as SocketAsyncResult;
1014 throw new ArgumentException ("Invalid IAsyncResult");
1016 if (!result.IsCompleted)
1017 result.AsyncWaitHandle.WaitOne();
1019 Interlocked.Decrement (ref pendingEnds);
1021 req.CheckIfThrowDelayedException();
1022 end_point=req.Worker.EndPoint;
1023 return(req.Worker.Total);
1026 public int EndSend(IAsyncResult result) {
1027 if (disposed && closed)
1028 throw new ObjectDisposedException (GetType ().ToString ());
1031 throw new ArgumentNullException ("result");
1033 SocketAsyncResult req = result as SocketAsyncResult;
1035 throw new ArgumentException ("Invalid IAsyncResult");
1037 if (!result.IsCompleted)
1038 result.AsyncWaitHandle.WaitOne();
1040 Interlocked.Decrement (ref pendingEnds);
1042 req.CheckIfThrowDelayedException();
1043 return(req.Worker.Total);
1046 public int EndSendTo(IAsyncResult result) {
1047 if (disposed && closed)
1048 throw new ObjectDisposedException (GetType ().ToString ());
1051 throw new ArgumentNullException ("result");
1053 SocketAsyncResult req = result as SocketAsyncResult;
1055 throw new ArgumentException ("Invalid IAsyncResult");
1057 if (!result.IsCompleted)
1058 result.AsyncWaitHandle.WaitOne();
1060 Interlocked.Decrement (ref pendingEnds);
1062 req.CheckIfThrowDelayedException();
1063 return(req.Worker.Total);
1066 void CheckIfClose ()
1068 if (Interlocked.CompareExchange (ref closeDelayed, 0, 1) == 1 &&
1069 Interlocked.CompareExchange (ref pendingEnds, 0, 0) == 0) {
1071 Close_internal(socket);
1075 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1076 private extern static void GetSocketOption_obj_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, out object obj_val);
1077 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1078 private extern static void GetSocketOption_arr_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val);
1080 public object GetSocketOption(SocketOptionLevel level,
1081 SocketOptionName name) {
1084 GetSocketOption_obj_internal(socket, level, name,
1087 if(name==SocketOptionName.Linger) {
1088 return((LingerOption)obj_val);
1089 } else if (name==SocketOptionName.AddMembership ||
1090 name==SocketOptionName.DropMembership) {
1091 return((MulticastOption)obj_val);
1093 return((int)obj_val);
1097 public void GetSocketOption(SocketOptionLevel level,
1098 SocketOptionName name,
1100 int opt_value_len=opt_value.Length;
1102 GetSocketOption_arr_internal(socket, level, name,
1106 public byte[] GetSocketOption(SocketOptionLevel level,
1107 SocketOptionName name,
1109 byte[] byte_val=new byte[length];
1111 GetSocketOption_arr_internal(socket, level, name,
1117 [MonoTODO("Totally undocumented")]
1118 public int IOControl(int ioctl_code, byte[] in_value,
1120 throw new NotImplementedException();
1123 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1124 private extern static void Listen_internal(IntPtr sock,
1127 public void Listen(int backlog) {
1128 Listen_internal(socket, backlog);
1131 /* The docs for Poll() are a bit lightweight too, but
1132 * it seems to be just a simple wrapper around Select.
1134 public bool Poll(int time_us, SelectMode mode) {
1135 Socket [] socketlist = new Socket []{this};
1139 case SelectMode.SelectError:
1140 Select_internal (ref n, ref n, ref socketlist, time_us);
1142 case SelectMode.SelectRead:
1143 Select_internal (ref socketlist, ref n, ref n, time_us);
1145 case SelectMode.SelectWrite:
1146 Select_internal (ref n, ref socketlist, ref n, time_us);
1149 throw new NotSupportedException();
1152 return (socketlist.Length == 1);
1155 public int Receive(byte[] buf) {
1156 return(Receive(buf, 0, buf.Length, SocketFlags.None));
1159 public int Receive(byte[] buf, SocketFlags flags) {
1160 return(Receive(buf, 0, buf.Length, flags));
1163 public int Receive(byte[] buf, int size, SocketFlags flags) {
1164 return(Receive(buf, 0, size, flags));
1167 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1168 private extern static int Receive_internal(IntPtr sock,
1174 public int Receive(byte[] buf, int offset, int size,
1175 SocketFlags flags) {
1177 throw new ArgumentNullException("buffer is null");
1179 if(offset<0 || offset > buf.Length) {
1180 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
1182 if(size<0 || offset+size > buf.Length) {
1183 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
1189 ret=Receive_internal(socket, buf, offset,
1191 } catch(SocketException) {
1200 public int ReceiveFrom(byte[] buf, ref EndPoint remote_end) {
1201 return(ReceiveFrom(buf, 0, buf.Length,
1202 SocketFlags.None, ref remote_end));
1205 public int ReceiveFrom(byte[] buf, SocketFlags flags,
1206 ref EndPoint remote_end) {
1207 return(ReceiveFrom(buf, 0, buf.Length, flags,
1211 public int ReceiveFrom(byte[] buf, int size, SocketFlags flags,
1212 ref EndPoint remote_end) {
1213 return(ReceiveFrom(buf, 0, size, flags,
1218 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1219 private extern static int RecvFrom_internal(IntPtr sock,
1224 ref SocketAddress sockaddr);
1226 public int ReceiveFrom(byte[] buf, int offset, int size,
1228 ref EndPoint remote_end) {
1230 throw new ArgumentNullException("buffer is null");
1232 if(remote_end==null) {
1233 throw new ArgumentNullException("remote endpoint is null");
1235 if(offset<0 || offset>buf.Length) {
1236 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
1238 if(size<0 || offset+size>buf.Length) {
1239 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
1242 SocketAddress sockaddr=remote_end.Serialize();
1246 count=RecvFrom_internal(socket, buf, offset,
1249 } catch(SocketException) {
1255 // Stupidly, EndPoint.Create() is an
1257 remote_end=remote_end.Create(sockaddr);
1262 public int Send(byte[] buf) {
1263 return(Send(buf, 0, buf.Length, SocketFlags.None));
1266 public int Send(byte[] buf, SocketFlags flags) {
1267 return(Send(buf, 0, buf.Length, flags));
1270 public int Send(byte[] buf, int size, SocketFlags flags) {
1271 return(Send(buf, 0, size, flags));
1274 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1275 private extern static int Send_internal(IntPtr sock,
1276 byte[] buf, int offset,
1280 public int Send (byte[] buf, int offset, int size, SocketFlags flags)
1283 throw new ArgumentNullException ("buffer");
1285 if (offset < 0 || offset > buf.Length)
1286 throw new ArgumentOutOfRangeException ("offset");
1288 if (size < 0 || offset + size > buf.Length)
1289 throw new ArgumentOutOfRangeException ("size");
1297 ret = Send_internal (socket, buf, offset, size, flags);
1298 } catch (SocketException) {
1307 public int SendTo(byte[] buffer, EndPoint remote_end) {
1308 return(SendTo(buffer, 0, buffer.Length,
1309 SocketFlags.None, remote_end));
1312 public int SendTo(byte[] buffer, SocketFlags flags,
1313 EndPoint remote_end) {
1314 return(SendTo(buffer, 0, buffer.Length, flags,
1318 public int SendTo(byte[] buffer, int size, SocketFlags flags,
1319 EndPoint remote_end) {
1320 return(SendTo(buffer, 0, size, flags, remote_end));
1324 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1325 private extern static int SendTo_internal(IntPtr sock,
1332 public int SendTo(byte[] buffer, int offset, int size,
1333 SocketFlags flags, EndPoint remote_end) {
1335 throw new ArgumentNullException("buffer is null");
1337 if(remote_end==null) {
1338 throw new ArgumentNullException("remote endpoint is null");
1340 if(offset<0 || offset>buffer.Length) {
1341 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
1343 if(size<0 || offset+size>buffer.Length) {
1344 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
1347 SocketAddress sockaddr=remote_end.Serialize();
1352 ret=SendTo_internal(socket, buffer, offset,
1353 size, flags, sockaddr);
1355 catch(SocketException) {
1364 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1365 private extern static void SetSocketOption_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, object obj_val, byte[] byte_val, int int_val);
1367 public void SetSocketOption(SocketOptionLevel level,
1368 SocketOptionName name,
1370 SetSocketOption_internal(socket, level, name, null,
1374 public void SetSocketOption(SocketOptionLevel level,
1375 SocketOptionName name,
1377 SetSocketOption_internal(socket, level, name, null,
1381 public void SetSocketOption(SocketOptionLevel level,
1382 SocketOptionName name,
1384 if(opt_value==null) {
1385 throw new ArgumentNullException();
1388 /* Passing a bool as the third parameter to
1389 * SetSocketOption causes this overload to be
1390 * used when in fact we want to pass the value
1391 * to the runtime as an int.
1393 if(opt_value is System.Boolean) {
1394 bool bool_val=(bool)opt_value;
1396 /* Stupid casting rules :-( */
1397 if(bool_val==true) {
1398 SetSocketOption_internal(socket, level,
1402 SetSocketOption_internal(socket, level,
1407 SetSocketOption_internal(socket, level, name,
1408 opt_value, null, 0);
1412 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1413 private extern static void Shutdown_internal(IntPtr socket, SocketShutdown how);
1415 public void Shutdown(SocketShutdown how) {
1416 Shutdown_internal(socket, how);
1419 public override int GetHashCode ()
1421 return (int) socket;
1424 private bool disposed;
1426 protected virtual void Dispose(bool explicitDisposing) {
1427 // Check to see if Dispose has already been called
1428 if(!this.disposed) {
1429 // If this is a call to Dispose,
1430 // dispose all managed resources.
1431 if(explicitDisposing) {
1432 // Free up stuff here
1435 // Release unmanaged resources
1439 if (Interlocked.CompareExchange (ref pendingEnds, 0, 0) == 0) {
1441 Close_internal(socket);
1443 Interlocked.CompareExchange (ref closeDelayed, 1, 0);
1448 void IDisposable.Dispose ()
1451 GC.SuppressFinalize (this);