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)
7 // Sridhar Kulkarni (sridharkulkarni@gmail.com)
8 // Brian Nickel (brian.nickel@gmail.com)
10 // Copyright (C) 2001, 2002 Phillip Pearson and Ximian, Inc.
11 // http://www.myelin.co.nz
12 // (c) 2004-2011 Novell, Inc. (http://www.novell.com)
16 // Permission is hereby granted, free of charge, to any person obtaining
17 // a copy of this software and associated documentation files (the
18 // "Software"), to deal in the Software without restriction, including
19 // without limitation the rights to use, copy, modify, merge, publish,
20 // distribute, sublicense, and/or sell copies of the Software, and to
21 // permit persons to whom the Software is furnished to do so, subject to
22 // the following conditions:
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 using System.Collections;
39 using System.Collections.Generic;
40 using System.Runtime.CompilerServices;
41 using System.Runtime.InteropServices;
42 using System.Threading;
44 using System.Security;
48 using System.Net.Configuration;
49 using System.Net.NetworkInformation;
51 #if MOONLIGHT && !INSIDE_SYSTEM
52 using System.Net.Policy;
55 namespace System.Net.Sockets {
57 public partial class Socket : IDisposable {
58 [StructLayout (LayoutKind.Sequential)]
64 // Used by the runtime
65 internal enum SocketOperation {
82 [StructLayout (LayoutKind.Sequential)]
83 internal sealed class SocketAsyncResult: IAsyncResult
85 /* Same structure in the runtime */
87 Keep this in sync with MonoSocketAsyncResult in
88 metadata/socket-io.h and ProcessAsyncReader
89 in System.Diagnostics/Process.cs.
95 AsyncCallback callback; // used from the runtime
96 WaitHandle waithandle;
98 Exception delayedException;
100 public EndPoint EndPoint; // Connect,ReceiveFrom,SendTo
101 public byte [] Buffer; // Receive,ReceiveFrom,Send,SendTo
102 public int Offset; // Receive,ReceiveFrom,Send,SendTo
103 public int Size; // Receive,ReceiveFrom,Send,SendTo
104 public SocketFlags SockFlags; // Receive,ReceiveFrom,Send,SendTo
105 public Socket AcceptSocket; // AcceptReceive
106 public IPAddress[] Addresses; // Connect
107 public int Port; // Connect
108 public IList<ArraySegment<byte>> Buffers; // Receive, Send
109 public bool ReuseSocket; // Disconnect
117 public bool blocking;
119 public SocketOperation operation;
121 public int EndCalled;
123 // These fields are not in MonoSocketAsyncResult
124 public Worker Worker;
125 public int CurrentAddress; // Connect
127 public SocketAsyncResult ()
131 public void Init (Socket sock, object state, AsyncCallback callback, SocketOperation operation)
135 this.blocking = sock.blocking;
136 this.handle = sock.socket;
138 this.blocking = true;
139 this.handle = IntPtr.Zero;
142 this.callback = callback;
143 GC.KeepAlive (this.callback);
144 this.operation = operation;
145 SockFlags = SocketFlags.None;
146 if (waithandle != null)
147 ((ManualResetEvent) waithandle).Reset ();
149 delayedException = null;
164 completed_sync = false;
173 public void DoMConnectCallback ()
175 if (callback == null)
178 ThreadPool.QueueUserWorkItem (_ => { callback (this); }, null);
180 ThreadPool.UnsafeQueueUserWorkItem (_ => { callback (this); }, null);
184 public void Dispose ()
186 Init (null, null, null, 0);
187 if (waithandle != null) {
193 public SocketAsyncResult (Socket sock, object state, AsyncCallback callback, SocketOperation operation)
196 this.blocking = sock.blocking;
197 this.handle = sock.socket;
199 this.callback = callback;
200 GC.KeepAlive (this.callback);
201 this.operation = operation;
202 SockFlags = SocketFlags.None;
203 Worker = new Worker (this);
206 public void CheckIfThrowDelayedException ()
208 if (delayedException != null) {
209 Sock.connected = false;
210 throw delayedException;
214 Sock.connected = false;
215 throw new SocketException (error);
219 void CompleteAllOnDispose (Queue queue)
221 object [] pending = queue.ToArray ();
225 for (int i = 0; i < pending.Length; i++) {
226 Worker worker = (Worker) pending [i];
227 SocketAsyncResult ares = worker.result;
228 cb = new WaitCallback (ares.CompleteDisposed);
230 ThreadPool.QueueUserWorkItem (cb, null);
232 ThreadPool.UnsafeQueueUserWorkItem (cb, null);
237 void CompleteDisposed (object unused)
242 public void Complete ()
244 if (operation != SocketOperation.Receive && Sock.disposed)
245 delayedException = new ObjectDisposedException (Sock.GetType ().ToString ());
250 if (operation == SocketOperation.Receive ||
251 operation == SocketOperation.ReceiveFrom ||
252 operation == SocketOperation.ReceiveGeneric ||
253 operation == SocketOperation.Accept) {
255 } else if (operation == SocketOperation.Send ||
256 operation == SocketOperation.SendTo ||
257 operation == SocketOperation.SendGeneric) {
263 Worker worker = null;
264 SocketAsyncCall sac = null;
266 // queue.Count will only be 0 if the socket is closed while receive/send/accept
267 // operation(s) are pending and at least one call to this method is
268 // waiting on the lock while another one calls CompleteAllOnDispose()
270 queue.Dequeue (); // remove ourselves
271 if (queue.Count > 0) {
272 worker = (Worker) queue.Peek ();
273 if (!Sock.disposed) {
274 sac = Worker.Dispatcher;
276 CompleteAllOnDispose (queue);
282 Socket.socket_pool_queue (sac, worker.result);
284 // IMPORTANT: 'callback', if any is scheduled from unmanaged code
287 public void Complete (bool synch)
289 completed_sync = synch;
293 public void Complete (int total)
299 public void Complete (Exception e, bool synch)
301 completed_sync = synch;
302 delayedException = e;
306 public void Complete (Exception e)
308 delayedException = e;
312 public void Complete (Socket s)
318 public void Complete (Socket s, int total)
325 public object AsyncState {
331 public WaitHandle AsyncWaitHandle {
334 if (waithandle == null)
335 waithandle = new ManualResetEvent (completed);
345 public bool CompletedSynchronously {
347 return(completed_sync);
351 public bool IsCompleted {
358 if (waithandle != null && value) {
359 ((ManualResetEvent) waithandle).Set ();
365 public Socket Socket {
372 get { return total; }
373 set { total = value; }
376 public SocketError ErrorCode {
378 SocketException ex = delayedException as SocketException;
380 return(ex.SocketErrorCode);
383 return((SocketError)error);
385 return(SocketError.Success);
390 internal sealed class Worker
392 public SocketAsyncResult result;
393 SocketAsyncEventArgs args;
395 public Worker (SocketAsyncEventArgs args)
398 result = new SocketAsyncResult ();
399 result.Worker = this;
402 public Worker (SocketAsyncResult ares)
407 public void Dispose ()
409 if (result != null) {
416 public static SocketAsyncCall Dispatcher = new SocketAsyncCall (DispatcherCB);
418 static void DispatcherCB (SocketAsyncResult sar)
420 SocketOperation op = sar.operation;
421 if (op == Socket.SocketOperation.Receive || op == Socket.SocketOperation.ReceiveGeneric ||
422 op == Socket.SocketOperation.RecvJustCallback)
423 sar.Worker.Receive ();
424 else if (op == Socket.SocketOperation.Send || op == Socket.SocketOperation.SendGeneric ||
425 op == Socket.SocketOperation.SendJustCallback)
428 else if (op == Socket.SocketOperation.ReceiveFrom)
429 sar.Worker.ReceiveFrom ();
430 else if (op == Socket.SocketOperation.SendTo)
431 sar.Worker.SendTo ();
433 else if (op == Socket.SocketOperation.Connect)
434 sar.Worker.Connect ();
436 else if (op == Socket.SocketOperation.Accept)
437 sar.Worker.Accept ();
438 else if (op == Socket.SocketOperation.AcceptReceive)
439 sar.Worker.AcceptReceive ();
440 else if (op == Socket.SocketOperation.Disconnect)
441 sar.Worker.Disconnect ();
443 // SendPackets and ReceiveMessageFrom are not implemented yet
445 else if (op == Socket.SocketOperation.ReceiveMessageFrom)
446 async_op = SocketAsyncOperation.ReceiveMessageFrom;
447 else if (op == Socket.SocketOperation.SendPackets)
448 async_op = SocketAsyncOperation.SendPackets;
452 throw new NotImplementedException (String.Format ("Operation {0} is not implemented", op));
455 /* This is called when reusing a SocketAsyncEventArgs */
456 public void Init (Socket sock, SocketAsyncEventArgs args, SocketOperation op)
458 result.Init (sock, args, SocketAsyncEventArgs.Dispatcher, op);
459 result.Worker = this;
460 SocketAsyncOperation async_op;
463 // -SocketOperation.AcceptReceive not used in SocketAsyncEventArgs
464 // -SendPackets and ReceiveMessageFrom are not implemented yet
465 if (op == Socket.SocketOperation.Connect)
466 async_op = SocketAsyncOperation.Connect;
468 else if (op == Socket.SocketOperation.Accept)
469 async_op = SocketAsyncOperation.Accept;
470 else if (op == Socket.SocketOperation.Disconnect)
471 async_op = SocketAsyncOperation.Disconnect;
473 else if (op == Socket.SocketOperation.Receive || op == Socket.SocketOperation.ReceiveGeneric)
474 async_op = SocketAsyncOperation.Receive;
476 else if (op == Socket.SocketOperation.ReceiveFrom)
477 async_op = SocketAsyncOperation.ReceiveFrom;
480 else if (op == Socket.SocketOperation.ReceiveMessageFrom)
481 async_op = SocketAsyncOperation.ReceiveMessageFrom;
483 else if (op == Socket.SocketOperation.Send || op == Socket.SocketOperation.SendGeneric)
484 async_op = SocketAsyncOperation.Send;
487 else if (op == Socket.SocketOperation.SendPackets)
488 async_op = SocketAsyncOperation.SendPackets;
490 else if (op == Socket.SocketOperation.SendTo)
491 async_op = SocketAsyncOperation.SendTo;
494 throw new NotImplementedException (String.Format ("Operation {0} is not implemented", op));
496 args.SetLastOperation (async_op);
497 args.SocketError = SocketError.Success;
498 args.BytesTransferred = 0;
501 public void Accept ()
504 Socket acc_socket = null;
506 if (args != null && args.AcceptSocket != null) {
507 result.Sock.Accept (args.AcceptSocket);
508 acc_socket = args.AcceptSocket;
510 acc_socket = result.Sock.Accept ();
512 args.AcceptSocket = acc_socket;
514 } catch (Exception e) {
519 result.Complete (acc_socket);
523 /* only used in 2.0 profile and newer, but
524 * leave in older profiles to keep interface
525 * to runtime consistent
527 public void AcceptReceive ()
530 Socket acc_socket = null;
532 if (result.AcceptSocket == null) {
533 acc_socket = result.Sock.Accept ();
535 acc_socket = result.AcceptSocket;
536 result.Sock.Accept (acc_socket);
538 } catch (Exception e) {
543 /* It seems the MS runtime
544 * special-cases 0-length requested
545 * receive data. See bug 464201.
548 if (result.Size > 0) {
551 total = acc_socket.Receive_nochecks (result.Buffer,
557 result.Complete (new SocketException ((int) error));
560 } catch (Exception e) {
566 result.Complete (acc_socket, total);
570 public void Connect ()
572 if (result.EndPoint == null) {
573 result.Complete (new SocketException ((int)SocketError.AddressNotAvailable));
577 SocketAsyncResult mconnect = result.AsyncState as SocketAsyncResult;
579 bool is_mconnect = (mconnect != null && mconnect.Addresses != null);
581 if (result.ErrorCode == SocketError.AccessDenied) {
583 result.DoMConnectCallback ();
586 bool is_mconnect = false;
590 EndPoint ep = result.EndPoint;
591 error_code = (int) result.Sock.GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
592 if (error_code == 0) {
595 result.Sock.seed_endpoint = ep;
596 result.Sock.connected = true;
597 result.Sock.isbound = true;
598 result.Sock.connect_in_progress = false;
602 result.DoMConnectCallback ();
607 result.Sock.connect_in_progress = false;
608 result.Complete (new SocketException (error_code));
612 if (mconnect.CurrentAddress >= mconnect.Addresses.Length) {
613 mconnect.Complete (new SocketException (error_code));
615 mconnect.DoMConnectCallback ();
618 mconnect.Sock.BeginMConnect (mconnect);
619 } catch (Exception e) {
620 result.Sock.connect_in_progress = false;
625 result.DoMConnectCallback ();
630 /* Also only used in 2.0 profile and newer */
631 public void Disconnect ()
636 result.ReuseSocket = args.DisconnectReuseSocket;
637 result.Sock.Disconnect (result.ReuseSocket);
638 } catch (Exception e) {
646 public void Receive ()
648 if (result.operation == SocketOperation.ReceiveGeneric) {
652 // Actual recv() done in the runtime
656 public void ReceiveFrom ()
661 total = result.Sock.ReceiveFrom_nochecks (result.Buffer,
665 ref result.EndPoint);
666 } catch (Exception e) {
671 result.Complete (total);
675 public void ReceiveGeneric ()
679 total = result.Sock.Receive (result.Buffers, result.SockFlags);
680 } catch (Exception e) {
684 result.Complete (total);
689 void UpdateSendValues (int last_sent)
691 if (result.error == 0) {
692 send_so_far += last_sent;
693 result.Offset += last_sent;
694 result.Size -= last_sent;
700 if (result.operation == SocketOperation.SendGeneric) {
704 // Actual send() done in the runtime
705 if (result.error == 0) {
706 UpdateSendValues (result.Total);
707 if (result.Sock.disposed) {
712 if (result.Size > 0) {
713 Socket.socket_pool_queue (Worker.Dispatcher, result);
714 return; // Have to finish writing everything. See bug #74475.
716 result.Total = send_so_far;
722 public void SendTo ()
727 total = result.Sock.SendTo_nochecks (result.Buffer,
733 UpdateSendValues (total);
734 if (result.Size > 0) {
735 Socket.socket_pool_queue (Worker.Dispatcher, result);
736 return; // Have to finish writing everything. See bug #74475.
738 result.Total = send_so_far;
740 } catch (Exception e) {
750 public void SendGeneric ()
754 total = result.Sock.Send (result.Buffers, result.SockFlags);
755 } catch (Exception e) {
759 result.Complete (total);
763 private Queue readQ = new Queue (2);
764 private Queue writeQ = new Queue (2);
766 internal delegate void SocketAsyncCall (SocketAsyncResult sar);
769 * These two fields are looked up by name by the runtime, don't change
770 * their name without also updating the runtime code.
772 private static int ipv4Supported = -1, ipv6Supported = -1;
777 // initialize ipv4Supported and ipv6Supported
778 CheckProtocolSupport ();
781 internal static void CheckProtocolSupport ()
783 if(ipv4Supported == -1) {
785 Socket tmp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
794 if (ipv6Supported == -1) {
796 #if CONFIGURATION_DEP
797 SettingsSection config;
798 config = (SettingsSection) System.Configuration.ConfigurationManager.GetSection ("system.net/settings");
800 ipv6Supported = config.Ipv6.Enabled ? -1 : 0;
802 NetConfig config = System.Configuration.ConfigurationSettings.GetConfig("system.net/settings") as NetConfig;
804 ipv6Supported = config.ipv6Enabled ? -1 : 0;
807 if (ipv6Supported != 0) {
809 Socket tmp = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
820 public static bool SupportsIPv4 {
822 CheckProtocolSupport();
823 return ipv4Supported == 1;
827 [ObsoleteAttribute ("Use OSSupportsIPv6 instead")]
828 public static bool SupportsIPv6 {
830 CheckProtocolSupport();
831 return ipv6Supported == 1;
835 public static bool OSSupportsIPv4 {
837 CheckProtocolSupport();
838 return ipv4Supported == 1;
843 public static bool OSSupportsIPv6 {
845 CheckProtocolSupport();
846 return ipv6Supported == 1;
850 public static bool OSSupportsIPv6 {
852 NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces ();
854 foreach (NetworkInterface adapter in nics) {
855 if (adapter.Supports (NetworkInterfaceComponent.IPv6))
863 /* the field "socket" is looked up by name by the runtime */
864 private IntPtr socket;
865 private AddressFamily address_family;
866 private SocketType socket_type;
867 private ProtocolType protocol_type;
868 internal bool blocking=true;
869 List<Thread> blocking_threads;
870 private bool isbound;
871 /* When true, the socket was connected at the time of
872 * the last IO operation
874 private bool connected;
875 /* true if we called Close_internal */
877 internal bool disposed;
878 bool connect_in_progress;
881 * This EndPoint is used when creating new endpoints. Because
882 * there are many types of EndPoints possible,
883 * seed_endpoint.Create(addr) is used for creating new ones.
884 * As such, this value is set on Bind, SentTo, ReceiveFrom,
887 internal EndPoint seed_endpoint = null;
889 void RegisterForBlockingSyscall ()
891 while (blocking_threads == null) {
892 //In the rare event this CAS fail, there's a good chance other thread won, so we're kosher.
893 //In the VERY rare event of all CAS fail together, we pay the full price of of failure.
894 Interlocked.CompareExchange (ref blocking_threads, new List<Thread> (), null);
900 /* We must use a finally block here to make this atomic. */
901 lock (blocking_threads) {
902 blocking_threads.Add (Thread.CurrentThread);
907 /* This must be called from a finally block! */
908 void UnRegisterForBlockingSyscall ()
910 //If this NRE, we're in deep problems because Register Must have
911 lock (blocking_threads) {
912 blocking_threads.Remove (Thread.CurrentThread);
916 void AbortRegisteredThreads () {
917 if (blocking_threads == null)
920 lock (blocking_threads) {
921 foreach (var t in blocking_threads)
922 cancel_blocking_socket_operation (t);
923 blocking_threads.Clear ();
928 // Creates a new system socket, returning the handle
929 [MethodImplAttribute(MethodImplOptions.InternalCall)]
930 private extern IntPtr Socket_internal(AddressFamily family,
936 public Socket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)
938 #if NET_2_1 && !MOBILE
939 switch (addressFamily) {
940 case AddressFamily.InterNetwork: // ok
941 case AddressFamily.InterNetworkV6: // ok
942 case AddressFamily.Unknown: // SocketException will be thrown later (with right error #)
944 // case AddressFamily.Unspecified:
946 throw new ArgumentException ("addressFamily");
949 switch (socketType) {
950 case SocketType.Stream: // ok
951 case SocketType.Unknown: // SocketException will be thrown later (with right error #)
954 throw new ArgumentException ("socketType");
957 switch (protocolType) {
958 case ProtocolType.Tcp: // ok
959 case ProtocolType.Unspecified: // ok
960 case ProtocolType.Unknown: // SocketException will be thrown later (with right error #)
963 throw new ArgumentException ("protocolType");
966 address_family = addressFamily;
967 socket_type = socketType;
968 protocol_type = protocolType;
972 socket = Socket_internal (addressFamily, socketType, protocolType, out error);
974 throw new SocketException (error);
975 #if !NET_2_1 || MOBILE
986 public AddressFamily AddressFamily {
987 get { return address_family; }
991 [MethodImplAttribute(MethodImplOptions.InternalCall)]
992 private extern static void Blocking_internal(IntPtr socket,
997 public bool Blocking {
1002 if (disposed && closed)
1003 throw new ObjectDisposedException (GetType ().ToString ());
1007 Blocking_internal (socket, value, out error);
1010 throw new SocketException (error);
1016 public bool Connected {
1017 get { return connected; }
1018 internal set { connected = value; }
1021 public ProtocolType ProtocolType {
1022 get { return protocol_type; }
1025 public bool NoDelay {
1027 if (disposed && closed)
1028 throw new ObjectDisposedException (GetType ().ToString ());
1032 return (int)(GetSocketOption (
1033 SocketOptionLevel.Tcp,
1034 SocketOptionName.NoDelay)) != 0;
1038 if (disposed && closed)
1039 throw new ObjectDisposedException (GetType ().ToString ());
1044 SocketOptionLevel.Tcp,
1045 SocketOptionName.NoDelay, value ? 1 : 0);
1049 public int ReceiveBufferSize {
1051 if (disposed && closed) {
1052 throw new ObjectDisposedException (GetType ().ToString ());
1054 return((int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer));
1057 if (disposed && closed) {
1058 throw new ObjectDisposedException (GetType ().ToString ());
1061 throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
1064 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, value);
1068 public int SendBufferSize {
1070 if (disposed && closed) {
1071 throw new ObjectDisposedException (GetType ().ToString ());
1073 return((int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendBuffer));
1076 if (disposed && closed) {
1077 throw new ObjectDisposedException (GetType ().ToString ());
1080 throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
1083 SetSocketOption (SocketOptionLevel.Socket,
1084 SocketOptionName.SendBuffer,
1091 if (disposed && closed) {
1092 throw new ObjectDisposedException (GetType ().ToString ());
1097 if (address_family == AddressFamily.InterNetwork) {
1098 ttl_val = (short)((int)GetSocketOption (SocketOptionLevel.IP, SocketOptionName.IpTimeToLive));
1099 } else if (address_family == AddressFamily.InterNetworkV6) {
1100 ttl_val = (short)((int)GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.HopLimit));
1102 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
1108 if (disposed && closed) {
1109 throw new ObjectDisposedException (GetType ().ToString ());
1112 throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
1115 if (address_family == AddressFamily.InterNetwork) {
1116 SetSocketOption (SocketOptionLevel.IP, SocketOptionName.IpTimeToLive, value);
1117 } else if (address_family == AddressFamily.InterNetworkV6) {
1118 SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.HopLimit, value);
1120 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
1125 // Returns the remote endpoint details in addr and port
1126 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1127 private extern static SocketAddress RemoteEndPoint_internal(IntPtr socket, int family, out int error);
1129 public EndPoint RemoteEndPoint {
1131 if (disposed && closed)
1132 throw new ObjectDisposedException (GetType ().ToString ());
1136 return seed_endpoint;
1139 * If the seed EndPoint is null, Connect, Bind,
1140 * etc has not yet been called. MS returns null
1143 if (!connected || seed_endpoint == null)
1149 sa=RemoteEndPoint_internal(socket, (int) address_family, out error);
1152 throw new SocketException (error);
1154 return seed_endpoint.Create (sa);
1158 void Linger (IntPtr handle)
1160 if (!connected || linger_timeout <= 0)
1163 // We don't want to receive any more data
1165 Shutdown_internal (handle, SocketShutdown.Receive, out error);
1169 int seconds = linger_timeout / 1000;
1170 int ms = linger_timeout % 1000;
1172 // If the other end closes, this will return 'true' with 'Available' == 0
1173 Poll_internal (handle, SelectMode.SelectRead, ms * 1000, out error);
1179 LingerOption linger = new LingerOption (true, seconds);
1180 SetSocketOption_internal (handle, SocketOptionLevel.Socket, SocketOptionName.Linger, linger, null, 0, out error);
1181 /* Not needed, we're closing upon return */
1186 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1187 static extern void cancel_blocking_socket_operation (Thread thread);
1189 protected virtual void Dispose (bool disposing)
1195 bool was_connected = connected;
1197 if ((int) socket != -1) {
1201 socket = (IntPtr) (-1);
1203 AbortRegisteredThreads ();
1207 //DateTime start = DateTime.UtcNow;
1208 Close_internal (x, out error);
1209 //Console.WriteLine ("Time spent in Close_internal: {0}ms", (DateTime.UtcNow - start).TotalMilliseconds);
1211 throw new SocketException (error);
1215 #if NET_2_1 || NET_4_0
1216 public void Dispose ()
1218 void IDisposable.Dispose ()
1222 GC.SuppressFinalize (this);
1225 // Closes the socket
1226 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1227 private extern static void Close_internal(IntPtr socket, out int error);
1229 public void Close ()
1232 ((IDisposable) this).Dispose ();
1235 public void Close (int timeout)
1237 linger_timeout = timeout;
1238 ((IDisposable) this).Dispose ();
1241 // Connects to the remote address
1242 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1243 private extern static void Connect_internal(IntPtr sock,
1247 public void Connect (EndPoint remoteEP)
1249 SocketAddress serial = null;
1251 if (disposed && closed)
1252 throw new ObjectDisposedException (GetType ().ToString ());
1254 if (remoteEP == null)
1255 throw new ArgumentNullException ("remoteEP");
1257 IPEndPoint ep = remoteEP as IPEndPoint;
1259 if (ep != null && socket_type != SocketType.Dgram) /* Dgram uses Any to 'disconnect' */
1263 if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any))
1264 throw new SocketException ((int) SocketError.AddressNotAvailable);
1267 if (protocol_type != ProtocolType.Tcp)
1268 throw new SocketException ((int) SocketError.AccessDenied);
1271 throw new InvalidOperationException ();
1273 serial = remoteEP.Serialize ();
1278 RegisterForBlockingSyscall ();
1279 Connect_internal (socket, serial, out error);
1281 UnRegisterForBlockingSyscall ();
1284 if (error == 0 || error == 10035)
1285 seed_endpoint = remoteEP; // Keep the ep around for non-blocking sockets
1289 error = SOCKET_CLOSED;
1290 throw new SocketException (error);
1294 if (socket_type == SocketType.Dgram && (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)))
1304 public bool ReceiveAsync (SocketAsyncEventArgs e)
1306 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1307 if (disposed && closed)
1308 throw new ObjectDisposedException (GetType ().ToString ());
1310 // LAME SPEC: the ArgumentException is never thrown, instead an NRE is
1311 // thrown when e.Buffer and e.BufferList are null (works fine when one is
1312 // set to a valid object)
1313 if (e.Buffer == null && e.BufferList == null)
1314 throw new NullReferenceException ("Either e.Buffer or e.BufferList must be valid buffers.");
1317 SocketOperation op = (e.Buffer != null) ? SocketOperation.Receive : SocketOperation.ReceiveGeneric;
1318 e.Worker.Init (this, e, op);
1319 SocketAsyncResult res = e.Worker.result;
1320 if (e.Buffer != null) {
1321 res.Buffer = e.Buffer;
1322 res.Offset = e.Offset;
1325 res.Buffers = e.BufferList;
1327 res.SockFlags = e.SocketFlags;
1330 readQ.Enqueue (e.Worker);
1331 count = readQ.Count;
1334 // Receive takes care of ReceiveGeneric
1335 socket_pool_queue (Worker.Dispatcher, res);
1341 public bool SendAsync (SocketAsyncEventArgs e)
1343 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1344 if (disposed && closed)
1345 throw new ObjectDisposedException (GetType ().ToString ());
1346 if (e.Buffer == null && e.BufferList == null)
1347 throw new NullReferenceException ("Either e.Buffer or e.BufferList must be valid buffers.");
1350 SocketOperation op = (e.Buffer != null) ? SocketOperation.Send : SocketOperation.SendGeneric;
1351 e.Worker.Init (this, e, op);
1352 SocketAsyncResult res = e.Worker.result;
1353 if (e.Buffer != null) {
1354 res.Buffer = e.Buffer;
1355 res.Offset = e.Offset;
1358 res.Buffers = e.BufferList;
1360 res.SockFlags = e.SocketFlags;
1363 writeQ.Enqueue (e.Worker);
1364 count = writeQ.Count;
1367 // Send takes care of SendGeneric
1368 socket_pool_queue (Worker.Dispatcher, res);
1373 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1374 extern static bool Poll_internal (IntPtr socket, SelectMode mode, int timeout, out int error);
1376 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1377 private extern static int Receive_internal(IntPtr sock,
1384 internal int Receive_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
1387 int ret = Receive_internal (socket, buf, offset, size, flags, out nativeError);
1388 error = (SocketError) nativeError;
1389 if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress) {
1399 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1400 private extern static void GetSocketOption_obj_internal(IntPtr socket,
1401 SocketOptionLevel level, SocketOptionName name, out object obj_val,
1404 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1405 private extern static int Send_internal(IntPtr sock,
1406 byte[] buf, int offset,
1411 internal int Send_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
1414 error = SocketError.Success;
1420 int ret = Send_internal (socket, buf, offset, size, flags, out nativeError);
1422 error = (SocketError)nativeError;
1424 if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress) {
1434 public object GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName)
1436 if (disposed && closed)
1437 throw new ObjectDisposedException (GetType ().ToString ());
1442 GetSocketOption_obj_internal (socket, optionLevel, optionName, out obj_val,
1445 throw new SocketException (error);
1447 if (optionName == SocketOptionName.Linger) {
1448 return((LingerOption)obj_val);
1449 } else if (optionName == SocketOptionName.AddMembership ||
1450 optionName == SocketOptionName.DropMembership) {
1451 return((MulticastOption)obj_val);
1452 } else if (obj_val is int) {
1453 return((int)obj_val);
1459 [MethodImplAttribute (MethodImplOptions.InternalCall)]
1460 private extern static void Shutdown_internal (IntPtr socket, SocketShutdown how, out int error);
1462 public void Shutdown (SocketShutdown how)
1464 if (disposed && closed)
1465 throw new ObjectDisposedException (GetType ().ToString ());
1468 throw new SocketException (10057); // Not connected
1472 Shutdown_internal (socket, how, out error);
1474 throw new SocketException (error);
1477 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1478 private extern static void SetSocketOption_internal (IntPtr socket, SocketOptionLevel level,
1479 SocketOptionName name, object obj_val,
1480 byte [] byte_val, int int_val,
1483 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int optionValue)
1485 if (disposed && closed)
1486 throw new ObjectDisposedException (GetType ().ToString ());
1490 SetSocketOption_internal (socket, optionLevel, optionName, null,
1491 null, optionValue, out error);
1494 throw new SocketException (error);
1497 private void ThrowIfUpd ()
1499 #if !NET_2_1 || MOBILE
1500 if (protocol_type == ProtocolType.Udp)
1501 throw new SocketException ((int)SocketError.ProtocolOption);
1508 IAsyncResult BeginConnect(EndPoint end_point, AsyncCallback callback, object state)
1510 if (disposed && closed)
1511 throw new ObjectDisposedException (GetType ().ToString ());
1513 if (end_point == null)
1514 throw new ArgumentNullException ("end_point");
1516 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Connect);
1517 req.EndPoint = end_point;
1519 // Bug #75154: Connect() should not succeed for .Any addresses.
1520 if (end_point is IPEndPoint) {
1521 IPEndPoint ep = (IPEndPoint) end_point;
1522 if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)) {
1523 req.Complete (new SocketException ((int) SocketError.AddressNotAvailable), true);
1529 if (connect_in_progress) {
1530 // This could happen when multiple IPs are used
1531 // Calling connect() again will reset the connection attempt and cause
1532 // an error. Better to just close the socket and move on.
1533 connect_in_progress = false;
1534 Close_internal (socket, out error);
1535 socket = Socket_internal (address_family, socket_type, protocol_type, out error);
1537 throw new SocketException (error);
1539 bool blk = blocking;
1542 SocketAddress serial = end_point.Serialize ();
1543 Connect_internal (socket, serial, out error);
1550 req.Complete (true);
1554 if (error != (int) SocketError.InProgress && error != (int) SocketError.WouldBlock) {
1558 req.Complete (new SocketException (error), true);
1565 connect_in_progress = true;
1566 socket_pool_queue (Worker.Dispatcher, req);
1575 IAsyncResult BeginConnect (IPAddress[] addresses, int port, AsyncCallback callback, object state)
1578 if (disposed && closed)
1579 throw new ObjectDisposedException (GetType ().ToString ());
1581 if (addresses == null)
1582 throw new ArgumentNullException ("addresses");
1584 if (addresses.Length == 0)
1585 throw new ArgumentException ("Empty addresses list");
1587 if (this.AddressFamily != AddressFamily.InterNetwork &&
1588 this.AddressFamily != AddressFamily.InterNetworkV6)
1589 throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
1591 if (port <= 0 || port > 65535)
1592 throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
1595 throw new InvalidOperationException ();
1598 SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Connect);
1599 req.Addresses = addresses;
1602 return BeginMConnect (req);
1605 IAsyncResult BeginMConnect (SocketAsyncResult req)
1607 IAsyncResult ares = null;
1608 Exception exc = null;
1609 for (int i = req.CurrentAddress; i < req.Addresses.Length; i++) {
1610 IPAddress addr = req.Addresses [i];
1611 IPEndPoint ep = new IPEndPoint (addr, req.Port);
1613 req.CurrentAddress++;
1614 ares = BeginConnect (ep, null, req);
1615 if (ares.IsCompleted && ares.CompletedSynchronously) {
1616 ((SocketAsyncResult) ares).CheckIfThrowDelayedException ();
1617 req.DoMConnectCallback ();
1620 } catch (Exception e) {
1632 // Returns false when it is ok to use RemoteEndPoint
1633 // true when addresses must be used (and addresses could be null/empty)
1634 bool GetCheckedIPs (SocketAsyncEventArgs e, out IPAddress [] addresses)
1637 #if MOONLIGHT || NET_4_0
1638 // Connect to the first address that match the host name, like:
1639 // http://blogs.msdn.com/ncl/archive/2009/07/20/new-ncl-features-in-net-4-0-beta-2.aspx
1640 // while skipping entries that do not match the address family
1641 DnsEndPoint dep = (e.RemoteEndPoint as DnsEndPoint);
1643 addresses = Dns.GetHostAddresses (dep.Host);
1644 #if MOONLIGHT && !INSIDE_SYSTEM
1645 if (!e.PolicyRestricted && !SecurityManager.HasElevatedPermissions) {
1646 List<IPAddress> valid = new List<IPAddress> ();
1647 foreach (IPAddress a in addresses) {
1648 // if we're not downloading a socket policy then check the policy
1649 // and if we're not running with elevated permissions (SL4 OoB option)
1650 endpoint = new IPEndPoint (a, dep.Port);
1651 if (!CrossDomainPolicyManager.CheckEndPoint (endpoint, e.SocketClientAccessPolicyProtocol))
1655 if (valid.Count == 0)
1656 e.SocketError = SocketError.AccessDenied;
1657 addresses = valid.ToArray ();
1662 e.ConnectByNameError = null;
1663 #if MOONLIGHT && !INSIDE_SYSTEM
1664 if (!e.PolicyRestricted && !SecurityManager.HasElevatedPermissions) {
1665 if (CrossDomainPolicyManager.CheckEndPoint (e.RemoteEndPoint, e.SocketClientAccessPolicyProtocol))
1668 e.SocketError = SocketError.AccessDenied;
1674 return false; // < NET_4_0 -> use remote endpoint
1678 bool ConnectAsyncReal (SocketAsyncEventArgs e)
1680 bool use_remoteep = true;
1681 #if MOONLIGHT || NET_4_0
1682 IPAddress [] addresses = null;
1683 use_remoteep = !GetCheckedIPs (e, out addresses);
1686 bool policy_failed = (e.SocketError == SocketError.AccessDenied);
1689 Worker w = e.Worker;
1690 w.Init (this, e, SocketOperation.Connect);
1691 SocketAsyncResult result = w.result;
1693 if (policy_failed) {
1694 // SocketAsyncEventArgs.Completed must be called
1696 result.EndPoint = e.RemoteEndPoint;
1697 result.error = (int) SocketError.AccessDenied;
1699 socket_pool_queue (Worker.Dispatcher, result);
1703 IAsyncResult ares = null;
1706 result.EndPoint = e.RemoteEndPoint;
1707 ares = BeginConnect (e.RemoteEndPoint, SocketAsyncEventArgs.Dispatcher, e);
1709 #if MOONLIGHT || NET_4_0
1712 DnsEndPoint dep = (e.RemoteEndPoint as DnsEndPoint);
1713 result.Addresses = addresses;
1714 result.Port = dep.Port;
1716 ares = BeginConnect (addresses, dep.Port, SocketAsyncEventArgs.Dispatcher, e);
1719 if (ares.IsCompleted && ares.CompletedSynchronously) {
1720 ((SocketAsyncResult) ares).CheckIfThrowDelayedException ();
1723 } catch (Exception exc) {
1724 result.Complete (exc, true);
1731 public bool ConnectAsync (SocketAsyncEventArgs e)
1733 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1734 if (disposed && closed)
1735 throw new ObjectDisposedException (GetType ().ToString ());
1737 throw new InvalidOperationException ("You may not perform this operation after calling the Listen method.");
1738 if (e.RemoteEndPoint == null)
1739 throw new ArgumentNullException ("remoteEP");
1741 return ConnectAsyncReal (e);
1745 static void CheckConnect (SocketAsyncEventArgs e)
1747 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1749 if (e.RemoteEndPoint == null)
1750 throw new ArgumentNullException ("remoteEP");
1751 if (e.BufferList != null)
1752 throw new ArgumentException ("Multiple buffers cannot be used with this method.");
1755 public bool ConnectAsync (SocketAsyncEventArgs e)
1757 if (disposed && closed)
1758 throw new ObjectDisposedException (GetType ().ToString ());
1761 // if an address family is specified then they must match
1762 AddressFamily raf = e.RemoteEndPoint.AddressFamily;
1763 if ((raf != AddressFamily.Unspecified) && (raf != AddressFamily))
1764 throw new NotSupportedException ("AddressFamily mismatch between socket and endpoint");
1766 // connected, not yet connected or even policy denied, the Socket.RemoteEndPoint is always
1767 // available after the ConnectAsync call
1768 seed_endpoint = e.RemoteEndPoint;
1769 return ConnectAsyncReal (e);
1772 public static bool ConnectAsync (SocketType socketType, ProtocolType protocolType, SocketAsyncEventArgs e)
1774 // exception ordering requires to check before creating the socket (good thing resource wise too)
1777 // create socket based on the endpoint address family (if specified), otherwise default fo IPv4
1778 AddressFamily raf = e.RemoteEndPoint.AddressFamily;
1779 if (raf == AddressFamily.Unspecified)
1780 raf = AddressFamily.InterNetwork;
1781 Socket s = new Socket (raf, socketType, protocolType);
1782 return s.ConnectAsyncReal (e);
1785 public static void CancelConnectAsync (SocketAsyncEventArgs e)
1788 throw new ArgumentNullException ("e");
1790 // FIXME: this is canceling a synchronous connect, not an async one
1791 Socket s = e.ConnectSocket;
1793 s.AbortRegisteredThreads ();
1796 [MethodImplAttribute (MethodImplOptions.InternalCall)]
1797 private extern static int Receive_internal (IntPtr sock, WSABUF[] bufarray, SocketFlags flags, out int error);
1803 int Receive (IList<ArraySegment<byte>> buffers)
1807 ret = Receive (buffers, SocketFlags.None, out error);
1808 if (error != SocketError.Success) {
1809 throw new SocketException ((int)error);
1814 [CLSCompliant (false)]
1820 int Receive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags)
1824 ret = Receive (buffers, socketFlags, out error);
1825 if (error != SocketError.Success) {
1826 throw new SocketException ((int)error);
1831 [CLSCompliant (false)]
1837 int Receive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode)
1839 if (disposed && closed)
1840 throw new ObjectDisposedException (GetType ().ToString ());
1842 if (buffers == null ||
1843 buffers.Count == 0) {
1844 throw new ArgumentNullException ("buffers");
1847 int numsegments = buffers.Count;
1851 /* Only example I can find of sending a byte
1852 * array reference directly into an internal
1854 * System.Runtime.Remoting/System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeSocket.cs,
1855 * so taking a lead from that...
1857 WSABUF[] bufarray = new WSABUF[numsegments];
1858 GCHandle[] gch = new GCHandle[numsegments];
1860 for(int i = 0; i < numsegments; i++) {
1861 ArraySegment<byte> segment = buffers[i];
1863 if (segment.Offset < 0 || segment.Count < 0 ||
1864 segment.Count > segment.Array.Length - segment.Offset)
1865 throw new ArgumentOutOfRangeException ("segment");
1867 gch[i] = GCHandle.Alloc (segment.Array, GCHandleType.Pinned);
1868 bufarray[i].len = segment.Count;
1869 bufarray[i].buf = Marshal.UnsafeAddrOfPinnedArrayElement (segment.Array, segment.Offset);
1873 ret = Receive_internal (socket, bufarray,
1877 for(int i = 0; i < numsegments; i++) {
1878 if (gch[i].IsAllocated) {
1884 errorCode = (SocketError)nativeError;
1888 [MethodImplAttribute (MethodImplOptions.InternalCall)]
1889 private extern static int Send_internal (IntPtr sock, WSABUF[] bufarray, SocketFlags flags, out int error);
1895 int Send (IList<ArraySegment<byte>> buffers)
1899 ret = Send (buffers, SocketFlags.None, out error);
1900 if (error != SocketError.Success) {
1901 throw new SocketException ((int)error);
1911 int Send (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags)
1915 ret = Send (buffers, socketFlags, out error);
1916 if (error != SocketError.Success) {
1917 throw new SocketException ((int)error);
1922 [CLSCompliant (false)]
1928 int Send (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode)
1930 if (disposed && closed)
1931 throw new ObjectDisposedException (GetType ().ToString ());
1932 if (buffers == null)
1933 throw new ArgumentNullException ("buffers");
1934 if (buffers.Count == 0)
1935 throw new ArgumentException ("Buffer is empty", "buffers");
1936 int numsegments = buffers.Count;
1940 WSABUF[] bufarray = new WSABUF[numsegments];
1941 GCHandle[] gch = new GCHandle[numsegments];
1942 for(int i = 0; i < numsegments; i++) {
1943 ArraySegment<byte> segment = buffers[i];
1945 if (segment.Offset < 0 || segment.Count < 0 ||
1946 segment.Count > segment.Array.Length - segment.Offset)
1947 throw new ArgumentOutOfRangeException ("segment");
1949 gch[i] = GCHandle.Alloc (segment.Array, GCHandleType.Pinned);
1950 bufarray[i].len = segment.Count;
1951 bufarray[i].buf = Marshal.UnsafeAddrOfPinnedArrayElement (segment.Array, segment.Offset);
1955 ret = Send_internal (socket, bufarray, socketFlags, out nativeError);
1957 for(int i = 0; i < numsegments; i++) {
1958 if (gch[i].IsAllocated) {
1963 errorCode = (SocketError)nativeError;
1967 Exception InvalidAsyncOp (string method)
1969 return new InvalidOperationException (method + " can only be called once per asynchronous operation");
1977 int EndReceive (IAsyncResult result)
1980 int bytesReceived = EndReceive (result, out error);
1981 if (error != SocketError.Success) {
1982 if (error != SocketError.WouldBlock && error != SocketError.InProgress)
1984 throw new SocketException ((int)error);
1986 return bytesReceived;
1994 int EndReceive (IAsyncResult asyncResult, out SocketError errorCode)
1996 if (disposed && closed)
1997 throw new ObjectDisposedException (GetType ().ToString ());
1999 if (asyncResult == null)
2000 throw new ArgumentNullException ("asyncResult");
2002 SocketAsyncResult req = asyncResult as SocketAsyncResult;
2004 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
2006 if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
2007 throw InvalidAsyncOp ("EndReceive");
2008 if (!asyncResult.IsCompleted)
2009 asyncResult.AsyncWaitHandle.WaitOne ();
2011 errorCode = req.ErrorCode;
2012 // If no socket error occurred, call CheckIfThrowDelayedException in case there are other
2013 // kinds of exceptions that should be thrown.
2014 if (errorCode == SocketError.Success)
2015 req.CheckIfThrowDelayedException();
2025 int EndSend (IAsyncResult result)
2028 int bytesSent = EndSend (result, out error);
2029 if (error != SocketError.Success) {
2030 if (error != SocketError.WouldBlock && error != SocketError.InProgress)
2032 throw new SocketException ((int)error);
2042 int EndSend (IAsyncResult asyncResult, out SocketError errorCode)
2044 if (disposed && closed)
2045 throw new ObjectDisposedException (GetType ().ToString ());
2046 if (asyncResult == null)
2047 throw new ArgumentNullException ("asyncResult");
2049 SocketAsyncResult req = asyncResult as SocketAsyncResult;
2051 throw new ArgumentException ("Invalid IAsyncResult", "result");
2053 if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
2054 throw InvalidAsyncOp ("EndSend");
2055 if (!asyncResult.IsCompleted)
2056 asyncResult.AsyncWaitHandle.WaitOne ();
2058 errorCode = req.ErrorCode;
2059 // If no socket error occurred, call CheckIfThrowDelayedException in case there are other
2060 // kinds of exceptions that should be thrown.
2061 if (errorCode == SocketError.Success)
2062 req.CheckIfThrowDelayedException ();
2067 // Used by Udpclient
2073 int EndReceiveFrom(IAsyncResult result, ref EndPoint end_point)
2075 if (disposed && closed)
2076 throw new ObjectDisposedException (GetType ().ToString ());
2079 throw new ArgumentNullException ("result");
2081 if (end_point == null)
2082 throw new ArgumentNullException ("remote_end");
2084 SocketAsyncResult req = result as SocketAsyncResult;
2086 throw new ArgumentException ("Invalid IAsyncResult", "result");
2088 if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
2089 throw InvalidAsyncOp ("EndReceiveFrom");
2090 if (!result.IsCompleted)
2091 result.AsyncWaitHandle.WaitOne();
2093 req.CheckIfThrowDelayedException();
2094 end_point = req.EndPoint;
2098 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2099 static extern void socket_pool_queue (SocketAsyncCall d, SocketAsyncResult r);