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 {
54 if (waithandle == null)
55 waithandle = new ManualResetEvent (completed);
65 public bool CompletedSynchronously {
67 return(completed_sync);
71 public bool IsCompleted {
78 if (waithandle != null && value) {
79 ((ManualResetEvent) waithandle).Set ();
85 public Worker Worker {
95 private sealed class Worker
97 private AsyncCallback callback;
98 private SocketAsyncResult result;
99 private Socket socket;
102 private EndPoint endpoint; // Connect,ReceiveFrom,SendTo
103 private byte[] buffer; // Receive,ReceiveFrom,Send,SendTo
104 private int offset; // Receive,ReceiveFrom,Send,SendTo
105 private int size; // Receive,ReceiveFrom,Send,SendTo
106 private SocketFlags sockflags; // Receive,ReceiveFrom,Send,SendTo
109 private Socket acc_socket;
114 public Worker(Socket req_sock,
115 AsyncCallback req_callback,
116 SocketAsyncResult req_result)
117 : this(req_sock, null, 0, 0, SocketFlags.None,
118 null, req_callback, req_result) {}
121 public Worker(Socket req_sock, EndPoint req_endpoint,
122 AsyncCallback req_callback,
123 SocketAsyncResult req_result)
124 : this(req_sock, null, 0, 0, SocketFlags.None,
125 req_endpoint, req_callback,
128 // For Receive and Send
129 public Worker(Socket req_sock, byte[] req_buffer,
130 int req_offset, int req_size,
131 SocketFlags req_sockflags,
132 AsyncCallback req_callback,
133 SocketAsyncResult req_result)
134 : this(req_sock, req_buffer, req_offset,
135 req_size, req_sockflags, null,
136 req_callback, req_result) {}
138 // For ReceiveFrom and SendTo
139 public Worker(Socket req_sock, byte[] req_buffer,
140 int req_offset, int req_size,
141 SocketFlags req_sockflags,
142 EndPoint req_endpoint,
143 AsyncCallback req_callback,
144 SocketAsyncResult req_result) {
149 sockflags=req_sockflags;
150 endpoint=req_endpoint;
151 callback=req_callback;
156 result.IsCompleted=true;
157 if (callback != null)
161 public void Accept() {
164 acc_socket=socket.Accept();
165 } catch (Exception e) {
166 result.SetDelayedException(e);
172 public void Connect() {
174 if (socket.Blocking) {
176 socket.Connect(endpoint);
177 } catch (Exception e) {
178 result.SetDelayedException(e);
184 Exception rethrow = null;
186 socket.Connect (endpoint);
187 } catch (SocketException e) {
189 if (e.NativeErrorCode != 10036) {
190 result.SetDelayedException(e);
195 socket.Poll (-1, SelectMode.SelectWrite);
197 socket.Connect (endpoint);
198 } catch (SocketException e2) {
201 } catch (Exception e3) {
206 result.SetDelayedException(rethrow);
211 public void Receive() {
213 if (socket.Blocking) {
215 total=socket.Receive(buffer, offset,
217 } catch (Exception e) {
218 result.SetDelayedException(e);
224 Exception rethrow = null;
226 total = socket.Receive (buffer, offset, size, sockflags);
227 } catch (SocketException e) {
229 if (e.NativeErrorCode != 10035) {
230 result.SetDelayedException(e);
235 socket.Poll (-1, SelectMode.SelectRead);
237 total = socket.Receive (buffer, offset, size, sockflags);
238 } catch (SocketException e2) {
241 } catch (Exception e3) {
246 result.SetDelayedException(rethrow);
251 public void ReceiveFrom() {
253 if (socket.Blocking) {
255 total=socket.ReceiveFrom(buffer,
259 } catch (Exception e) {
260 result.SetDelayedException(e);
266 Exception rethrow = null;
268 total = socket.ReceiveFrom (buffer, offset, size,
269 sockflags, ref endpoint);
270 } catch (SocketException e) {
272 if (e.NativeErrorCode != 10035) {
273 result.SetDelayedException(e);
278 socket.Poll (-1, SelectMode.SelectRead);
280 total = socket.ReceiveFrom (buffer, offset, size,
281 sockflags, ref endpoint);
282 } catch (SocketException e2) {
285 } catch (Exception e3) {
290 result.SetDelayedException(rethrow);
297 if (socket.Blocking) {
299 total=socket.Send(buffer, offset, size,
301 } catch (Exception e) {
302 result.SetDelayedException(e);
308 Exception rethrow = null;
310 total = socket.Send (buffer, offset, size, sockflags);
311 } catch (SocketException e) {
313 if (e.NativeErrorCode != 10035) {
314 result.SetDelayedException(e);
319 socket.Poll (-1, SelectMode.SelectWrite);
321 total = socket.Send (buffer, offset, size, sockflags);
322 } catch (SocketException e2) {
325 } catch (Exception e3) {
330 result.SetDelayedException(rethrow);
335 public void SendTo() {
337 if (socket.Blocking) {
339 total=socket.SendTo(buffer, offset,
342 } catch (Exception e) {
343 result.SetDelayedException(e);
349 Exception rethrow = null;
351 total = socket.SendTo (buffer, offset, size,
352 sockflags, endpoint);
353 } catch (SocketException e) {
355 if (e.NativeErrorCode != 10035) {
356 result.SetDelayedException(e);
361 socket.Poll (-1, SelectMode.SelectWrite);
363 total = socket.SendTo (buffer, offset, size,
364 sockflags, endpoint);
365 } catch (SocketException e2) {
368 } catch (Exception e3) {
373 result.SetDelayedException(rethrow);
378 public EndPoint EndPoint {
384 public Socket Socket {
397 /* the field "socket" is looked up by name by the runtime */
398 private IntPtr socket;
399 private AddressFamily address_family;
400 private SocketType socket_type;
401 private ProtocolType protocol_type;
402 private bool blocking=true;
403 private int pendingEnds;
404 private int closeDelayed;
406 delegate void SocketAsyncCall ();
408 * These two fields are looked up by name by the runtime, don't change
\r
409 * their name without also updating the runtime code.
\r
411 private static int ipv4Supported = -1, ipv6Supported = -1;
413 /* When true, the socket was connected at the time of
414 * the last IO operation
416 private bool connected=false;
417 /* true if we called Close_internal */
420 /* Used in LocalEndPoint and RemoteEndPoint if the
421 * Mono.Posix assembly is available
423 private static object unixendpoint=null;
424 private static Type unixendpointtype=null;
426 [MethodImplAttribute(MethodImplOptions.InternalCall)]
427 private extern static void Select_internal(ref Socket[] read,
432 public static void Select(IList read_list, IList write_list,
433 IList err_list, int time_us) {
434 if(read_list==null &&
437 throw new ArgumentNullException();
440 int read_count = 0, write_count = 0, err_count = 0;
441 Socket[] read_arr = null;
442 Socket[] write_arr = null;
443 Socket[] err_arr = null;
446 read_count=read_list.Count;
449 read_arr=new Socket[read_count];
451 if (write_list!=null)
452 write_count=write_list.Count;
454 if (write_count != 0)
455 write_arr=new Socket[write_count];
458 err_count=err_list.Count;
461 err_arr=new Socket[err_count];
465 if (read_count != 0) {
468 foreach (Socket s in read_list) {
474 if (write_count != 0) {
476 foreach (Socket s in write_list) {
482 if (err_count != 0) {
484 foreach (Socket s in err_list) {
490 Select_internal(ref read_arr, ref write_arr,
491 ref err_arr, time_us);
493 if(read_list!=null) {
495 for(i=0; i<read_arr.Length; i++) {
496 read_list.Add(read_arr[i]);
500 if(write_list!=null) {
502 for(i=0; i<write_arr.Length; i++) {
503 write_list.Add(write_arr[i]);
509 for(i=0; i<err_arr.Length; i++) {
510 err_list.Add(err_arr[i]);
519 ass=Assembly.Load("Mono.Posix");
520 } catch (FileNotFoundException) {
524 unixendpointtype=ass.GetType("Mono.Posix.UnixEndPoint");
526 /* The endpoint Create() method is an instance
529 Type[] arg_types=new Type[1];
530 arg_types[0]=typeof(string);
531 ConstructorInfo cons=unixendpointtype.GetConstructor(arg_types);
533 object[] args=new object[1];
536 unixendpoint=cons.Invoke(args);
539 // private constructor used by Accept, which already
540 // has a socket handle to use
541 private Socket(AddressFamily family, SocketType type,
542 ProtocolType proto, IntPtr sock) {
543 address_family=family;
551 // Creates a new system socket, returning the handle
552 [MethodImplAttribute(MethodImplOptions.InternalCall)]
553 private extern IntPtr Socket_internal(AddressFamily family,
557 public Socket(AddressFamily family, SocketType type,
558 ProtocolType proto) {
559 address_family=family;
563 socket=Socket_internal(family, type, proto);
566 public AddressFamily AddressFamily {
568 return(address_family);
572 // Returns the amount of data waiting to be read on socket
573 [MethodImplAttribute(MethodImplOptions.InternalCall)]
574 private extern static int Available_internal(IntPtr socket);
576 public int Available {
578 if (disposed && closed)
579 throw new ObjectDisposedException (GetType ().ToString ());
581 return(Available_internal(socket));
585 [MethodImplAttribute(MethodImplOptions.InternalCall)]
586 private extern static void Blocking_internal(IntPtr socket,
589 public bool Blocking {
594 Blocking_internal(socket, value);
599 public bool Connected {
605 public IntPtr Handle {
611 // Returns the local endpoint details in addr and port
612 [MethodImplAttribute(MethodImplOptions.InternalCall)]
613 private extern static SocketAddress LocalEndPoint_internal(IntPtr socket);
615 [MonoTODO("Support non-IP endpoints")]
616 public EndPoint LocalEndPoint {
618 if (disposed && closed)
619 throw new ObjectDisposedException (GetType ().ToString ());
623 sa=LocalEndPoint_internal(socket);
625 if(sa.Family==AddressFamily.InterNetwork || sa.Family==AddressFamily.InterNetworkV6) {
626 // Stupidly, EndPoint.Create() is an
628 return new IPEndPoint(0, 0).Create(sa);
629 } else if (sa.Family==AddressFamily.Unix &&
630 unixendpoint!=null) {
631 return((EndPoint)unixendpointtype.InvokeMember("Create", BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public, null, unixendpoint, new object[] {sa}));
633 throw new NotImplementedException();
638 public ProtocolType ProtocolType {
640 return(protocol_type);
644 // Returns the remote endpoint details in addr and port
645 [MethodImplAttribute(MethodImplOptions.InternalCall)]
646 private extern static SocketAddress RemoteEndPoint_internal(IntPtr socket);
648 [MonoTODO("Support non-IP endpoints")]
649 public EndPoint RemoteEndPoint {
651 if (disposed && closed)
652 throw new ObjectDisposedException (GetType ().ToString ());
656 sa=RemoteEndPoint_internal(socket);
658 if(sa.Family==AddressFamily.InterNetwork || sa.Family==AddressFamily.InterNetworkV6 ) {
659 // Stupidly, EndPoint.Create() is an
661 return new IPEndPoint(0, 0).Create(sa);
662 } else if (sa.Family==AddressFamily.Unix &&
663 unixendpoint!=null) {
664 return((EndPoint)unixendpointtype.InvokeMember("Create", BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public, null, unixendpoint, new object[] {sa}));
666 throw new NotImplementedException();
671 public SocketType SocketType {
678 public static bool SupportsIPv4 {
\r
680 CheckProtocolSupport();
\r
681 return ipv4Supported == 1;
\r
685 public static bool SupportsIPv6 {
\r
687 CheckProtocolSupport();
\r
688 return ipv6Supported == 1;
\r
692 internal static bool SupportsIPv4
\r
700 internal static bool SupportsIPv6
\r
709 internal static void CheckProtocolSupport()
711 if(ipv4Supported == -1) {
\r
713 Socket tmp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
\r
723 if(ipv6Supported == -1) {
\r
724 NetConfig config = (NetConfig)System.Configuration.ConfigurationSettings.GetConfig("system.net/settings");
\r
727 ipv6Supported = config.ipv6Enabled?-1:0;
\r
729 if(ipv6Supported != 0) {
\r
731 Socket tmp = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
\r
741 // Creates a new system socket, returning the handle
742 [MethodImplAttribute(MethodImplOptions.InternalCall)]
743 private extern static IntPtr Accept_internal(IntPtr sock);
745 public Socket Accept() {
746 if (disposed && closed)
747 throw new ObjectDisposedException (GetType ().ToString ());
749 IntPtr sock=Accept_internal(socket);
751 return(new Socket(this.AddressFamily, this.SocketType,
752 this.ProtocolType, sock));
755 public IAsyncResult BeginAccept(AsyncCallback callback,
758 if (disposed && closed)
759 throw new ObjectDisposedException (GetType ().ToString ());
761 Interlocked.Increment (ref pendingEnds);
762 SocketAsyncResult req=new SocketAsyncResult(state);
763 Worker worker=new Worker(this, callback, req);
765 SocketAsyncCall sac = new SocketAsyncCall (worker.Accept);
766 sac.BeginInvoke (null, null);
770 public IAsyncResult BeginConnect(EndPoint end_point,
771 AsyncCallback callback,
774 if (disposed && closed)
775 throw new ObjectDisposedException (GetType ().ToString ());
777 if (end_point == null)
778 throw new ArgumentNullException ("end_point");
780 Interlocked.Increment (ref pendingEnds);
781 SocketAsyncResult req=new SocketAsyncResult(state);
782 Worker worker=new Worker(this, end_point, callback,
785 SocketAsyncCall sac = new SocketAsyncCall (worker.Connect);
786 sac.BeginInvoke (null, null);
790 public IAsyncResult BeginReceive(byte[] buffer, int offset,
792 SocketFlags socket_flags,
793 AsyncCallback callback,
796 if (disposed && closed)
797 throw new ObjectDisposedException (GetType ().ToString ());
800 throw new ArgumentNullException ("buffer");
803 throw new ArgumentOutOfRangeException ("offset must be >= 0");
806 throw new ArgumentOutOfRangeException ("size must be >= 0");
808 if (offset + size > buffer.Length)
809 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
811 Interlocked.Increment (ref pendingEnds);
812 SocketAsyncResult req=new SocketAsyncResult(state);
813 Worker worker=new Worker(this, buffer, offset, size,
814 socket_flags, callback, req);
816 SocketAsyncCall sac = new SocketAsyncCall (worker.Receive);
817 sac.BeginInvoke (null, null);
821 public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset,
823 SocketFlags socket_flags,
824 ref EndPoint remote_end,
825 AsyncCallback callback,
827 if (disposed && closed)
828 throw new ObjectDisposedException (GetType ().ToString ());
831 throw new ArgumentNullException ("buffer");
834 throw new ArgumentOutOfRangeException ("offset must be >= 0");
837 throw new ArgumentOutOfRangeException ("size must be >= 0");
839 if (offset + size > buffer.Length)
840 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
842 Interlocked.Increment (ref pendingEnds);
843 SocketAsyncResult req=new SocketAsyncResult(state);
844 Worker worker=new Worker(this, buffer, offset, size,
845 socket_flags, remote_end,
848 SocketAsyncCall sac = new SocketAsyncCall (worker.ReceiveFrom);
849 sac.BeginInvoke (null, null);
853 public IAsyncResult BeginSend(byte[] buffer, int offset,
855 SocketFlags socket_flags,
856 AsyncCallback callback,
858 if (disposed && closed)
859 throw new ObjectDisposedException (GetType ().ToString ());
862 throw new ArgumentNullException ("buffer");
865 throw new ArgumentOutOfRangeException ("offset must be >= 0");
868 throw new ArgumentOutOfRangeException ("size must be >= 0");
870 if (offset + size > buffer.Length)
871 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
873 Interlocked.Increment (ref pendingEnds);
874 SocketAsyncResult req=new SocketAsyncResult(state);
875 Worker worker=new Worker(this, buffer, offset, size,
876 socket_flags, callback, req);
878 SocketAsyncCall sac = new SocketAsyncCall (worker.Send);
879 sac.BeginInvoke (null, null);
883 public IAsyncResult BeginSendTo(byte[] buffer, int offset,
885 SocketFlags socket_flags,
887 AsyncCallback callback,
889 if (disposed && closed)
890 throw new ObjectDisposedException (GetType ().ToString ());
893 throw new ArgumentNullException ("buffer");
896 throw new ArgumentOutOfRangeException ("offset must be >= 0");
899 throw new ArgumentOutOfRangeException ("size must be >= 0");
901 if (offset + size > buffer.Length)
902 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
904 Interlocked.Increment (ref pendingEnds);
905 SocketAsyncResult req=new SocketAsyncResult(state);
906 Worker worker=new Worker(this, buffer, offset, size,
907 socket_flags, remote_end,
910 SocketAsyncCall sac = new SocketAsyncCall (worker.SendTo);
911 sac.BeginInvoke (null, null);
915 // Creates a new system socket, returning the handle
916 [MethodImplAttribute(MethodImplOptions.InternalCall)]
917 private extern static void Bind_internal(IntPtr sock,
920 public void Bind(EndPoint local_end) {
921 if (disposed && closed)
922 throw new ObjectDisposedException (GetType ().ToString ());
924 if(local_end==null) {
925 throw new ArgumentNullException("local_end");
928 Bind_internal(socket, local_end.Serialize());
932 [MethodImplAttribute(MethodImplOptions.InternalCall)]
933 private extern static void Close_internal(IntPtr socket);
935 public void Close() {
936 ((IDisposable) this).Dispose ();
939 // Connects to the remote address
940 [MethodImplAttribute(MethodImplOptions.InternalCall)]
941 private extern static void Connect_internal(IntPtr sock,
944 public void Connect(EndPoint remote_end) {
945 if (disposed && closed)
946 throw new ObjectDisposedException (GetType ().ToString ());
948 if(remote_end==null) {
949 throw new ArgumentNullException("remote_end");
952 Connect_internal(socket, remote_end.Serialize());
956 public Socket EndAccept(IAsyncResult result) {
957 if (disposed && closed)
958 throw new ObjectDisposedException (GetType ().ToString ());
961 throw new ArgumentNullException ("result");
963 SocketAsyncResult req = result as SocketAsyncResult;
965 throw new ArgumentException ("Invalid IAsyncResult");
967 if (!result.IsCompleted)
968 result.AsyncWaitHandle.WaitOne();
970 Interlocked.Decrement (ref pendingEnds);
972 req.CheckIfThrowDelayedException();
973 return(req.Worker.Socket);
976 public void EndConnect(IAsyncResult result) {
977 if (disposed && closed)
978 throw new ObjectDisposedException (GetType ().ToString ());
981 throw new ArgumentNullException ("result");
983 SocketAsyncResult req = result as SocketAsyncResult;
985 throw new ArgumentException ("Invalid IAsyncResult");
987 if (!result.IsCompleted)
988 result.AsyncWaitHandle.WaitOne();
990 Interlocked.Decrement (ref pendingEnds);
992 req.CheckIfThrowDelayedException();
995 public int EndReceive(IAsyncResult result) {
996 if (disposed && closed)
997 throw new ObjectDisposedException (GetType ().ToString ());
1000 throw new ArgumentNullException ("result");
1002 SocketAsyncResult req = result as SocketAsyncResult;
1004 throw new ArgumentException ("Invalid IAsyncResult");
1006 if (!result.IsCompleted)
1007 result.AsyncWaitHandle.WaitOne();
1009 Interlocked.Decrement (ref pendingEnds);
1011 req.CheckIfThrowDelayedException();
1012 return(req.Worker.Total);
1015 public int EndReceiveFrom(IAsyncResult result,
1016 ref EndPoint end_point) {
1017 if (disposed && closed)
1018 throw new ObjectDisposedException (GetType ().ToString ());
1021 throw new ArgumentNullException ("result");
1023 SocketAsyncResult req = result as SocketAsyncResult;
1025 throw new ArgumentException ("Invalid IAsyncResult");
1027 if (!result.IsCompleted)
1028 result.AsyncWaitHandle.WaitOne();
1030 Interlocked.Decrement (ref pendingEnds);
1032 req.CheckIfThrowDelayedException();
1033 end_point=req.Worker.EndPoint;
1034 return(req.Worker.Total);
1037 public int EndSend(IAsyncResult result) {
1038 if (disposed && closed)
1039 throw new ObjectDisposedException (GetType ().ToString ());
1042 throw new ArgumentNullException ("result");
1044 SocketAsyncResult req = result as SocketAsyncResult;
1046 throw new ArgumentException ("Invalid IAsyncResult");
1048 if (!result.IsCompleted)
1049 result.AsyncWaitHandle.WaitOne();
1051 Interlocked.Decrement (ref pendingEnds);
1053 req.CheckIfThrowDelayedException();
1054 return(req.Worker.Total);
1057 public int EndSendTo(IAsyncResult result) {
1058 if (disposed && closed)
1059 throw new ObjectDisposedException (GetType ().ToString ());
1062 throw new ArgumentNullException ("result");
1064 SocketAsyncResult req = result as SocketAsyncResult;
1066 throw new ArgumentException ("Invalid IAsyncResult");
1068 if (!result.IsCompleted)
1069 result.AsyncWaitHandle.WaitOne();
1071 Interlocked.Decrement (ref pendingEnds);
1073 req.CheckIfThrowDelayedException();
1074 return(req.Worker.Total);
1077 void CheckIfClose ()
1079 if (Interlocked.CompareExchange (ref closeDelayed, 0, 1) == 1 &&
1080 Interlocked.CompareExchange (ref pendingEnds, 0, 0) == 0) {
1082 Close_internal(socket);
1086 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1087 private extern static void GetSocketOption_obj_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, out object obj_val);
1088 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1089 private extern static void GetSocketOption_arr_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val);
1091 public object GetSocketOption(SocketOptionLevel level,
1092 SocketOptionName name) {
1095 GetSocketOption_obj_internal(socket, level, name,
1098 if(name==SocketOptionName.Linger) {
1099 return((LingerOption)obj_val);
1100 } else if (name==SocketOptionName.AddMembership ||
1101 name==SocketOptionName.DropMembership) {
1102 return((MulticastOption)obj_val);
1104 return((int)obj_val);
1108 public void GetSocketOption(SocketOptionLevel level,
1109 SocketOptionName name,
1111 int opt_value_len=opt_value.Length;
1113 GetSocketOption_arr_internal(socket, level, name,
1117 public byte[] GetSocketOption(SocketOptionLevel level,
1118 SocketOptionName name,
1120 byte[] byte_val=new byte[length];
1122 GetSocketOption_arr_internal(socket, level, name,
1128 // See Socket.IOControl, WSAIoctl documentation in MSDN. The
1129 // common options between UNIX and Winsock are FIONREAD,
1130 // FIONBIO and SIOCATMARK. Anything else will depend on the
1132 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1133 extern static int WSAIoctl (IntPtr sock, int ioctl_code, byte [] input, byte [] output);
1135 public int IOControl (int ioctl_code, byte [] in_value, byte [] out_value)
1138 throw new ObjectDisposedException (GetType ().ToString ());
1140 int result = WSAIoctl (socket, ioctl_code, in_value, out_value);
1142 throw new InvalidOperationException ("Must use Blocking property instead.");
1147 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1148 private extern static void Listen_internal(IntPtr sock,
1151 public void Listen(int backlog) {
1152 Listen_internal(socket, backlog);
1155 /* The docs for Poll() are a bit lightweight too, but
1156 * it seems to be just a simple wrapper around Select.
1158 public bool Poll(int time_us, SelectMode mode) {
1159 Socket [] socketlist = new Socket []{this};
1163 case SelectMode.SelectError:
1164 Select_internal (ref n, ref n, ref socketlist, time_us);
1166 case SelectMode.SelectRead:
1167 Select_internal (ref socketlist, ref n, ref n, time_us);
1169 case SelectMode.SelectWrite:
1170 Select_internal (ref n, ref socketlist, ref n, time_us);
1173 throw new NotSupportedException();
1176 return (socketlist.Length == 1);
1179 public int Receive(byte[] buf) {
1180 return(Receive(buf, 0, buf.Length, SocketFlags.None));
1183 public int Receive(byte[] buf, SocketFlags flags) {
1184 return(Receive(buf, 0, buf.Length, flags));
1187 public int Receive(byte[] buf, int size, SocketFlags flags) {
1188 return(Receive(buf, 0, size, flags));
1191 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1192 private extern static int Receive_internal(IntPtr sock,
1198 public int Receive(byte[] buf, int offset, int size,
1199 SocketFlags flags) {
1201 throw new ArgumentNullException("buffer is null");
1203 if(offset<0 || offset > buf.Length) {
1204 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
1206 if(size<0 || offset+size > buf.Length) {
1207 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
1213 ret=Receive_internal(socket, buf, offset,
1215 } catch(SocketException) {
1224 public int ReceiveFrom(byte[] buf, ref EndPoint remote_end) {
1225 return(ReceiveFrom(buf, 0, buf.Length,
1226 SocketFlags.None, ref remote_end));
1229 public int ReceiveFrom(byte[] buf, SocketFlags flags,
1230 ref EndPoint remote_end) {
1231 return(ReceiveFrom(buf, 0, buf.Length, flags,
1235 public int ReceiveFrom(byte[] buf, int size, SocketFlags flags,
1236 ref EndPoint remote_end) {
1237 return(ReceiveFrom(buf, 0, size, flags,
1242 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1243 private extern static int RecvFrom_internal(IntPtr sock,
1248 ref SocketAddress sockaddr);
1250 public int ReceiveFrom(byte[] buf, int offset, int size,
1252 ref EndPoint remote_end) {
1254 throw new ArgumentNullException("buffer is null");
1256 if(remote_end==null) {
1257 throw new ArgumentNullException("remote endpoint is null");
1259 if(offset<0 || offset>buf.Length) {
1260 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
1262 if(size<0 || offset+size>buf.Length) {
1263 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
1266 SocketAddress sockaddr=remote_end.Serialize();
1270 count=RecvFrom_internal(socket, buf, offset,
1273 } catch(SocketException) {
1279 // Stupidly, EndPoint.Create() is an
1281 remote_end=remote_end.Create(sockaddr);
1286 public int Send(byte[] buf) {
1287 return(Send(buf, 0, buf.Length, SocketFlags.None));
1290 public int Send(byte[] buf, SocketFlags flags) {
1291 return(Send(buf, 0, buf.Length, flags));
1294 public int Send(byte[] buf, int size, SocketFlags flags) {
1295 return(Send(buf, 0, size, flags));
1298 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1299 private extern static int Send_internal(IntPtr sock,
1300 byte[] buf, int offset,
1304 public int Send (byte[] buf, int offset, int size, SocketFlags flags)
1307 throw new ArgumentNullException ("buffer");
1309 if (offset < 0 || offset > buf.Length)
1310 throw new ArgumentOutOfRangeException ("offset");
1312 if (size < 0 || offset + size > buf.Length)
1313 throw new ArgumentOutOfRangeException ("size");
1321 ret = Send_internal (socket, buf, offset, size, flags);
1322 } catch (SocketException) {
1331 public int SendTo(byte[] buffer, EndPoint remote_end) {
1332 return(SendTo(buffer, 0, buffer.Length,
1333 SocketFlags.None, remote_end));
1336 public int SendTo(byte[] buffer, SocketFlags flags,
1337 EndPoint remote_end) {
1338 return(SendTo(buffer, 0, buffer.Length, flags,
1342 public int SendTo(byte[] buffer, int size, SocketFlags flags,
1343 EndPoint remote_end) {
1344 return(SendTo(buffer, 0, size, flags, remote_end));
1348 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1349 private extern static int SendTo_internal(IntPtr sock,
1356 public int SendTo(byte[] buffer, int offset, int size,
1357 SocketFlags flags, EndPoint remote_end) {
1359 throw new ArgumentNullException("buffer is null");
1361 if(remote_end==null) {
1362 throw new ArgumentNullException("remote endpoint is null");
1364 if(offset<0 || offset>buffer.Length) {
1365 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
1367 if(size<0 || offset+size>buffer.Length) {
1368 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
1371 SocketAddress sockaddr=remote_end.Serialize();
1376 ret=SendTo_internal(socket, buffer, offset,
1377 size, flags, sockaddr);
1379 catch(SocketException) {
1388 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1389 private extern static void SetSocketOption_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, object obj_val, byte[] byte_val, int int_val);
1391 public void SetSocketOption(SocketOptionLevel level,
1392 SocketOptionName name,
1394 SetSocketOption_internal(socket, level, name, null,
1398 public void SetSocketOption(SocketOptionLevel level,
1399 SocketOptionName name,
1401 SetSocketOption_internal(socket, level, name, null,
1405 public void SetSocketOption(SocketOptionLevel level,
1406 SocketOptionName name,
1408 if(opt_value==null) {
1409 throw new ArgumentNullException();
1412 /* Passing a bool as the third parameter to
1413 * SetSocketOption causes this overload to be
1414 * used when in fact we want to pass the value
1415 * to the runtime as an int.
1417 if(opt_value is System.Boolean) {
1418 bool bool_val=(bool)opt_value;
1420 /* Stupid casting rules :-( */
1421 if(bool_val==true) {
1422 SetSocketOption_internal(socket, level,
1426 SetSocketOption_internal(socket, level,
1431 SetSocketOption_internal(socket, level, name,
1432 opt_value, null, 0);
1436 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1437 private extern static void Shutdown_internal(IntPtr socket, SocketShutdown how);
1439 public void Shutdown(SocketShutdown how) {
1440 Shutdown_internal(socket, how);
1443 public override int GetHashCode ()
1445 return (int) socket;
1448 private bool disposed;
1450 protected virtual void Dispose(bool explicitDisposing) {
1454 if (!explicitDisposing) {
1456 Close_internal (socket);
1460 if (Interlocked.CompareExchange (ref pendingEnds, 0, 0) == 0) {
1462 Close_internal (socket);
1464 Interlocked.CompareExchange (ref closeDelayed, 1, 0);
1469 void IDisposable.Dispose ()
1472 GC.SuppressFinalize (this);