1 // System.Net.Sockets.Socket.cs
4 // Phillip Pearson (pp@myelin.co.nz)
5 // Dick Porter <dick@ximian.com>
6 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
8 // Copyright (C) 2001, 2002 Phillip Pearson and Ximian, Inc.
9 // http://www.myelin.co.nz
10 // (c) 2004 Novell, Inc. (http://www.novell.com)
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 using System.Collections;
37 using System.Runtime.CompilerServices;
38 using System.Runtime.InteropServices;
39 using System.Threading;
40 using System.Reflection;
42 using System.Net.Configuration;
44 namespace System.Net.Sockets
46 public class Socket : IDisposable
48 enum SocketOperation {
61 [StructLayout (LayoutKind.Sequential)]
62 private sealed class SocketAsyncResult: IAsyncResult
64 /* Same structure in the runtime */
68 AsyncCallback callback;
69 WaitHandle waithandle;
71 Exception delayedException;
73 public EndPoint EndPoint; // Connect,ReceiveFrom,SendTo
74 public byte [] Buffer; // Receive,ReceiveFrom,Send,SendTo
75 public int Offset; // Receive,ReceiveFrom,Send,SendTo
76 public int Size; // Receive,ReceiveFrom,Send,SendTo
77 public SocketFlags SockFlags; // Receive,ReceiveFrom,Send,SendTo
87 SocketOperation operation;
90 public SocketAsyncResult (Socket sock, object state, AsyncCallback callback, SocketOperation operation)
93 this.blocking = sock.blocking;
94 this.handle = sock.socket;
96 this.callback = callback;
97 this.operation = operation;
98 SockFlags = SocketFlags.None;
101 public void CheckIfThrowDelayedException ()
103 if (delayedException != null)
104 throw delayedException;
107 throw new SocketException (error);
111 void CompleteAllOnDispose (Queue queue)
113 object [] pending = queue.ToArray ();
117 for (int i = 0; i < pending.Length; i++) {
118 SocketAsyncResult ares = (SocketAsyncResult) pending [i];
119 cb = new WaitCallback (ares.CompleteDisposed);
120 ThreadPool.QueueUserWorkItem (cb, null);
124 void CompleteDisposed (object unused)
129 public void Complete ()
131 if (operation != SocketOperation.Receive && Sock.disposed)
132 delayedException = new ObjectDisposedException (Sock.GetType ().ToString ());
137 if (operation == SocketOperation.Receive || operation == SocketOperation.ReceiveFrom) {
139 } else if (operation == SocketOperation.Send || operation == SocketOperation.SendTo) {
144 SocketAsyncCall sac = null;
145 SocketAsyncResult req = null;
147 queue.Dequeue (); // remove ourselves
148 if (queue.Count > 0) {
149 req = (SocketAsyncResult) queue.Peek ();
150 if (!Sock.disposed) {
151 Worker worker = new Worker (req);
152 sac = GetDelegate (worker, req.operation);
154 CompleteAllOnDispose (queue);
160 sac.BeginInvoke (null, req);
163 if (callback != null)
167 SocketAsyncCall GetDelegate (Worker worker, SocketOperation op)
170 case SocketOperation.Receive:
171 return new SocketAsyncCall (worker.Receive);
172 case SocketOperation.ReceiveFrom:
173 return new SocketAsyncCall (worker.ReceiveFrom);
174 case SocketOperation.Send:
175 return new SocketAsyncCall (worker.Send);
176 case SocketOperation.SendTo:
177 return new SocketAsyncCall (worker.SendTo);
179 return null; // never happens
183 public void Complete (bool synch)
185 completed_sync = synch;
189 public void Complete (int total)
195 public void Complete (Exception e, bool synch)
197 completed_sync = synch;
198 delayedException = e;
202 public void Complete (Exception e)
204 delayedException = e;
208 public void Complete (Socket s)
214 public object AsyncState {
220 public WaitHandle AsyncWaitHandle {
223 if (waithandle == null)
224 waithandle = new ManualResetEvent (completed);
234 public bool CompletedSynchronously {
236 return(completed_sync);
240 public bool IsCompleted {
247 if (waithandle != null && value) {
248 ((ManualResetEvent) waithandle).Set ();
254 public Socket Socket {
261 get { return total; }
262 set { total = value; }
266 private sealed class Worker
268 SocketAsyncResult result;
270 public Worker (SocketAsyncResult ares)
275 public void Accept ()
277 Socket acc_socket = null;
279 acc_socket = result.Sock.Accept ();
280 } catch (Exception e) {
285 result.Complete (acc_socket);
288 public void Connect ()
291 if (!result.Sock.Blocking) {
292 result.Sock.Poll (-1, SelectMode.SelectWrite);
293 int success = (int)result.Sock.GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
295 result.Sock.connected = true;
297 result.Complete (new SocketException (success));
301 result.Sock.Connect (result.EndPoint);
302 result.Sock.connected = true;
304 } catch (Exception e) {
312 public void Receive ()
314 // Actual recv() done in the runtime
318 public void ReceiveFrom ()
322 total = result.Sock.ReceiveFrom_nochecks (result.Buffer,
326 ref result.EndPoint);
327 } catch (Exception e) {
332 result.Complete (total);
337 void UpdateSendValues (int last_sent)
339 if (result.error == 0) {
340 send_so_far += last_sent;
341 result.Offset += last_sent;
342 result.Size -= last_sent;
348 // Actual send() done in the runtime
349 if (result.error == 0) {
350 UpdateSendValues (result.Total);
351 if (result.Sock.disposed) {
356 if (result.Size > 0) {
357 SocketAsyncCall sac = new SocketAsyncCall (this.Send);
358 sac.BeginInvoke (null, result);
359 return; // Have to finish writing everything. See bug #74475.
361 result.Total = send_so_far;
366 public void SendTo ()
370 total = result.Sock.SendTo_nochecks (result.Buffer,
376 UpdateSendValues (total);
377 if (result.Size > 0) {
378 SocketAsyncCall sac = new SocketAsyncCall (this.SendTo);
379 sac.BeginInvoke (null, result);
380 return; // Have to finish writing everything. See bug #74475.
382 result.Total = send_so_far;
383 } catch (Exception e) {
392 /* the field "socket" is looked up by name by the runtime */
393 private IntPtr socket;
394 private AddressFamily address_family;
395 private SocketType socket_type;
396 private ProtocolType protocol_type;
397 internal bool blocking=true;
398 private Queue readQ = new Queue (2);
399 private Queue writeQ = new Queue (2);
401 delegate void SocketAsyncCall ();
403 * These two fields are looked up by name by the runtime, don't change
404 * their name without also updating the runtime code.
406 private static int ipv4Supported = -1, ipv6Supported = -1;
408 /* When true, the socket was connected at the time of
409 * the last IO operation
411 private bool connected=false;
412 /* true if we called Close_internal */
414 internal bool disposed;
417 /* Used in LocalEndPoint and RemoteEndPoint if the
418 * Mono.Posix assembly is available
420 private static object unixendpoint=null;
421 private static Type unixendpointtype=null;
424 static void AddSockets (ArrayList sockets, IList list, string name)
427 foreach (Socket sock in list) {
428 if (sock == null) // MS throws a NullRef
429 throw new ArgumentNullException (name, "Contains a null element");
437 [MethodImplAttribute(MethodImplOptions.InternalCall)]
438 private extern static void Select_internal (ref Socket [] sockets,
442 public static void Select (IList checkRead, IList checkWrite, IList checkError, int microSeconds)
444 ArrayList list = new ArrayList ();
445 AddSockets (list, checkRead, "checkRead");
446 AddSockets (list, checkWrite, "checkWrite");
447 AddSockets (list, checkError, "checkError");
449 if (list.Count == 3) {
450 throw new ArgumentNullException ("checkRead, checkWrite, checkError",
451 "All the lists are null or empty.");
456 * The 'sockets' array contains: READ socket 0-n, null,
457 * WRITE socket 0-n, null,
458 * ERROR socket 0-n, null
460 Socket [] sockets = (Socket []) list.ToArray (typeof (Socket));
461 Select_internal (ref sockets, microSeconds, out error);
464 throw new SocketException (error);
466 if (checkRead != null)
469 if (checkWrite != null)
472 if (checkError != null)
479 int count = sockets.Length;
480 IList currentList = checkRead;
481 for (int i = 0; i < count; i++) {
482 Socket sock = sockets [i];
483 if (sock == null) { // separator
484 currentList = (mode == 0) ? checkWrite : checkError;
489 if (currentList != null) {
490 sock.connected = true;
491 currentList.Add (sock);
500 ass = Assembly.Load (Consts.AssemblyMono_Posix);
501 } catch (FileNotFoundException) {
505 unixendpointtype=ass.GetType("Mono.Posix.UnixEndPoint");
507 /* The endpoint Create() method is an instance
510 Type[] arg_types=new Type[1];
511 arg_types[0]=typeof(string);
512 ConstructorInfo cons=unixendpointtype.GetConstructor(arg_types);
514 object[] args=new object[1];
517 unixendpoint=cons.Invoke(args);
520 // private constructor used by Accept, which already
521 // has a socket handle to use
522 private Socket(AddressFamily family, SocketType type,
523 ProtocolType proto, IntPtr sock) {
524 address_family=family;
532 // Creates a new system socket, returning the handle
533 [MethodImplAttribute(MethodImplOptions.InternalCall)]
534 private extern IntPtr Socket_internal(AddressFamily family,
539 public Socket(AddressFamily family, SocketType type,
540 ProtocolType proto) {
541 address_family=family;
547 socket=Socket_internal(family, type, proto, out error);
549 throw new SocketException (error);
553 public AddressFamily AddressFamily {
555 return(address_family);
559 // Returns the amount of data waiting to be read on socket
560 [MethodImplAttribute(MethodImplOptions.InternalCall)]
561 private extern static int Available_internal(IntPtr socket,
565 public int Available {
567 if (disposed && closed)
568 throw new ObjectDisposedException (GetType ().ToString ());
572 ret = Available_internal(socket, out error);
575 throw new SocketException (error);
582 [MethodImplAttribute(MethodImplOptions.InternalCall)]
583 private extern static void Blocking_internal(IntPtr socket,
587 public bool Blocking {
592 if (disposed && closed)
593 throw new ObjectDisposedException (GetType ().ToString ());
597 Blocking_internal(socket, value, out error);
600 throw new SocketException (error);
607 public bool Connected {
613 public IntPtr Handle {
619 // Returns the local endpoint details in addr and port
620 [MethodImplAttribute(MethodImplOptions.InternalCall)]
621 private extern static SocketAddress LocalEndPoint_internal(IntPtr socket, out int error);
623 [MonoTODO("Support non-IP endpoints")]
624 public EndPoint LocalEndPoint {
626 if (disposed && closed)
627 throw new ObjectDisposedException (GetType ().ToString ());
632 sa=LocalEndPoint_internal(socket, out error);
635 throw new SocketException (error);
638 if(sa.Family==AddressFamily.InterNetwork || sa.Family==AddressFamily.InterNetworkV6) {
639 // Stupidly, EndPoint.Create() is an
641 return new IPEndPoint(0, 0).Create(sa);
642 } else if (sa.Family==AddressFamily.Unix &&
643 unixendpoint!=null) {
644 return((EndPoint)unixendpointtype.InvokeMember("Create", BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public, null, unixendpoint, new object[] {sa}));
646 throw new NotImplementedException();
651 public ProtocolType ProtocolType {
653 return(protocol_type);
657 // Returns the remote endpoint details in addr and port
658 [MethodImplAttribute(MethodImplOptions.InternalCall)]
659 private extern static SocketAddress RemoteEndPoint_internal(IntPtr socket, out int error);
661 [MonoTODO("Support non-IP endpoints")]
662 public EndPoint RemoteEndPoint {
664 if (disposed && closed)
665 throw new ObjectDisposedException (GetType ().ToString ());
670 sa=RemoteEndPoint_internal(socket, out error);
673 throw new SocketException (error);
676 if(sa.Family==AddressFamily.InterNetwork || sa.Family==AddressFamily.InterNetworkV6 ) {
677 // Stupidly, EndPoint.Create() is an
679 return new IPEndPoint(0, 0).Create(sa);
680 } else if (sa.Family==AddressFamily.Unix &&
681 unixendpoint!=null) {
682 return((EndPoint)unixendpointtype.InvokeMember("Create", BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public, null, unixendpoint, new object[] {sa}));
684 throw new NotImplementedException();
689 public SocketType SocketType {
695 public static bool SupportsIPv4 {
697 CheckProtocolSupport();
698 return ipv4Supported == 1;
702 public static bool SupportsIPv6 {
704 CheckProtocolSupport();
705 return ipv6Supported == 1;
710 public int SendTimeout {
712 return (int)GetSocketOption(
713 SocketOptionLevel.Socket,
714 SocketOptionName.SendTimeout);
718 SocketOptionLevel.Socket,
719 SocketOptionName.SendTimeout, value);
723 public int ReceiveTimeout {
725 return (int)GetSocketOption(
726 SocketOptionLevel.Socket,
727 SocketOptionName.ReceiveTimeout);
731 SocketOptionLevel.Socket,
732 SocketOptionName.ReceiveTimeout, value);
736 public bool NoDelay {
738 return (int)(GetSocketOption (
739 SocketOptionLevel.Tcp,
740 SocketOptionName.NoDelay)) != 0;
745 SocketOptionLevel.Tcp,
746 SocketOptionName.NoDelay, value ? 1 : 0);
751 internal static void CheckProtocolSupport()
753 if(ipv4Supported == -1) {
755 Socket tmp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
765 if(ipv6Supported == -1) {
766 #if NET_2_0 && CONFIGURATION_DEP
767 SettingsSection config;
768 config = (SettingsSection) System.Configuration.ConfigurationManager.GetSection ("system.net/settings");
770 ipv6Supported = config.Ipv6.Enabled ? -1 : 0;
772 NetConfig config = (NetConfig)System.Configuration.ConfigurationSettings.GetConfig("system.net/settings");
775 ipv6Supported = config.ipv6Enabled?-1:0;
777 if(ipv6Supported != 0) {
779 Socket tmp = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
789 // Creates a new system socket, returning the handle
790 [MethodImplAttribute(MethodImplOptions.InternalCall)]
791 private extern static IntPtr Accept_internal(IntPtr sock,
794 Thread blocking_thread;
795 public Socket Accept() {
796 if (disposed && closed)
797 throw new ObjectDisposedException (GetType ().ToString ());
800 IntPtr sock = (IntPtr) (-1);
801 blocking_thread = Thread.CurrentThread;
803 sock = Accept_internal(socket, out error);
804 } catch (ThreadAbortException) {
806 Thread.ResetAbort ();
807 error = (int) SocketError.Interrupted;
810 blocking_thread = null;
814 throw new SocketException (error);
817 Socket accepted = new Socket(this.AddressFamily,
819 this.ProtocolType, sock);
821 accepted.Blocking = this.Blocking;
825 public IAsyncResult BeginAccept(AsyncCallback callback,
828 if (disposed && closed)
829 throw new ObjectDisposedException (GetType ().ToString ());
831 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Accept);
832 Worker worker = new Worker (req);
833 SocketAsyncCall sac = new SocketAsyncCall (worker.Accept);
834 sac.BeginInvoke (null, req);
838 public IAsyncResult BeginConnect(EndPoint end_point,
839 AsyncCallback callback,
842 if (disposed && closed)
843 throw new ObjectDisposedException (GetType ().ToString ());
845 if (end_point == null)
846 throw new ArgumentNullException ("end_point");
848 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Connect);
849 req.EndPoint = end_point;
851 // Bug #75154: Connect() should not succeed for .Any addresses.
852 if (end_point is IPEndPoint) {
853 IPEndPoint ep = (IPEndPoint) end_point;
854 if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)) {
855 req.Complete (new SocketException ((int) SocketError.AddressNotAvailable), true);
862 SocketAddress serial = end_point.Serialize ();
863 Connect_internal (socket, serial, out error);
868 } else if (error != (int) SocketError.InProgress && error != (int) SocketError.WouldBlock) {
871 req.Complete (new SocketException (error), true);
875 if (blocking || error == (int) SocketError.InProgress || error == (int) SocketError.WouldBlock) {
878 Worker worker = new Worker (req);
879 SocketAsyncCall sac = new SocketAsyncCall (worker.Connect);
880 sac.BeginInvoke (null, req);
886 public IAsyncResult BeginReceive(byte[] buffer, int offset,
888 SocketFlags socket_flags,
889 AsyncCallback callback,
892 if (disposed && closed)
893 throw new ObjectDisposedException (GetType ().ToString ());
896 throw new ArgumentNullException ("buffer");
898 if (offset < 0 || offset > buffer.Length)
899 throw new ArgumentOutOfRangeException ("offset");
901 if (size < 0 || offset + size > buffer.Length)
902 throw new ArgumentOutOfRangeException ("size");
904 SocketAsyncResult req;
906 req = new SocketAsyncResult (this, state, callback, SocketOperation.Receive);
910 req.SockFlags = socket_flags;
912 if (readQ.Count == 1) {
913 Worker worker = new Worker (req);
914 SocketAsyncCall sac = new SocketAsyncCall (worker.Receive);
915 sac.BeginInvoke (null, req);
922 public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset,
924 SocketFlags socket_flags,
925 ref EndPoint remote_end,
926 AsyncCallback callback,
928 if (disposed && closed)
929 throw new ObjectDisposedException (GetType ().ToString ());
932 throw new ArgumentNullException ("buffer");
935 throw new ArgumentOutOfRangeException ("offset must be >= 0");
938 throw new ArgumentOutOfRangeException ("size must be >= 0");
940 if (offset + size > buffer.Length)
941 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
943 SocketAsyncResult req;
945 req = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveFrom);
949 req.SockFlags = socket_flags;
950 req.EndPoint = remote_end;
952 if (readQ.Count == 1) {
953 Worker worker = new Worker (req);
954 SocketAsyncCall sac = new SocketAsyncCall (worker.ReceiveFrom);
955 sac.BeginInvoke (null, req);
961 public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socket_flags,
962 AsyncCallback callback, object state)
964 if (disposed && closed)
965 throw new ObjectDisposedException (GetType ().ToString ());
968 throw new ArgumentNullException ("buffer");
971 throw new ArgumentOutOfRangeException ("offset must be >= 0");
974 throw new ArgumentOutOfRangeException ("size must be >= 0");
976 if (offset + size > buffer.Length)
977 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
979 SocketAsyncResult req;
981 req = new SocketAsyncResult (this, state, callback, SocketOperation.Send);
985 req.SockFlags = socket_flags;
986 writeQ.Enqueue (req);
987 if (writeQ.Count == 1) {
988 Worker worker = new Worker (req);
989 SocketAsyncCall sac = new SocketAsyncCall (worker.Send);
990 sac.BeginInvoke (null, req);
996 public IAsyncResult BeginSendTo(byte[] buffer, int offset,
998 SocketFlags socket_flags,
1000 AsyncCallback callback,
1002 if (disposed && closed)
1003 throw new ObjectDisposedException (GetType ().ToString ());
1006 throw new ArgumentNullException ("buffer");
1009 throw new ArgumentOutOfRangeException ("offset must be >= 0");
1012 throw new ArgumentOutOfRangeException ("size must be >= 0");
1014 if (offset + size > buffer.Length)
1015 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
1017 SocketAsyncResult req;
1019 req = new SocketAsyncResult (this, state, callback, SocketOperation.SendTo);
1020 req.Buffer = buffer;
1021 req.Offset = offset;
1023 req.SockFlags = socket_flags;
1024 req.EndPoint = remote_end;
1025 writeQ.Enqueue (req);
1026 if (writeQ.Count == 1) {
1027 Worker worker = new Worker (req);
1028 SocketAsyncCall sac = new SocketAsyncCall (worker.SendTo);
1029 sac.BeginInvoke (null, req);
1035 // Creates a new system socket, returning the handle
1036 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1037 private extern static void Bind_internal(IntPtr sock,
1041 public void Bind(EndPoint local_end) {
1042 if (disposed && closed)
1043 throw new ObjectDisposedException (GetType ().ToString ());
1045 if(local_end==null) {
1046 throw new ArgumentNullException("local_end");
1051 Bind_internal(socket, local_end.Serialize(),
1055 throw new SocketException (error);
1059 // Closes the socket
1060 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1061 private extern static void Close_internal(IntPtr socket,
1064 public void Close() {
1065 ((IDisposable) this).Dispose ();
1068 // Connects to the remote address
1069 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1070 private extern static void Connect_internal(IntPtr sock,
1074 public void Connect(EndPoint remote_end) {
1075 if (disposed && closed)
1076 throw new ObjectDisposedException (GetType ().ToString ());
1078 if(remote_end==null) {
1079 throw new ArgumentNullException("remote_end");
1082 if (remote_end is IPEndPoint) {
1083 IPEndPoint ep = (IPEndPoint) remote_end;
1084 if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any))
1085 throw new SocketException ((int) SocketError.AddressNotAvailable);
1088 SocketAddress serial = remote_end.Serialize ();
1091 blocking_thread = Thread.CurrentThread;
1093 Connect_internal (socket, serial, out error);
1094 } catch (ThreadAbortException) {
1096 Thread.ResetAbort ();
1097 error = (int) SocketError.Interrupted;
1100 blocking_thread = null;
1104 throw new SocketException (error);
1110 public Socket EndAccept(IAsyncResult result) {
1111 if (disposed && closed)
1112 throw new ObjectDisposedException (GetType ().ToString ());
1115 throw new ArgumentNullException ("result");
1117 SocketAsyncResult req = result as SocketAsyncResult;
1119 throw new ArgumentException ("Invalid IAsyncResult", "result");
1121 if (!result.IsCompleted)
1122 result.AsyncWaitHandle.WaitOne();
1124 req.CheckIfThrowDelayedException();
1128 public void EndConnect(IAsyncResult result) {
1129 if (disposed && closed)
1130 throw new ObjectDisposedException (GetType ().ToString ());
1133 throw new ArgumentNullException ("result");
1135 SocketAsyncResult req = result as SocketAsyncResult;
1137 throw new ArgumentException ("Invalid IAsyncResult", "result");
1139 if (!result.IsCompleted)
1140 result.AsyncWaitHandle.WaitOne();
1142 req.CheckIfThrowDelayedException();
1145 public int EndReceive(IAsyncResult result) {
1146 if (disposed && closed)
1147 throw new ObjectDisposedException (GetType ().ToString ());
1150 throw new ArgumentNullException ("result");
1152 SocketAsyncResult req = result as SocketAsyncResult;
1154 throw new ArgumentException ("Invalid IAsyncResult", "result");
1156 if (!result.IsCompleted)
1157 result.AsyncWaitHandle.WaitOne();
1159 req.CheckIfThrowDelayedException();
1163 public int EndReceiveFrom(IAsyncResult result,
1164 ref EndPoint end_point) {
1165 if (disposed && closed)
1166 throw new ObjectDisposedException (GetType ().ToString ());
1169 throw new ArgumentNullException ("result");
1171 SocketAsyncResult req = result as SocketAsyncResult;
1173 throw new ArgumentException ("Invalid IAsyncResult", "result");
1175 if (!result.IsCompleted)
1176 result.AsyncWaitHandle.WaitOne();
1178 req.CheckIfThrowDelayedException();
1179 end_point = req.EndPoint;
1183 public int EndSend(IAsyncResult result) {
1184 if (disposed && closed)
1185 throw new ObjectDisposedException (GetType ().ToString ());
1188 throw new ArgumentNullException ("result");
1190 SocketAsyncResult req = result as SocketAsyncResult;
1192 throw new ArgumentException ("Invalid IAsyncResult", "result");
1194 if (!result.IsCompleted)
1195 result.AsyncWaitHandle.WaitOne();
1197 req.CheckIfThrowDelayedException();
1201 public int EndSendTo(IAsyncResult result) {
1202 if (disposed && closed)
1203 throw new ObjectDisposedException (GetType ().ToString ());
1206 throw new ArgumentNullException ("result");
1208 SocketAsyncResult req = result as SocketAsyncResult;
1210 throw new ArgumentException ("Invalid IAsyncResult", "result");
1212 if (!result.IsCompleted)
1213 result.AsyncWaitHandle.WaitOne();
1215 req.CheckIfThrowDelayedException();
1219 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1220 private extern static void GetSocketOption_obj_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, out object obj_val, out int error);
1221 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1222 private extern static void GetSocketOption_arr_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val, out int error);
1224 public object GetSocketOption (SocketOptionLevel level, SocketOptionName name)
1226 if (disposed && closed)
1227 throw new ObjectDisposedException (GetType ().ToString ());
1232 GetSocketOption_obj_internal(socket, level, name,
1233 out obj_val, out error);
1236 throw new SocketException (error);
1239 if(name==SocketOptionName.Linger) {
1240 return((LingerOption)obj_val);
1241 } else if (name==SocketOptionName.AddMembership ||
1242 name==SocketOptionName.DropMembership) {
1243 return((MulticastOption)obj_val);
1244 } else if (obj_val is int) {
1245 return((int)obj_val);
1251 public void GetSocketOption (SocketOptionLevel level, SocketOptionName name, byte [] opt_value)
1253 if (disposed && closed)
1254 throw new ObjectDisposedException (GetType ().ToString ());
1258 GetSocketOption_arr_internal(socket, level, name,
1259 ref opt_value, out error);
1262 throw new SocketException (error);
1266 public byte [] GetSocketOption (SocketOptionLevel level, SocketOptionName name, int length)
1268 if (disposed && closed)
1269 throw new ObjectDisposedException (GetType ().ToString ());
1271 byte[] byte_val=new byte[length];
1274 GetSocketOption_arr_internal(socket, level, name,
1275 ref byte_val, out error);
1278 throw new SocketException (error);
1284 // See Socket.IOControl, WSAIoctl documentation in MSDN. The
1285 // common options between UNIX and Winsock are FIONREAD,
1286 // FIONBIO and SIOCATMARK. Anything else will depend on the
1288 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1289 extern static int WSAIoctl (IntPtr sock, int ioctl_code,
1290 byte [] input, byte [] output,
1293 public int IOControl (int ioctl_code, byte [] in_value, byte [] out_value)
1296 throw new ObjectDisposedException (GetType ().ToString ());
1299 int result = WSAIoctl (socket, ioctl_code, in_value,
1300 out_value, out error);
1303 throw new SocketException (error);
1307 throw new InvalidOperationException ("Must use Blocking property instead.");
1312 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1313 private extern static void Listen_internal(IntPtr sock,
1317 public void Listen (int backlog)
1319 if (disposed && closed)
1320 throw new ObjectDisposedException (GetType ().ToString ());
1324 Listen_internal(socket, backlog, out error);
1327 throw new SocketException (error);
1331 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1332 extern static bool Poll_internal (IntPtr socket, SelectMode mode, int timeout, out int error);
1334 public bool Poll (int time_us, SelectMode mode)
1336 if (disposed && closed)
1337 throw new ObjectDisposedException (GetType ().ToString ());
1339 if (mode != SelectMode.SelectRead &&
1340 mode != SelectMode.SelectWrite &&
1341 mode != SelectMode.SelectError)
1342 throw new NotSupportedException ("'mode' parameter is not valid.");
1345 bool result = Poll_internal (socket, mode, time_us, out error);
1347 throw new SocketException (error);
1349 if (result == true) {
1350 /* Update the connected state; for
1351 * non-blocking Connect()s this is
1352 * when we can find out that the
1353 * connect succeeded.
1361 public int Receive (byte [] buf)
1363 if (disposed && closed)
1364 throw new ObjectDisposedException (GetType ().ToString ());
1367 throw new ArgumentNullException ("buf");
1371 int ret = Receive_nochecks (buf, 0, buf.Length, SocketFlags.None, out error);
1373 if (error != SocketError.Success)
1374 throw new SocketException ((int) error);
1379 public int Receive (byte [] buf, SocketFlags flags)
1381 if (disposed && closed)
1382 throw new ObjectDisposedException (GetType ().ToString ());
1385 throw new ArgumentNullException ("buf");
1389 int ret = Receive_nochecks (buf, 0, buf.Length, flags, out error);
1391 if (error != SocketError.Success) {
1392 if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
1393 throw new SocketException ((int) error, "Operation timed out.");
1394 throw new SocketException ((int) error);
1400 public int Receive (byte [] buf, int size, SocketFlags flags)
1402 if (disposed && closed)
1403 throw new ObjectDisposedException (GetType ().ToString ());
1406 throw new ArgumentNullException ("buf");
1408 if (size < 0 || size > buf.Length)
1409 throw new ArgumentOutOfRangeException ("size");
1413 int ret = Receive_nochecks (buf, 0, size, flags, out error);
1415 if (error != SocketError.Success) {
1416 if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
1417 throw new SocketException ((int) error, "Operation timed out.");
1418 throw new SocketException ((int) error);
1424 public int Receive (byte [] buf, int offset, int size, SocketFlags flags)
1426 if (disposed && closed)
1427 throw new ObjectDisposedException (GetType ().ToString ());
1430 throw new ArgumentNullException ("buf");
1432 if (offset < 0 || offset > buf.Length)
1433 throw new ArgumentOutOfRangeException ("offset");
1435 if (size < 0 || offset + size > buf.Length)
1436 throw new ArgumentOutOfRangeException ("size");
1440 int ret = Receive_nochecks (buf, offset, size, flags, out error);
1442 if (error != SocketError.Success) {
1443 if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
1444 throw new SocketException ((int) error, "Operation timed out.");
1445 throw new SocketException ((int) error);
1452 public int Receive (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
1454 if (disposed && closed)
1455 throw new ObjectDisposedException (GetType ().ToString ());
1458 throw new ArgumentNullException ("buf");
1460 if (offset < 0 || offset > buf.Length)
1461 throw new ArgumentOutOfRangeException ("offset");
1463 if (size < 0 || offset + size > buf.Length)
1464 throw new ArgumentOutOfRangeException ("size");
1466 return Receive_nochecks (buf, offset, size, flags, out error);
1470 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1471 private extern static int Receive_internal(IntPtr sock,
1478 int Receive_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
1481 int ret = Receive_internal (socket, buf, offset, size, flags, out nativeError);
1482 error = (SocketError) nativeError;
1483 if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress)
1491 public int ReceiveFrom (byte [] buf, ref EndPoint remote_end)
1493 if (disposed && closed)
1494 throw new ObjectDisposedException (GetType ().ToString ());
1497 throw new ArgumentNullException ("buf");
1499 if (remote_end == null)
1500 throw new ArgumentNullException ("remote_end");
1502 return ReceiveFrom_nochecks (buf, 0, buf.Length, SocketFlags.None, ref remote_end);
1505 public int ReceiveFrom (byte [] buf, SocketFlags flags, ref EndPoint remote_end)
1507 if (disposed && closed)
1508 throw new ObjectDisposedException (GetType ().ToString ());
1511 throw new ArgumentNullException ("buf");
1513 if (remote_end == null)
1514 throw new ArgumentNullException ("remote_end");
1517 return ReceiveFrom_nochecks (buf, 0, buf.Length, flags, ref remote_end);
1520 public int ReceiveFrom (byte [] buf, int size, SocketFlags flags,
1521 ref EndPoint remote_end)
1523 if (disposed && closed)
1524 throw new ObjectDisposedException (GetType ().ToString ());
1527 throw new ArgumentNullException ("buf");
1529 if (remote_end == null)
1530 throw new ArgumentNullException ("remote_end");
1532 if (size < 0 || size > buf.Length)
1533 throw new ArgumentOutOfRangeException ("size");
1535 return ReceiveFrom_nochecks (buf, 0, size, flags, ref remote_end);
1539 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1540 private extern static int RecvFrom_internal(IntPtr sock,
1545 ref SocketAddress sockaddr,
1548 public int ReceiveFrom (byte [] buf, int offset, int size, SocketFlags flags,
1549 ref EndPoint remote_end)
1551 if (disposed && closed)
1552 throw new ObjectDisposedException (GetType ().ToString ());
1555 throw new ArgumentNullException ("buf");
1557 if (remote_end == null)
1558 throw new ArgumentNullException ("remote_end");
1560 if (offset < 0 || offset > buf.Length)
1561 throw new ArgumentOutOfRangeException ("offset");
1563 if (size < 0 || offset + size > buf.Length)
1564 throw new ArgumentOutOfRangeException ("size");
1566 return ReceiveFrom_nochecks (buf, offset, size, flags, ref remote_end);
1569 int ReceiveFrom_nochecks (byte [] buf, int offset, int size, SocketFlags flags,
1570 ref EndPoint remote_end)
1572 SocketAddress sockaddr = remote_end.Serialize();
1575 cnt = RecvFrom_internal (socket, buf, offset, size, flags, ref sockaddr, out error);
1577 SocketError err = (SocketError) error;
1579 if (err != SocketError.WouldBlock && err != SocketError.InProgress)
1581 else if (err == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
1582 throw new SocketException (error, "Operation timed out.");
1584 throw new SocketException (error);
1589 // If sockaddr is null then we're a connection
1590 // oriented protocol and should ignore the
1591 // remote_end parameter (see MSDN
1592 // documentation for Socket.ReceiveFrom(...) )
1594 if ( sockaddr != null ) {
1595 // Stupidly, EndPoint.Create() is an
1597 remote_end = remote_end.Create (sockaddr);
1603 public int Send (byte [] buf)
1605 if (disposed && closed)
1606 throw new ObjectDisposedException (GetType ().ToString ());
1609 throw new ArgumentNullException ("buf");
1613 int ret = Send_nochecks (buf, 0, buf.Length, SocketFlags.None, out error);
1615 if (error != SocketError.Success)
1616 throw new SocketException ((int) error);
1621 public int Send (byte [] buf, SocketFlags flags)
1623 if (disposed && closed)
1624 throw new ObjectDisposedException (GetType ().ToString ());
1627 throw new ArgumentNullException ("buf");
1631 int ret = Send_nochecks (buf, 0, buf.Length, flags, out error);
1633 if (error != SocketError.Success)
1634 throw new SocketException ((int) error);
1639 public int Send (byte [] buf, int size, SocketFlags flags)
1641 if (disposed && closed)
1642 throw new ObjectDisposedException (GetType ().ToString ());
1645 throw new ArgumentNullException ("buf");
1647 if (size < 0 || size > buf.Length)
1648 throw new ArgumentOutOfRangeException ("size");
1652 int ret = Send_nochecks (buf, 0, size, flags, out error);
1654 if (error != SocketError.Success)
1655 throw new SocketException ((int) error);
1660 public int Send (byte [] buf, int offset, int size, SocketFlags flags)
1662 if (disposed && closed)
1663 throw new ObjectDisposedException (GetType ().ToString ());
1666 throw new ArgumentNullException ("buffer");
1668 if (offset < 0 || offset > buf.Length)
1669 throw new ArgumentOutOfRangeException ("offset");
1671 if (size < 0 || offset + size > buf.Length)
1672 throw new ArgumentOutOfRangeException ("size");
1676 int ret = Send_nochecks (buf, offset, size, flags, out error);
1678 if (error != SocketError.Success)
1679 throw new SocketException ((int) error);
1685 public int Send (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
1687 if (disposed && closed)
1688 throw new ObjectDisposedException (GetType ().ToString ());
1691 throw new ArgumentNullException ("buffer");
1693 if (offset < 0 || offset > buf.Length)
1694 throw new ArgumentOutOfRangeException ("offset");
1696 if (size < 0 || offset + size > buf.Length)
1697 throw new ArgumentOutOfRangeException ("size");
1699 return Send_nochecks (buf, offset, size, flags, out error);
1703 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1704 private extern static int Send_internal(IntPtr sock,
1705 byte[] buf, int offset,
1710 int Send_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
1713 error = SocketError.Success;
1719 int ret = Send_internal (socket, buf, offset, size, flags, out nativeError);
1721 error = (SocketError)nativeError;
1723 if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress)
1731 public int SendTo (byte [] buffer, EndPoint remote_end)
1733 if (disposed && closed)
1734 throw new ObjectDisposedException (GetType ().ToString ());
1737 throw new ArgumentNullException ("buffer");
1739 if (remote_end == null)
1740 throw new ArgumentNullException ("remote_end");
1742 return SendTo_nochecks (buffer, 0, buffer.Length, SocketFlags.None, remote_end);
1745 public int SendTo (byte [] buffer, SocketFlags flags, EndPoint remote_end)
1747 if (disposed && closed)
1748 throw new ObjectDisposedException (GetType ().ToString ());
1751 throw new ArgumentNullException ("buffer");
1753 if (remote_end == null)
1754 throw new ArgumentNullException ("remote_end");
1756 return SendTo_nochecks (buffer, 0, buffer.Length, flags, remote_end);
1759 public int SendTo (byte [] buffer, int size, SocketFlags flags, EndPoint remote_end)
1761 if (disposed && closed)
1762 throw new ObjectDisposedException (GetType ().ToString ());
1765 throw new ArgumentNullException ("buffer");
1767 if (remote_end == null)
1768 throw new ArgumentNullException ("remote_end");
1770 if (size < 0 || size > buffer.Length)
1771 throw new ArgumentOutOfRangeException ("size");
1773 return SendTo_nochecks (buffer, 0, size, flags, remote_end);
1776 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1777 private extern static int SendTo_internal(IntPtr sock,
1785 public int SendTo (byte [] buffer, int offset, int size, SocketFlags flags,
1786 EndPoint remote_end)
1788 if (disposed && closed)
1789 throw new ObjectDisposedException (GetType ().ToString ());
1792 throw new ArgumentNullException ("buffer");
1794 if (remote_end == null)
1795 throw new ArgumentNullException("remote_end");
1797 if (offset < 0 || offset > buffer.Length)
1798 throw new ArgumentOutOfRangeException ("offset");
1800 if (size < 0 || offset + size > buffer.Length)
1801 throw new ArgumentOutOfRangeException ("size");
1803 return SendTo_nochecks (buffer, offset, size, flags, remote_end);
1806 int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags,
1807 EndPoint remote_end)
1809 SocketAddress sockaddr = remote_end.Serialize ();
1813 ret = SendTo_internal (socket, buffer, offset, size, flags, sockaddr, out error);
1815 SocketError err = (SocketError) error;
1817 if (err != SocketError.WouldBlock && err != SocketError.InProgress)
1820 throw new SocketException (error);
1828 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1829 private extern static void SetSocketOption_internal (IntPtr socket, SocketOptionLevel level,
1830 SocketOptionName name, object obj_val,
1831 byte [] byte_val, int int_val,
1834 public void SetSocketOption (SocketOptionLevel level, SocketOptionName name, byte[] opt_value)
1836 if (disposed && closed)
1837 throw new ObjectDisposedException (GetType ().ToString ());
1841 SetSocketOption_internal(socket, level, name, null,
1842 opt_value, 0, out error);
1845 throw new SocketException (error);
1849 public void SetSocketOption (SocketOptionLevel level, SocketOptionName name, int opt_value)
1851 if (disposed && closed)
1852 throw new ObjectDisposedException (GetType ().ToString ());
1856 SetSocketOption_internal(socket, level, name, null,
1857 null, opt_value, out error);
1860 throw new SocketException (error);
1864 public void SetSocketOption (SocketOptionLevel level, SocketOptionName name, object opt_value)
1867 if (disposed && closed)
1868 throw new ObjectDisposedException (GetType ().ToString ());
1870 if(opt_value==null) {
1871 throw new ArgumentNullException();
1875 /* From MS documentation on SetSocketOption: "For an
1876 * option with a Boolean data type, specify a nonzero
1877 * value to enable the option, and a zero value to
1878 * disable the option."
1879 * Booleans are only handled in 2.0
1882 if (opt_value is System.Boolean) {
1884 bool bool_val = (bool) opt_value;
1885 int int_val = (bool_val) ? 1 : 0;
1887 SetSocketOption_internal (socket, level, name, null, null, int_val, out error);
1889 throw new ArgumentException ("Use an integer 1 (true) or 0 (false) instead of a boolean.", "opt_value");
1892 SetSocketOption_internal (socket, level, name, opt_value, null, 0, out error);
1896 throw new SocketException (error);
1900 public void SetSocketOption (SocketOptionLevel level, SocketOptionName name, bool optionValue)
1902 if (disposed && closed)
1903 throw new ObjectDisposedException (GetType ().ToString ());
1906 int int_val = (optionValue) ? 1 : 0;
1907 SetSocketOption_internal (socket, level, name, null, null, int_val, out error);
1909 throw new SocketException (error);
1912 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1913 private extern static void Shutdown_internal(IntPtr socket, SocketShutdown how, out int error);
1915 public void Shutdown (SocketShutdown how)
1917 if (disposed && closed)
1918 throw new ObjectDisposedException (GetType ().ToString ());
1922 Shutdown_internal(socket, how, out error);
1925 throw new SocketException (error);
1929 public override int GetHashCode ()
1931 return (int) socket;
1934 protected virtual void Dispose (bool explicitDisposing)
1941 if ((int) socket != -1) {
1945 socket = (IntPtr) (-1);
1946 Close_internal (x, out error);
1947 if (blocking_thread != null) {
1948 blocking_thread.Abort ();
1949 blocking_thread = null;
1953 throw new SocketException (error);
1957 void IDisposable.Dispose ()
1960 GC.SuppressFinalize (this);