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 {
61 public bool CompletedSynchronously {
63 return(completed_sync);
67 public bool IsCompleted {
76 public Worker Worker {
86 private sealed class Worker
88 private AsyncCallback callback;
89 private SocketAsyncResult result;
90 private Socket socket;
93 private EndPoint endpoint; // Connect,ReceiveFrom,SendTo
94 private byte[] buffer; // Receive,ReceiveFrom,Send,SendTo
95 private int offset; // Receive,ReceiveFrom,Send,SendTo
96 private int size; // Receive,ReceiveFrom,Send,SendTo
97 private SocketFlags sockflags; // Receive,ReceiveFrom,Send,SendTo
100 private Socket acc_socket;
105 public Worker(Socket req_sock,
106 AsyncCallback req_callback,
107 SocketAsyncResult req_result)
108 : this(req_sock, null, 0, 0, SocketFlags.None,
109 null, req_callback, req_result) {}
112 public Worker(Socket req_sock, EndPoint req_endpoint,
113 AsyncCallback req_callback,
114 SocketAsyncResult req_result)
115 : this(req_sock, null, 0, 0, SocketFlags.None,
116 req_endpoint, req_callback,
119 // For Receive and Send
120 public Worker(Socket req_sock, byte[] req_buffer,
121 int req_offset, int req_size,
122 SocketFlags req_sockflags,
123 AsyncCallback req_callback,
124 SocketAsyncResult req_result)
125 : this(req_sock, req_buffer, req_offset,
126 req_size, req_sockflags, null,
127 req_callback, req_result) {}
129 // For ReceiveFrom and SendTo
130 public Worker(Socket req_sock, byte[] req_buffer,
131 int req_offset, int req_size,
132 SocketFlags req_sockflags,
133 EndPoint req_endpoint,
134 AsyncCallback req_callback,
135 SocketAsyncResult req_result) {
140 sockflags=req_sockflags;
141 endpoint=req_endpoint;
142 callback=req_callback;
147 ((ManualResetEvent)result.AsyncWaitHandle).Set();
148 result.IsCompleted=true;
149 if (callback != null)
153 public void Accept() {
156 acc_socket=socket.Accept();
157 } catch (Exception e) {
158 result.SetDelayedException(e);
164 public void Connect() {
166 if (socket.Blocking) {
168 socket.Connect(endpoint);
169 } catch (Exception e) {
170 result.SetDelayedException(e);
176 SocketException rethrow = null;
178 socket.Connect (endpoint);
179 } catch (SocketException e) {
181 if (e.NativeErrorCode != 10036) {
182 result.SetDelayedException(e);
187 socket.Poll (-1, SelectMode.SelectWrite);
189 socket.Connect (endpoint);
190 } catch (SocketException e2) {
195 result.SetDelayedException(rethrow);
200 public void Receive() {
202 if (socket.Blocking) {
204 total=socket.Receive(buffer, offset,
206 } catch (Exception e) {
207 result.SetDelayedException(e);
213 SocketException rethrow = null;
215 total = socket.Receive (buffer, offset, size, sockflags);
216 } catch (SocketException e) {
218 if (e.NativeErrorCode != 10035) {
219 result.SetDelayedException(e);
224 socket.Poll (-1, SelectMode.SelectRead);
226 total = socket.Receive (buffer, offset, size, sockflags);
227 } catch (SocketException e2) {
232 result.SetDelayedException(rethrow);
237 public void ReceiveFrom() {
240 total=socket.ReceiveFrom(buffer,
244 } catch (Exception e) {
245 result.SetDelayedException(e);
254 total=socket.Send(buffer, offset, size,
256 } catch (Exception e) {
257 result.SetDelayedException(e);
263 public void SendTo() {
266 total=socket.SendTo(buffer, offset,
269 } catch (Exception e) {
270 result.SetDelayedException(e);
276 public EndPoint EndPoint {
282 public Socket Socket {
295 /* the field "socket" is looked up by name by the runtime */
296 private IntPtr socket;
297 private AddressFamily address_family;
298 private SocketType socket_type;
299 private ProtocolType protocol_type;
300 private bool blocking=true;
301 private int pendingEnds;
302 private int closeDelayed;
305 * These two fields are looked up by name by the runtime, don't change
\r
306 * their name without also updating the runtime code.
\r
308 private static int ipv4Supported = -1, ipv6Supported = -1;
310 /* When true, the socket was connected at the time of
311 * the last IO operation
313 private bool connected=false;
314 /* true if we called Close_internal */
317 /* Used in LocalEndPoint and RemoteEndPoint if the
318 * Mono.Posix assembly is available
320 private static object unixendpoint=null;
321 private static Type unixendpointtype=null;
323 [MethodImplAttribute(MethodImplOptions.InternalCall)]
324 private extern static void Select_internal(ref Socket[] read,
329 public static void Select(IList read_list, IList write_list,
330 IList err_list, int time_us) {
331 if(read_list==null &&
334 throw new ArgumentNullException();
337 int read_count = 0, write_count = 0, err_count = 0;
338 Socket[] read_arr = null;
339 Socket[] write_arr = null;
340 Socket[] err_arr = null;
343 read_count=read_list.Count;
346 read_arr=new Socket[read_count];
348 if (write_list!=null)
349 write_count=write_list.Count;
351 if (write_count != 0)
352 write_arr=new Socket[write_count];
355 err_count=err_list.Count;
358 err_arr=new Socket[err_count];
362 if (read_count != 0) {
365 foreach (Socket s in read_list) {
371 if (write_count != 0) {
373 foreach (Socket s in write_list) {
379 if (err_count != 0) {
381 foreach (Socket s in err_list) {
387 Select_internal(ref read_arr, ref write_arr,
388 ref err_arr, time_us);
390 if(read_list!=null) {
392 for(i=0; i<read_arr.Length; i++) {
393 read_list.Add(read_arr[i]);
397 if(write_list!=null) {
399 for(i=0; i<write_arr.Length; i++) {
400 write_list.Add(write_arr[i]);
406 for(i=0; i<err_arr.Length; i++) {
407 err_list.Add(err_arr[i]);
416 ass=Assembly.Load("Mono.Posix");
417 } catch (FileNotFoundException) {
421 unixendpointtype=ass.GetType("Mono.Posix.UnixEndPoint");
423 /* The endpoint Create() method is an instance
426 Type[] arg_types=new Type[1];
427 arg_types[0]=typeof(string);
428 ConstructorInfo cons=unixendpointtype.GetConstructor(arg_types);
430 object[] args=new object[1];
433 unixendpoint=cons.Invoke(args);
436 // private constructor used by Accept, which already
437 // has a socket handle to use
438 private Socket(AddressFamily family, SocketType type,
439 ProtocolType proto, IntPtr sock) {
440 address_family=family;
448 // Creates a new system socket, returning the handle
449 [MethodImplAttribute(MethodImplOptions.InternalCall)]
450 private extern IntPtr Socket_internal(AddressFamily family,
454 public Socket(AddressFamily family, SocketType type,
455 ProtocolType proto) {
456 address_family=family;
460 socket=Socket_internal(family, type, proto);
463 public AddressFamily AddressFamily {
465 return(address_family);
469 // Returns the amount of data waiting to be read on socket
470 [MethodImplAttribute(MethodImplOptions.InternalCall)]
471 private extern static int Available_internal(IntPtr socket);
473 public int Available {
475 if (disposed && closed)
476 throw new ObjectDisposedException (GetType ().ToString ());
478 return(Available_internal(socket));
482 [MethodImplAttribute(MethodImplOptions.InternalCall)]
483 private extern static void Blocking_internal(IntPtr socket,
486 public bool Blocking {
491 Blocking_internal(socket, value);
496 public bool Connected {
502 public IntPtr Handle {
508 // Returns the local endpoint details in addr and port
509 [MethodImplAttribute(MethodImplOptions.InternalCall)]
510 private extern static SocketAddress LocalEndPoint_internal(IntPtr socket);
512 [MonoTODO("Support non-IP endpoints")]
513 public EndPoint LocalEndPoint {
515 if (disposed && closed)
516 throw new ObjectDisposedException (GetType ().ToString ());
520 sa=LocalEndPoint_internal(socket);
522 if(sa.Family==AddressFamily.InterNetwork || sa.Family==AddressFamily.InterNetworkV6) {
523 // Stupidly, EndPoint.Create() is an
525 return new IPEndPoint(0, 0).Create(sa);
526 } else if (sa.Family==AddressFamily.Unix &&
527 unixendpoint!=null) {
528 return((EndPoint)unixendpointtype.InvokeMember("Create", BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public, null, unixendpoint, new object[] {sa}));
530 throw new NotImplementedException();
535 public ProtocolType ProtocolType {
537 return(protocol_type);
541 // Returns the remote endpoint details in addr and port
542 [MethodImplAttribute(MethodImplOptions.InternalCall)]
543 private extern static SocketAddress RemoteEndPoint_internal(IntPtr socket);
545 [MonoTODO("Support non-IP endpoints")]
546 public EndPoint RemoteEndPoint {
548 if (disposed && closed)
549 throw new ObjectDisposedException (GetType ().ToString ());
553 sa=RemoteEndPoint_internal(socket);
555 if(sa.Family==AddressFamily.InterNetwork || sa.Family==AddressFamily.InterNetworkV6 ) {
556 // Stupidly, EndPoint.Create() is an
558 return new IPEndPoint(0, 0).Create(sa);
559 } else if (sa.Family==AddressFamily.Unix &&
560 unixendpoint!=null) {
561 return((EndPoint)unixendpointtype.InvokeMember("Create", BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public, null, unixendpoint, new object[] {sa}));
563 throw new NotImplementedException();
568 public SocketType SocketType {
575 public static bool SupportsIPv4 {
\r
577 CheckProtocolSupport();
\r
578 return ipv4Supported == 1;
\r
582 public static bool SupportsIPv6 {
\r
584 CheckProtocolSupport();
\r
585 return ipv6Supported == 1;
\r
589 internal static bool SupportsIPv4
\r
597 internal static bool SupportsIPv6
\r
606 internal static void CheckProtocolSupport()
608 if(ipv4Supported == -1) {
\r
610 Socket tmp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
\r
620 if(ipv6Supported == -1) {
\r
621 NetConfig config = (NetConfig)System.Configuration.ConfigurationSettings.GetConfig("system.net/settings");
\r
624 ipv6Supported = config.ipv6Enabled?-1:0;
\r
626 if(ipv6Supported != 0) {
\r
628 Socket tmp = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
\r
638 // Creates a new system socket, returning the handle
639 [MethodImplAttribute(MethodImplOptions.InternalCall)]
640 private extern static IntPtr Accept_internal(IntPtr sock);
642 public Socket Accept() {
643 if (disposed && closed)
644 throw new ObjectDisposedException (GetType ().ToString ());
646 IntPtr sock=Accept_internal(socket);
648 return(new Socket(this.AddressFamily, this.SocketType,
649 this.ProtocolType, sock));
652 public IAsyncResult BeginAccept(AsyncCallback callback,
655 if (disposed && closed)
656 throw new ObjectDisposedException (GetType ().ToString ());
658 Interlocked.Increment (ref pendingEnds);
659 SocketAsyncResult req=new SocketAsyncResult(state);
660 Worker worker=new Worker(this, callback, req);
662 Thread child=new Thread(new ThreadStart(worker.Accept));
663 child.IsBackground = true;
668 public IAsyncResult BeginConnect(EndPoint end_point,
669 AsyncCallback callback,
672 if (disposed && closed)
673 throw new ObjectDisposedException (GetType ().ToString ());
675 if (end_point == null)
676 throw new ArgumentNullException ("end_point");
678 Interlocked.Increment (ref pendingEnds);
679 SocketAsyncResult req=new SocketAsyncResult(state);
680 Worker worker=new Worker(this, end_point, callback,
683 Thread child=new Thread(new ThreadStart(worker.Connect));
684 child.IsBackground = true;
689 public IAsyncResult BeginReceive(byte[] buffer, int offset,
691 SocketFlags socket_flags,
692 AsyncCallback callback,
695 if (disposed && closed)
696 throw new ObjectDisposedException (GetType ().ToString ());
699 throw new ArgumentNullException ("buffer");
702 throw new ArgumentOutOfRangeException ("offset must be >= 0");
705 throw new ArgumentOutOfRangeException ("size must be >= 0");
707 if (offset + size > buffer.Length)
708 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
710 Interlocked.Increment (ref pendingEnds);
711 SocketAsyncResult req=new SocketAsyncResult(state);
712 Worker worker=new Worker(this, buffer, offset, size,
713 socket_flags, callback, req);
715 Thread child=new Thread(new ThreadStart(worker.Receive));
716 child.IsBackground = true;
721 public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset,
723 SocketFlags socket_flags,
724 ref EndPoint remote_end,
725 AsyncCallback callback,
727 if (disposed && closed)
728 throw new ObjectDisposedException (GetType ().ToString ());
731 throw new ArgumentNullException ("buffer");
734 throw new ArgumentOutOfRangeException ("offset must be >= 0");
737 throw new ArgumentOutOfRangeException ("size must be >= 0");
739 if (offset + size > buffer.Length)
740 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
742 Interlocked.Increment (ref pendingEnds);
743 SocketAsyncResult req=new SocketAsyncResult(state);
744 Worker worker=new Worker(this, buffer, offset, size,
745 socket_flags, remote_end,
748 Thread child=new Thread(new ThreadStart(worker.ReceiveFrom));
749 child.IsBackground = true;
754 public IAsyncResult BeginSend(byte[] buffer, int offset,
756 SocketFlags socket_flags,
757 AsyncCallback callback,
759 if (disposed && closed)
760 throw new ObjectDisposedException (GetType ().ToString ());
763 throw new ArgumentNullException ("buffer");
766 throw new ArgumentOutOfRangeException ("offset must be >= 0");
769 throw new ArgumentOutOfRangeException ("size must be >= 0");
771 if (offset + size > buffer.Length)
772 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
774 Interlocked.Increment (ref pendingEnds);
775 SocketAsyncResult req=new SocketAsyncResult(state);
776 Worker worker=new Worker(this, buffer, offset, size,
777 socket_flags, callback, req);
779 Thread child=new Thread(new ThreadStart(worker.Send));
780 child.IsBackground = true;
785 public IAsyncResult BeginSendTo(byte[] buffer, int offset,
787 SocketFlags socket_flags,
789 AsyncCallback callback,
791 if (disposed && closed)
792 throw new ObjectDisposedException (GetType ().ToString ());
795 throw new ArgumentNullException ("buffer");
798 throw new ArgumentOutOfRangeException ("offset must be >= 0");
801 throw new ArgumentOutOfRangeException ("size must be >= 0");
803 if (offset + size > buffer.Length)
804 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
806 Interlocked.Increment (ref pendingEnds);
807 SocketAsyncResult req=new SocketAsyncResult(state);
808 Worker worker=new Worker(this, buffer, offset, size,
809 socket_flags, remote_end,
812 Thread child=new Thread(new ThreadStart(worker.SendTo));
813 child.IsBackground = true;
818 // Creates a new system socket, returning the handle
819 [MethodImplAttribute(MethodImplOptions.InternalCall)]
820 private extern static void Bind_internal(IntPtr sock,
823 public void Bind(EndPoint local_end) {
824 if (disposed && closed)
825 throw new ObjectDisposedException (GetType ().ToString ());
827 if(local_end==null) {
828 throw new ArgumentNullException("local_end");
831 Bind_internal(socket, local_end.Serialize());
835 [MethodImplAttribute(MethodImplOptions.InternalCall)]
836 private extern static void Close_internal(IntPtr socket);
838 public void Close() {
839 ((IDisposable) this).Dispose ();
842 // Connects to the remote address
843 [MethodImplAttribute(MethodImplOptions.InternalCall)]
844 private extern static void Connect_internal(IntPtr sock,
847 public void Connect(EndPoint remote_end) {
848 if (disposed && closed)
849 throw new ObjectDisposedException (GetType ().ToString ());
851 if(remote_end==null) {
852 throw new ArgumentNullException("remote_end");
855 Connect_internal(socket, remote_end.Serialize());
859 public Socket EndAccept(IAsyncResult result) {
860 if (disposed && closed)
861 throw new ObjectDisposedException (GetType ().ToString ());
864 throw new ArgumentNullException ("result");
866 SocketAsyncResult req = result as SocketAsyncResult;
868 throw new ArgumentException ("Invalid IAsyncResult");
870 result.AsyncWaitHandle.WaitOne();
871 Interlocked.Decrement (ref pendingEnds);
873 req.CheckIfThrowDelayedException();
874 return(req.Worker.Socket);
877 public void EndConnect(IAsyncResult result) {
878 if (disposed && closed)
879 throw new ObjectDisposedException (GetType ().ToString ());
882 throw new ArgumentNullException ("result");
884 SocketAsyncResult req = result as SocketAsyncResult;
886 throw new ArgumentException ("Invalid IAsyncResult");
888 result.AsyncWaitHandle.WaitOne();
889 Interlocked.Decrement (ref pendingEnds);
891 req.CheckIfThrowDelayedException();
894 public int EndReceive(IAsyncResult result) {
895 if (disposed && closed)
896 throw new ObjectDisposedException (GetType ().ToString ());
899 throw new ArgumentNullException ("result");
901 SocketAsyncResult req = result as SocketAsyncResult;
903 throw new ArgumentException ("Invalid IAsyncResult");
905 result.AsyncWaitHandle.WaitOne();
906 Interlocked.Decrement (ref pendingEnds);
908 req.CheckIfThrowDelayedException();
909 return(req.Worker.Total);
912 public int EndReceiveFrom(IAsyncResult result,
913 ref EndPoint end_point) {
914 if (disposed && closed)
915 throw new ObjectDisposedException (GetType ().ToString ());
918 throw new ArgumentNullException ("result");
920 SocketAsyncResult req = result as SocketAsyncResult;
922 throw new ArgumentException ("Invalid IAsyncResult");
924 result.AsyncWaitHandle.WaitOne();
925 Interlocked.Decrement (ref pendingEnds);
927 req.CheckIfThrowDelayedException();
928 end_point=req.Worker.EndPoint;
929 return(req.Worker.Total);
932 public int EndSend(IAsyncResult result) {
933 if (disposed && closed)
934 throw new ObjectDisposedException (GetType ().ToString ());
937 throw new ArgumentNullException ("result");
939 SocketAsyncResult req = result as SocketAsyncResult;
941 throw new ArgumentException ("Invalid IAsyncResult");
943 result.AsyncWaitHandle.WaitOne();
944 Interlocked.Decrement (ref pendingEnds);
946 req.CheckIfThrowDelayedException();
947 return(req.Worker.Total);
950 public int EndSendTo(IAsyncResult result) {
951 if (disposed && closed)
952 throw new ObjectDisposedException (GetType ().ToString ());
955 throw new ArgumentNullException ("result");
957 SocketAsyncResult req = result as SocketAsyncResult;
959 throw new ArgumentException ("Invalid IAsyncResult");
961 result.AsyncWaitHandle.WaitOne();
962 Interlocked.Decrement (ref pendingEnds);
964 req.CheckIfThrowDelayedException();
965 return(req.Worker.Total);
970 if (Interlocked.CompareExchange (ref closeDelayed, 1, 0) == 1) {
972 Close_internal(socket);
976 [MethodImplAttribute(MethodImplOptions.InternalCall)]
977 private extern static void GetSocketOption_obj_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, out object obj_val);
978 [MethodImplAttribute(MethodImplOptions.InternalCall)]
979 private extern static void GetSocketOption_arr_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val);
981 public object GetSocketOption(SocketOptionLevel level,
982 SocketOptionName name) {
985 GetSocketOption_obj_internal(socket, level, name,
988 if(name==SocketOptionName.Linger) {
989 return((LingerOption)obj_val);
990 } else if (name==SocketOptionName.AddMembership ||
991 name==SocketOptionName.DropMembership) {
992 return((MulticastOption)obj_val);
994 return((int)obj_val);
998 public void GetSocketOption(SocketOptionLevel level,
999 SocketOptionName name,
1001 int opt_value_len=opt_value.Length;
1003 GetSocketOption_arr_internal(socket, level, name,
1007 public byte[] GetSocketOption(SocketOptionLevel level,
1008 SocketOptionName name,
1010 byte[] byte_val=new byte[length];
1012 GetSocketOption_arr_internal(socket, level, name,
1018 [MonoTODO("Totally undocumented")]
1019 public int IOControl(int ioctl_code, byte[] in_value,
1021 throw new NotImplementedException();
1024 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1025 private extern static void Listen_internal(IntPtr sock,
1028 public void Listen(int backlog) {
1029 Listen_internal(socket, backlog);
1032 /* The docs for Poll() are a bit lightweight too, but
1033 * it seems to be just a simple wrapper around Select.
1035 public bool Poll(int time_us, SelectMode mode) {
1036 Socket [] socketlist = new Socket []{this};
1040 case SelectMode.SelectError:
1041 Select_internal (ref n, ref n, ref socketlist, time_us);
1043 case SelectMode.SelectRead:
1044 Select_internal (ref socketlist, ref n, ref n, time_us);
1046 case SelectMode.SelectWrite:
1047 Select_internal (ref n, ref socketlist, ref n, time_us);
1050 throw new NotSupportedException();
1053 return (socketlist.Length == 1);
1056 public int Receive(byte[] buf) {
1057 return(Receive(buf, 0, buf.Length, SocketFlags.None));
1060 public int Receive(byte[] buf, SocketFlags flags) {
1061 return(Receive(buf, 0, buf.Length, flags));
1064 public int Receive(byte[] buf, int size, SocketFlags flags) {
1065 return(Receive(buf, 0, size, flags));
1068 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1069 private extern static int Receive_internal(IntPtr sock,
1075 public int Receive(byte[] buf, int offset, int size,
1076 SocketFlags flags) {
1078 throw new ArgumentNullException("buffer is null");
1080 if(offset<0 || offset > buf.Length) {
1081 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
1083 if(size<0 || offset+size > buf.Length) {
1084 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
1090 ret=Receive_internal(socket, buf, offset,
1092 } catch(SocketException) {
1101 public int ReceiveFrom(byte[] buf, ref EndPoint remote_end) {
1102 return(ReceiveFrom(buf, 0, buf.Length,
1103 SocketFlags.None, ref remote_end));
1106 public int ReceiveFrom(byte[] buf, SocketFlags flags,
1107 ref EndPoint remote_end) {
1108 return(ReceiveFrom(buf, 0, buf.Length, flags,
1112 public int ReceiveFrom(byte[] buf, int size, SocketFlags flags,
1113 ref EndPoint remote_end) {
1114 return(ReceiveFrom(buf, 0, size, flags,
1119 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1120 private extern static int RecvFrom_internal(IntPtr sock,
1125 ref SocketAddress sockaddr);
1127 public int ReceiveFrom(byte[] buf, int offset, int size,
1129 ref EndPoint remote_end) {
1131 throw new ArgumentNullException("buffer is null");
1133 if(remote_end==null) {
1134 throw new ArgumentNullException("remote endpoint is null");
1136 if(offset<0 || offset>buf.Length) {
1137 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
1139 if(size<0 || offset+size>buf.Length) {
1140 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
1143 SocketAddress sockaddr=remote_end.Serialize();
1147 count=RecvFrom_internal(socket, buf, offset,
1150 } catch(SocketException) {
1156 // Stupidly, EndPoint.Create() is an
1158 remote_end=remote_end.Create(sockaddr);
1163 public int Send(byte[] buf) {
1164 return(Send(buf, 0, buf.Length, SocketFlags.None));
1167 public int Send(byte[] buf, SocketFlags flags) {
1168 return(Send(buf, 0, buf.Length, flags));
1171 public int Send(byte[] buf, int size, SocketFlags flags) {
1172 return(Send(buf, 0, size, flags));
1175 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1176 private extern static int Send_internal(IntPtr sock,
1177 byte[] buf, int offset,
1181 public int Send (byte[] buf, int offset, int size, SocketFlags flags)
1184 throw new ArgumentNullException ("buffer");
1186 if (offset < 0 || offset > buf.Length)
1187 throw new ArgumentOutOfRangeException ("offset");
1189 if (size < 0 || offset + size > buf.Length)
1190 throw new ArgumentOutOfRangeException ("size");
1198 ret = Send_internal (socket, buf, offset, size, flags);
1199 } catch (SocketException) {
1208 public int SendTo(byte[] buffer, EndPoint remote_end) {
1209 return(SendTo(buffer, 0, buffer.Length,
1210 SocketFlags.None, remote_end));
1213 public int SendTo(byte[] buffer, SocketFlags flags,
1214 EndPoint remote_end) {
1215 return(SendTo(buffer, 0, buffer.Length, flags,
1219 public int SendTo(byte[] buffer, int size, SocketFlags flags,
1220 EndPoint remote_end) {
1221 return(SendTo(buffer, 0, size, flags, remote_end));
1225 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1226 private extern static int SendTo_internal(IntPtr sock,
1233 public int SendTo(byte[] buffer, int offset, int size,
1234 SocketFlags flags, EndPoint remote_end) {
1236 throw new ArgumentNullException("buffer is null");
1238 if(remote_end==null) {
1239 throw new ArgumentNullException("remote endpoint is null");
1241 if(offset<0 || offset>buffer.Length) {
1242 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
1244 if(size<0 || offset+size>buffer.Length) {
1245 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
1248 SocketAddress sockaddr=remote_end.Serialize();
1253 ret=SendTo_internal(socket, buffer, offset,
1254 size, flags, sockaddr);
1256 catch(SocketException) {
1265 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1266 private extern static void SetSocketOption_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, object obj_val, byte[] byte_val, int int_val);
1268 public void SetSocketOption(SocketOptionLevel level,
1269 SocketOptionName name,
1271 SetSocketOption_internal(socket, level, name, null,
1275 public void SetSocketOption(SocketOptionLevel level,
1276 SocketOptionName name,
1278 SetSocketOption_internal(socket, level, name, null,
1282 public void SetSocketOption(SocketOptionLevel level,
1283 SocketOptionName name,
1285 if(opt_value==null) {
1286 throw new ArgumentNullException();
1289 /* Passing a bool as the third parameter to
1290 * SetSocketOption causes this overload to be
1291 * used when in fact we want to pass the value
1292 * to the runtime as an int.
1294 if(opt_value is System.Boolean) {
1295 bool bool_val=(bool)opt_value;
1297 /* Stupid casting rules :-( */
1298 if(bool_val==true) {
1299 SetSocketOption_internal(socket, level,
1303 SetSocketOption_internal(socket, level,
1308 SetSocketOption_internal(socket, level, name,
1309 opt_value, null, 0);
1313 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1314 private extern static void Shutdown_internal(IntPtr socket, SocketShutdown how);
1316 public void Shutdown(SocketShutdown how) {
1317 Shutdown_internal(socket, how);
1320 public override int GetHashCode ()
1322 return (int) socket;
1325 private bool disposed;
1327 protected virtual void Dispose(bool explicitDisposing) {
1328 // Check to see if Dispose has already been called
1329 if(!this.disposed) {
1330 // If this is a call to Dispose,
1331 // dispose all managed resources.
1332 if(explicitDisposing) {
1333 // Free up stuff here
1336 // Release unmanaged resources
1340 Interlocked.CompareExchange (ref closeDelayed, 0, 1);
1341 if (Interlocked.CompareExchange (ref pendingEnds, 0, 0) == 0) {
1342 if (Interlocked.CompareExchange (ref closeDelayed, 1, 0) == 1) {
1344 Close_internal(socket);
1350 void IDisposable.Dispose ()
1353 GC.SuppressFinalize (this);