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,
433 public static void Select(IList read_list, IList write_list,
434 IList err_list, int time_us) {
435 if(read_list==null &&
438 throw new ArgumentNullException();
441 int read_count = 0, write_count = 0, err_count = 0;
442 Socket[] read_arr = null;
443 Socket[] write_arr = null;
444 Socket[] err_arr = null;
447 read_count=read_list.Count;
450 read_arr=new Socket[read_count];
452 if (write_list!=null)
453 write_count=write_list.Count;
455 if (write_count != 0)
456 write_arr=new Socket[write_count];
459 err_count=err_list.Count;
462 err_arr=new Socket[err_count];
466 if (read_count != 0) {
469 foreach (Socket s in read_list) {
475 if (write_count != 0) {
477 foreach (Socket s in write_list) {
483 if (err_count != 0) {
485 foreach (Socket s in err_list) {
493 Select_internal(ref read_arr, ref write_arr,
494 ref err_arr, time_us, out error);
497 throw new SocketException (error);
500 if(read_list!=null) {
502 for(i=0; i<read_arr.Length; i++) {
503 read_list.Add(read_arr[i]);
507 if(write_list!=null) {
509 for(i=0; i<write_arr.Length; i++) {
510 write_list.Add(write_arr[i]);
516 for(i=0; i<err_arr.Length; i++) {
517 err_list.Add(err_arr[i]);
526 ass=Assembly.Load("Mono.Posix");
527 } catch (FileNotFoundException) {
531 unixendpointtype=ass.GetType("Mono.Posix.UnixEndPoint");
533 /* The endpoint Create() method is an instance
536 Type[] arg_types=new Type[1];
537 arg_types[0]=typeof(string);
538 ConstructorInfo cons=unixendpointtype.GetConstructor(arg_types);
540 object[] args=new object[1];
543 unixendpoint=cons.Invoke(args);
546 // private constructor used by Accept, which already
547 // has a socket handle to use
548 private Socket(AddressFamily family, SocketType type,
549 ProtocolType proto, IntPtr sock) {
550 address_family=family;
558 // Creates a new system socket, returning the handle
559 [MethodImplAttribute(MethodImplOptions.InternalCall)]
560 private extern IntPtr Socket_internal(AddressFamily family,
565 public Socket(AddressFamily family, SocketType type,
566 ProtocolType proto) {
567 address_family=family;
573 socket=Socket_internal(family, type, proto, out error);
575 throw new SocketException (error);
579 public AddressFamily AddressFamily {
581 return(address_family);
585 // Returns the amount of data waiting to be read on socket
586 [MethodImplAttribute(MethodImplOptions.InternalCall)]
587 private extern static int Available_internal(IntPtr socket,
590 public int Available {
592 if (disposed && closed)
593 throw new ObjectDisposedException (GetType ().ToString ());
597 ret = Available_internal(socket, out error);
600 throw new SocketException (error);
607 [MethodImplAttribute(MethodImplOptions.InternalCall)]
608 private extern static void Blocking_internal(IntPtr socket,
612 public bool Blocking {
619 Blocking_internal(socket, value, out error);
622 throw new SocketException (error);
629 public bool Connected {
635 public IntPtr Handle {
641 // Returns the local endpoint details in addr and port
642 [MethodImplAttribute(MethodImplOptions.InternalCall)]
643 private extern static SocketAddress LocalEndPoint_internal(IntPtr socket, out int error);
645 [MonoTODO("Support non-IP endpoints")]
646 public EndPoint LocalEndPoint {
648 if (disposed && closed)
649 throw new ObjectDisposedException (GetType ().ToString ());
654 sa=LocalEndPoint_internal(socket, out error);
657 throw new SocketException (error);
660 if(sa.Family==AddressFamily.InterNetwork || sa.Family==AddressFamily.InterNetworkV6) {
661 // Stupidly, EndPoint.Create() is an
663 return new IPEndPoint(0, 0).Create(sa);
664 } else if (sa.Family==AddressFamily.Unix &&
665 unixendpoint!=null) {
666 return((EndPoint)unixendpointtype.InvokeMember("Create", BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public, null, unixendpoint, new object[] {sa}));
668 throw new NotImplementedException();
673 public ProtocolType ProtocolType {
675 return(protocol_type);
679 // Returns the remote endpoint details in addr and port
680 [MethodImplAttribute(MethodImplOptions.InternalCall)]
681 private extern static SocketAddress RemoteEndPoint_internal(IntPtr socket, out int error);
683 [MonoTODO("Support non-IP endpoints")]
684 public EndPoint RemoteEndPoint {
686 if (disposed && closed)
687 throw new ObjectDisposedException (GetType ().ToString ());
692 sa=RemoteEndPoint_internal(socket, out error);
695 throw new SocketException (error);
698 if(sa.Family==AddressFamily.InterNetwork || sa.Family==AddressFamily.InterNetworkV6 ) {
699 // Stupidly, EndPoint.Create() is an
701 return new IPEndPoint(0, 0).Create(sa);
702 } else if (sa.Family==AddressFamily.Unix &&
703 unixendpoint!=null) {
704 return((EndPoint)unixendpointtype.InvokeMember("Create", BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public, null, unixendpoint, new object[] {sa}));
706 throw new NotImplementedException();
711 public SocketType SocketType {
718 public static bool SupportsIPv4 {
\r
720 CheckProtocolSupport();
\r
721 return ipv4Supported == 1;
\r
725 public static bool SupportsIPv6 {
\r
727 CheckProtocolSupport();
\r
728 return ipv6Supported == 1;
\r
732 internal static bool SupportsIPv4
\r
740 internal static bool SupportsIPv6
\r
749 internal static void CheckProtocolSupport()
751 if(ipv4Supported == -1) {
\r
753 Socket tmp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
\r
763 if(ipv6Supported == -1) {
\r
764 NetConfig config = (NetConfig)System.Configuration.ConfigurationSettings.GetConfig("system.net/settings");
\r
767 ipv6Supported = config.ipv6Enabled?-1:0;
\r
769 if(ipv6Supported != 0) {
\r
771 Socket tmp = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
\r
781 // Creates a new system socket, returning the handle
782 [MethodImplAttribute(MethodImplOptions.InternalCall)]
783 private extern static IntPtr Accept_internal(IntPtr sock,
786 public Socket Accept() {
787 if (disposed && closed)
788 throw new ObjectDisposedException (GetType ().ToString ());
791 IntPtr sock=Accept_internal(socket, out error);
794 throw new SocketException (error);
797 return(new Socket(this.AddressFamily, this.SocketType,
798 this.ProtocolType, sock));
801 public IAsyncResult BeginAccept(AsyncCallback callback,
804 if (disposed && closed)
805 throw new ObjectDisposedException (GetType ().ToString ());
807 Interlocked.Increment (ref pendingEnds);
808 SocketAsyncResult req=new SocketAsyncResult(state);
809 Worker worker=new Worker(this, callback, req);
811 SocketAsyncCall sac = new SocketAsyncCall (worker.Accept);
812 sac.BeginInvoke (null, null);
816 public IAsyncResult BeginConnect(EndPoint end_point,
817 AsyncCallback callback,
820 if (disposed && closed)
821 throw new ObjectDisposedException (GetType ().ToString ());
823 if (end_point == null)
824 throw new ArgumentNullException ("end_point");
826 Interlocked.Increment (ref pendingEnds);
827 SocketAsyncResult req=new SocketAsyncResult(state);
828 Worker worker=new Worker(this, end_point, callback,
831 SocketAsyncCall sac = new SocketAsyncCall (worker.Connect);
832 sac.BeginInvoke (null, null);
836 public IAsyncResult BeginReceive(byte[] buffer, int offset,
838 SocketFlags socket_flags,
839 AsyncCallback callback,
842 if (disposed && closed)
843 throw new ObjectDisposedException (GetType ().ToString ());
846 throw new ArgumentNullException ("buffer");
849 throw new ArgumentOutOfRangeException ("offset must be >= 0");
852 throw new ArgumentOutOfRangeException ("size must be >= 0");
854 if (offset + size > buffer.Length)
855 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
857 Interlocked.Increment (ref pendingEnds);
858 SocketAsyncResult req=new SocketAsyncResult(state);
859 Worker worker=new Worker(this, buffer, offset, size,
860 socket_flags, callback, req);
862 SocketAsyncCall sac = new SocketAsyncCall (worker.Receive);
863 sac.BeginInvoke (null, null);
867 public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset,
869 SocketFlags socket_flags,
870 ref EndPoint remote_end,
871 AsyncCallback callback,
873 if (disposed && closed)
874 throw new ObjectDisposedException (GetType ().ToString ());
877 throw new ArgumentNullException ("buffer");
880 throw new ArgumentOutOfRangeException ("offset must be >= 0");
883 throw new ArgumentOutOfRangeException ("size must be >= 0");
885 if (offset + size > buffer.Length)
886 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
888 Interlocked.Increment (ref pendingEnds);
889 SocketAsyncResult req=new SocketAsyncResult(state);
890 Worker worker=new Worker(this, buffer, offset, size,
891 socket_flags, remote_end,
894 SocketAsyncCall sac = new SocketAsyncCall (worker.ReceiveFrom);
895 sac.BeginInvoke (null, null);
899 public IAsyncResult BeginSend(byte[] buffer, int offset,
901 SocketFlags socket_flags,
902 AsyncCallback callback,
904 if (disposed && closed)
905 throw new ObjectDisposedException (GetType ().ToString ());
908 throw new ArgumentNullException ("buffer");
911 throw new ArgumentOutOfRangeException ("offset must be >= 0");
914 throw new ArgumentOutOfRangeException ("size must be >= 0");
916 if (offset + size > buffer.Length)
917 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
919 Interlocked.Increment (ref pendingEnds);
920 SocketAsyncResult req=new SocketAsyncResult(state);
921 Worker worker=new Worker(this, buffer, offset, size,
922 socket_flags, callback, req);
924 SocketAsyncCall sac = new SocketAsyncCall (worker.Send);
925 sac.BeginInvoke (null, null);
929 public IAsyncResult BeginSendTo(byte[] buffer, int offset,
931 SocketFlags socket_flags,
933 AsyncCallback callback,
935 if (disposed && closed)
936 throw new ObjectDisposedException (GetType ().ToString ());
939 throw new ArgumentNullException ("buffer");
942 throw new ArgumentOutOfRangeException ("offset must be >= 0");
945 throw new ArgumentOutOfRangeException ("size must be >= 0");
947 if (offset + size > buffer.Length)
948 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
950 Interlocked.Increment (ref pendingEnds);
951 SocketAsyncResult req=new SocketAsyncResult(state);
952 Worker worker=new Worker(this, buffer, offset, size,
953 socket_flags, remote_end,
956 SocketAsyncCall sac = new SocketAsyncCall (worker.SendTo);
957 sac.BeginInvoke (null, null);
961 // Creates a new system socket, returning the handle
962 [MethodImplAttribute(MethodImplOptions.InternalCall)]
963 private extern static void Bind_internal(IntPtr sock,
967 public void Bind(EndPoint local_end) {
968 if (disposed && closed)
969 throw new ObjectDisposedException (GetType ().ToString ());
971 if(local_end==null) {
972 throw new ArgumentNullException("local_end");
977 Bind_internal(socket, local_end.Serialize(),
981 throw new SocketException (error);
986 [MethodImplAttribute(MethodImplOptions.InternalCall)]
987 private extern static void Close_internal(IntPtr socket,
990 public void Close() {
991 ((IDisposable) this).Dispose ();
994 // Connects to the remote address
995 [MethodImplAttribute(MethodImplOptions.InternalCall)]
996 private extern static void Connect_internal(IntPtr sock,
1000 public void Connect(EndPoint remote_end) {
1001 if (disposed && closed)
1002 throw new ObjectDisposedException (GetType ().ToString ());
1004 if(remote_end==null) {
1005 throw new ArgumentNullException("remote_end");
1010 Connect_internal(socket, remote_end.Serialize(),
1014 throw new SocketException (error);
1020 public Socket EndAccept(IAsyncResult result) {
1021 if (disposed && closed)
1022 throw new ObjectDisposedException (GetType ().ToString ());
1025 throw new ArgumentNullException ("result");
1027 SocketAsyncResult req = result as SocketAsyncResult;
1029 throw new ArgumentException ("Invalid IAsyncResult");
1031 if (!result.IsCompleted)
1032 result.AsyncWaitHandle.WaitOne();
1034 Interlocked.Decrement (ref pendingEnds);
1036 req.CheckIfThrowDelayedException();
1037 return(req.Worker.Socket);
1040 public void EndConnect(IAsyncResult result) {
1041 if (disposed && closed)
1042 throw new ObjectDisposedException (GetType ().ToString ());
1045 throw new ArgumentNullException ("result");
1047 SocketAsyncResult req = result as SocketAsyncResult;
1049 throw new ArgumentException ("Invalid IAsyncResult");
1051 if (!result.IsCompleted)
1052 result.AsyncWaitHandle.WaitOne();
1054 Interlocked.Decrement (ref pendingEnds);
1056 req.CheckIfThrowDelayedException();
1059 public int EndReceive(IAsyncResult result) {
1060 if (disposed && closed)
1061 throw new ObjectDisposedException (GetType ().ToString ());
1064 throw new ArgumentNullException ("result");
1066 SocketAsyncResult req = result as SocketAsyncResult;
1068 throw new ArgumentException ("Invalid IAsyncResult");
1070 if (!result.IsCompleted)
1071 result.AsyncWaitHandle.WaitOne();
1073 Interlocked.Decrement (ref pendingEnds);
1075 req.CheckIfThrowDelayedException();
1076 return(req.Worker.Total);
1079 public int EndReceiveFrom(IAsyncResult result,
1080 ref EndPoint end_point) {
1081 if (disposed && closed)
1082 throw new ObjectDisposedException (GetType ().ToString ());
1085 throw new ArgumentNullException ("result");
1087 SocketAsyncResult req = result as SocketAsyncResult;
1089 throw new ArgumentException ("Invalid IAsyncResult");
1091 if (!result.IsCompleted)
1092 result.AsyncWaitHandle.WaitOne();
1094 Interlocked.Decrement (ref pendingEnds);
1096 req.CheckIfThrowDelayedException();
1097 end_point=req.Worker.EndPoint;
1098 return(req.Worker.Total);
1101 public int EndSend(IAsyncResult result) {
1102 if (disposed && closed)
1103 throw new ObjectDisposedException (GetType ().ToString ());
1106 throw new ArgumentNullException ("result");
1108 SocketAsyncResult req = result as SocketAsyncResult;
1110 throw new ArgumentException ("Invalid IAsyncResult");
1112 if (!result.IsCompleted)
1113 result.AsyncWaitHandle.WaitOne();
1115 Interlocked.Decrement (ref pendingEnds);
1117 req.CheckIfThrowDelayedException();
1118 return(req.Worker.Total);
1121 public int EndSendTo(IAsyncResult result) {
1122 if (disposed && closed)
1123 throw new ObjectDisposedException (GetType ().ToString ());
1126 throw new ArgumentNullException ("result");
1128 SocketAsyncResult req = result as SocketAsyncResult;
1130 throw new ArgumentException ("Invalid IAsyncResult");
1132 if (!result.IsCompleted)
1133 result.AsyncWaitHandle.WaitOne();
1135 Interlocked.Decrement (ref pendingEnds);
1137 req.CheckIfThrowDelayedException();
1138 return(req.Worker.Total);
1141 void CheckIfClose ()
1143 if (Interlocked.CompareExchange (ref closeDelayed, 0, 1) == 1 &&
1144 Interlocked.CompareExchange (ref pendingEnds, 0, 0) == 0) {
1149 Close_internal(socket, out error);
1152 throw new SocketException (error);
1157 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1158 private extern static void GetSocketOption_obj_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, out object obj_val, out int error);
1159 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1160 private extern static void GetSocketOption_arr_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val, out int error);
1162 public object GetSocketOption(SocketOptionLevel level,
1163 SocketOptionName name) {
1167 GetSocketOption_obj_internal(socket, level, name,
1168 out obj_val, out error);
1171 throw new SocketException (error);
1174 if(name==SocketOptionName.Linger) {
1175 return((LingerOption)obj_val);
1176 } else if (name==SocketOptionName.AddMembership ||
1177 name==SocketOptionName.DropMembership) {
1178 return((MulticastOption)obj_val);
1180 return((int)obj_val);
1184 public void GetSocketOption(SocketOptionLevel level,
1185 SocketOptionName name,
1187 int opt_value_len=opt_value.Length;
1190 GetSocketOption_arr_internal(socket, level, name,
1191 ref opt_value, out error);
1194 throw new SocketException (error);
1198 public byte[] GetSocketOption(SocketOptionLevel level,
1199 SocketOptionName name,
1201 byte[] byte_val=new byte[length];
1204 GetSocketOption_arr_internal(socket, level, name,
1205 ref byte_val, out error);
1208 throw new SocketException (error);
1214 // See Socket.IOControl, WSAIoctl documentation in MSDN. The
1215 // common options between UNIX and Winsock are FIONREAD,
1216 // FIONBIO and SIOCATMARK. Anything else will depend on the
1218 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1219 extern static int WSAIoctl (IntPtr sock, int ioctl_code,
1220 byte [] input, byte [] output,
1223 public int IOControl (int ioctl_code, byte [] in_value,
1227 throw new ObjectDisposedException (GetType ().ToString ());
1230 int result = WSAIoctl (socket, ioctl_code, in_value,
1231 out_value, out error);
1234 throw new SocketException (error);
1238 throw new InvalidOperationException ("Must use Blocking property instead.");
1243 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1244 private extern static void Listen_internal(IntPtr sock,
1248 public void Listen(int backlog) {
1251 Listen_internal(socket, backlog, out error);
1254 throw new SocketException (error);
1258 /* The docs for Poll() are a bit lightweight too, but
1259 * it seems to be just a simple wrapper around Select.
1261 public bool Poll(int time_us, SelectMode mode) {
1262 Socket [] socketlist = new Socket []{this};
1267 case SelectMode.SelectError:
1268 Select_internal (ref n, ref n, ref socketlist,
1269 time_us, out error);
1271 case SelectMode.SelectRead:
1272 Select_internal (ref socketlist, ref n, ref n,
1273 time_us, out error);
1275 case SelectMode.SelectWrite:
1276 Select_internal (ref n, ref socketlist, ref n,
1277 time_us, out error);
1280 throw new NotSupportedException();
1284 throw new SocketException (error);
1287 return (socketlist.Length == 1);
1290 public int Receive(byte[] buf) {
1291 return(Receive(buf, 0, buf.Length, SocketFlags.None));
1294 public int Receive(byte[] buf, SocketFlags flags) {
1295 return(Receive(buf, 0, buf.Length, flags));
1298 public int Receive(byte[] buf, int size, SocketFlags flags) {
1299 return(Receive(buf, 0, size, flags));
1302 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1303 private extern static int Receive_internal(IntPtr sock,
1310 public int Receive(byte[] buf, int offset, int size,
1311 SocketFlags flags) {
1313 throw new ArgumentNullException("buffer is null");
1315 if(offset<0 || offset > buf.Length) {
1316 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
1318 if(size<0 || offset+size > buf.Length) {
1319 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
1324 ret=Receive_internal(socket, buf, offset, size, flags,
1329 throw new SocketException (error);
1337 public int ReceiveFrom(byte[] buf, ref EndPoint remote_end) {
1338 return(ReceiveFrom(buf, 0, buf.Length,
1339 SocketFlags.None, ref remote_end));
1342 public int ReceiveFrom(byte[] buf, SocketFlags flags,
1343 ref EndPoint remote_end) {
1344 return(ReceiveFrom(buf, 0, buf.Length, flags,
1348 public int ReceiveFrom(byte[] buf, int size, SocketFlags flags,
1349 ref EndPoint remote_end) {
1350 return(ReceiveFrom(buf, 0, size, flags,
1355 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1356 private extern static int RecvFrom_internal(IntPtr sock,
1361 ref SocketAddress sockaddr,
1364 public int ReceiveFrom(byte[] buf, int offset, int size,
1366 ref EndPoint remote_end) {
1368 throw new ArgumentNullException("buffer is null");
1370 if(remote_end==null) {
1371 throw new ArgumentNullException("remote endpoint is null");
1373 if(offset<0 || offset>buf.Length) {
1374 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
1376 if(size<0 || offset+size>buf.Length) {
1377 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
1380 SocketAddress sockaddr=remote_end.Serialize();
1383 count=RecvFrom_internal(socket, buf, offset, size,
1384 flags, ref sockaddr,
1389 throw new SocketException (error);
1393 // Stupidly, EndPoint.Create() is an
1395 remote_end=remote_end.Create(sockaddr);
1400 public int Send(byte[] buf) {
1401 return(Send(buf, 0, buf.Length, SocketFlags.None));
1404 public int Send(byte[] buf, SocketFlags flags) {
1405 return(Send(buf, 0, buf.Length, flags));
1408 public int Send(byte[] buf, int size, SocketFlags flags) {
1409 return(Send(buf, 0, size, flags));
1412 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1413 private extern static int Send_internal(IntPtr sock,
1414 byte[] buf, int offset,
1419 public int Send (byte[] buf, int offset, int size, SocketFlags flags)
1422 throw new ArgumentNullException ("buffer");
1424 if (offset < 0 || offset > buf.Length)
1425 throw new ArgumentOutOfRangeException ("offset");
1427 if (size < 0 || offset + size > buf.Length)
1428 throw new ArgumentOutOfRangeException ("size");
1435 ret = Send_internal (socket, buf, offset, size, flags,
1440 throw new SocketException (error);
1447 public int SendTo(byte[] buffer, EndPoint remote_end) {
1448 return(SendTo(buffer, 0, buffer.Length,
1449 SocketFlags.None, remote_end));
1452 public int SendTo(byte[] buffer, SocketFlags flags,
1453 EndPoint remote_end) {
1454 return(SendTo(buffer, 0, buffer.Length, flags,
1458 public int SendTo(byte[] buffer, int size, SocketFlags flags,
1459 EndPoint remote_end) {
1460 return(SendTo(buffer, 0, size, flags, remote_end));
1464 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1465 private extern static int SendTo_internal(IntPtr sock,
1473 public int SendTo(byte[] buffer, int offset, int size,
1474 SocketFlags flags, EndPoint remote_end) {
1476 throw new ArgumentNullException("buffer is null");
1478 if(remote_end==null) {
1479 throw new ArgumentNullException("remote endpoint is null");
1481 if(offset<0 || offset>buffer.Length) {
1482 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
1484 if(size<0 || offset+size>buffer.Length) {
1485 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
1488 SocketAddress sockaddr=remote_end.Serialize();
1492 ret=SendTo_internal(socket, buffer, offset, size,
1493 flags, sockaddr, out error);
1497 throw new SocketException (error);
1504 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1505 private extern static void SetSocketOption_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, object obj_val, byte[] byte_val, int int_val, out int error);
1507 public void SetSocketOption(SocketOptionLevel level,
1508 SocketOptionName name,
1512 SetSocketOption_internal(socket, level, name, null,
1513 opt_value, 0, out error);
1516 throw new SocketException (error);
1520 public void SetSocketOption(SocketOptionLevel level,
1521 SocketOptionName name,
1525 SetSocketOption_internal(socket, level, name, null,
1526 null, opt_value, out error);
1529 throw new SocketException (error);
1533 public void SetSocketOption(SocketOptionLevel level,
1534 SocketOptionName name,
1536 if(opt_value==null) {
1537 throw new ArgumentNullException();
1542 /* Passing a bool as the third parameter to
1543 * SetSocketOption causes this overload to be
1544 * used when in fact we want to pass the value
1545 * to the runtime as an int.
1547 if(opt_value is System.Boolean) {
1548 bool bool_val=(bool)opt_value;
1550 /* Stupid casting rules :-( */
1551 if(bool_val==true) {
1552 SetSocketOption_internal(socket, level,
1557 SetSocketOption_internal(socket, level,
1563 SetSocketOption_internal(socket, level, name,
1569 throw new SocketException (error);
1573 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1574 private extern static void Shutdown_internal(IntPtr socket, SocketShutdown how, out int error);
1576 public void Shutdown(SocketShutdown how) {
1579 Shutdown_internal(socket, how, out error);
1582 throw new SocketException (error);
1586 public override int GetHashCode ()
1588 return (int) socket;
1591 private bool disposed;
1593 protected virtual void Dispose(bool explicitDisposing) {
1599 if (!explicitDisposing) {
1601 Close_internal (socket, out error);
1604 throw new SocketException (error);
1610 if (Interlocked.CompareExchange (ref pendingEnds, 0, 0) == 0) {
1612 Close_internal (socket, out error);
1615 throw new SocketException (error);
1618 Interlocked.CompareExchange (ref closeDelayed, 1, 0);
1623 void IDisposable.Dispose ()
1626 GC.SuppressFinalize (this);