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)
9 // Ludovic Henry (ludovic@xamarin.com)
11 // Copyright (C) 2001, 2002 Phillip Pearson and Ximian, Inc.
12 // http://www.myelin.co.nz
13 // (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;
43 using System.Reflection;
45 using System.Net.Configuration;
48 using System.Net.NetworkInformation;
50 namespace System.Net.Sockets
52 public partial class Socket : IDisposable
54 const int SOCKET_CLOSED_CODE = 10004;
55 const string TIMEOUT_EXCEPTION_MSG = "A connection attempt failed because the connected party did not properly respond" +
56 "after a period of time, or established connection failed because connected host has failed to respond";
59 * These two fields are looked up by name by the runtime, don't change
60 * their name without also updating the runtime code.
62 static int ipv4_supported = -1;
63 static int ipv6_supported = -1;
65 /* true if we called Close_internal */
69 bool use_overlapped_io;
73 AddressFamily address_family;
74 SocketType socket_type;
75 ProtocolType protocol_type;
77 /* the field "safe_handle" is looked up by name by the runtime */
78 internal SafeSocketHandle safe_handle;
81 * This EndPoint is used when creating new endpoints. Because
82 * there are many types of EndPoints possible,
83 * seed_endpoint.Create(addr) is used for creating new ones.
84 * As such, this value is set on Bind, SentTo, ReceiveFrom,
87 internal EndPoint seed_endpoint = null;
89 internal Queue<SocketAsyncWorker> readQ = new Queue<SocketAsyncWorker> (2);
90 internal Queue<SocketAsyncWorker> writeQ = new Queue<SocketAsyncWorker> (2);
92 internal bool is_blocking = true;
93 internal bool is_bound;
95 /* When true, the socket was connected at the time of the last IO operation */
96 internal bool is_connected;
98 internal bool is_disposed;
99 internal bool connect_in_progress;
105 if (ipv4_supported == -1) {
107 Socket tmp = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
116 if (ipv6_supported == -1) {
117 // We need to put a try/catch around ConfigurationManager methods as will always throw an exception
118 // when run in a mono embedded application. This occurs as embedded applications do not have a setup
119 // for application config. The exception is not thrown when called from a normal .NET application.
121 // We, then, need to guard calls to the ConfigurationManager. If the config is not found or throws an
122 // exception, will fall through to the existing Socket / API directly below in the code.
124 // Also note that catching ConfigurationErrorsException specifically would require library dependency
125 // System.Configuration, and wanted to avoid that.
127 #if CONFIGURATION_DEP
129 SettingsSection config;
130 config = (SettingsSection) System.Configuration.ConfigurationManager.GetSection ("system.net/settings");
132 ipv6_supported = config.Ipv6.Enabled ? -1 : 0;
138 NetConfig config = System.Configuration.ConfigurationSettings.GetConfig("system.net/settings") as NetConfig;
140 ipv6_supported = config.ipv6Enabled ? -1 : 0;
146 if (ipv6_supported != 0) {
148 Socket tmp = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
160 // This constructor is used by servers that want to listen for instance on both
161 // ipv4 and ipv6. Mono has historically done that if you use InterNetworkV6 (at
162 // least on Unix), because that is the default behavior unless the IPV6_V6ONLY
163 // option is explicitly set by using setsockopt (sock, IPPROTO_IPV6, IPV6_ONLY)
165 public Socket (SocketType socketType, ProtocolType protocolType)
166 : this (AddressFamily.InterNetworkV6, socketType, protocolType)
171 public Socket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)
173 #if NET_2_1 && !MOBILE
174 switch (addressFamily) {
175 case AddressFamily.InterNetwork: // ok
176 case AddressFamily.InterNetworkV6: // ok
177 case AddressFamily.Unknown: // SocketException will be thrown later (with right error #)
179 // case AddressFamily.Unspecified:
181 throw new ArgumentException ("addressFamily");
184 switch (socketType) {
185 case SocketType.Stream: // ok
186 case SocketType.Unknown: // SocketException will be thrown later (with right error #)
189 throw new ArgumentException ("socketType");
192 switch (protocolType) {
193 case ProtocolType.Tcp: // ok
194 case ProtocolType.Unspecified: // ok
195 case ProtocolType.Unknown: // SocketException will be thrown later (with right error #)
198 throw new ArgumentException ("protocolType");
201 this.address_family = addressFamily;
202 this.socket_type = socketType;
203 this.protocol_type = protocolType;
206 var handle = Socket_internal (addressFamily, socketType, protocolType, out error);
208 this.safe_handle = new SafeSocketHandle (handle, true);
211 throw new SocketException (error);
213 #if !NET_2_1 || MOBILE
219 public Socket (SocketInformation socketInformation)
221 this.is_listening = (socketInformation.Options & SocketInformationOptions.Listening) != 0;
222 this.is_connected = (socketInformation.Options & SocketInformationOptions.Connected) != 0;
223 this.is_blocking = (socketInformation.Options & SocketInformationOptions.NonBlocking) == 0;
224 this.use_overlapped_io = (socketInformation.Options & SocketInformationOptions.UseOnlyOverlappedIO) != 0;
226 var result = Mono.DataConverter.Unpack ("iiiil", socketInformation.ProtocolInformation, 0);
228 this.address_family = (AddressFamily) (int) result [0];
229 this.socket_type = (SocketType) (int) result [1];
230 this.protocol_type = (ProtocolType) (int) result [2];
231 this.is_bound = (ProtocolType) (int) result [3] != 0;
232 this.safe_handle = new SafeSocketHandle ((IntPtr) (long) result [4], true);
238 /* private constructor used by Accept, which already has a socket handle to use */
239 internal Socket(AddressFamily family, SocketType type, ProtocolType proto, SafeSocketHandle safe_handle)
241 this.address_family = family;
242 this.socket_type = type;
243 this.protocol_type = proto;
245 this.safe_handle = safe_handle;
246 this.is_connected = true;
254 void SocketDefaults ()
257 /* Need to test IPv6 further */
258 if (address_family == AddressFamily.InterNetwork
259 // || address_family == AddressFamily.InterNetworkV6
261 /* This is the default, but it probably has nasty side
262 * effects on Linux, as the socket option is kludged by
263 * turning on or off PMTU discovery... */
264 this.DontFragment = false;
267 /* Microsoft sets these to 8192, but we are going to keep them
268 * both to the OS defaults as these have a big performance impact.
269 * on WebClient performance. */
270 // this.ReceiveBufferSize = 8192;
271 // this.SendBufferSize = 8192;
272 } catch (SocketException) {
276 /* Creates a new system socket, returning the handle */
277 [MethodImplAttribute(MethodImplOptions.InternalCall)]
278 extern IntPtr Socket_internal (AddressFamily family, SocketType type, ProtocolType proto, out int error);
284 [ObsoleteAttribute ("Use OSSupportsIPv4 instead")]
285 public static bool SupportsIPv4 {
286 get { return ipv4_supported == 1; }
289 [ObsoleteAttribute ("Use OSSupportsIPv6 instead")]
290 public static bool SupportsIPv6 {
291 get { return ipv6_supported == 1; }
295 public static bool OSSupportsIPv4 {
296 get { return ipv4_supported == 1; }
299 public static bool OSSupportsIPv4 {
301 NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces ();
303 foreach (NetworkInterface adapter in nics) {
304 if (adapter.Supports (NetworkInterfaceComponent.IPv4))
314 public static bool OSSupportsIPv6 {
315 get { return ipv6_supported == 1; }
318 public static bool OSSupportsIPv6 {
320 NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces ();
322 foreach (NetworkInterface adapter in nics) {
323 if (adapter.Supports (NetworkInterfaceComponent.IPv6))
332 public int Available {
334 ThrowIfDisposedAndClosed ();
337 ret = Available_internal (safe_handle, out error);
340 throw new SocketException (error);
346 static int Available_internal (SafeSocketHandle safeHandle, out int error)
348 bool release = false;
350 safeHandle.DangerousAddRef (ref release);
351 return Available_internal (safeHandle.DangerousGetHandle (), out error);
354 safeHandle.DangerousRelease ();
358 /* Returns the amount of data waiting to be read on socket */
359 [MethodImplAttribute(MethodImplOptions.InternalCall)]
360 extern static int Available_internal (IntPtr socket, out int error);
362 public bool DontFragment {
364 ThrowIfDisposedAndClosed ();
366 switch (address_family) {
367 case AddressFamily.InterNetwork:
368 return ((int) GetSocketOption (SocketOptionLevel.IP, SocketOptionName.DontFragment)) != 0;
369 case AddressFamily.InterNetworkV6:
370 return ((int) GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.DontFragment)) != 0;
372 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
376 ThrowIfDisposedAndClosed ();
378 switch (address_family) {
379 case AddressFamily.InterNetwork:
380 SetSocketOption (SocketOptionLevel.IP, SocketOptionName.DontFragment, value ? 1 : 0);
382 case AddressFamily.InterNetworkV6:
383 SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.DontFragment, value ? 1 : 0);
386 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
391 public bool EnableBroadcast {
393 ThrowIfDisposedAndClosed ();
395 if (protocol_type != ProtocolType.Udp)
396 throw new SocketException ((int) SocketError.ProtocolOption);
398 return ((int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Broadcast)) != 0;
401 ThrowIfDisposedAndClosed ();
403 if (protocol_type != ProtocolType.Udp)
404 throw new SocketException ((int) SocketError.ProtocolOption);
406 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Broadcast, value ? 1 : 0);
410 public bool ExclusiveAddressUse {
412 ThrowIfDisposedAndClosed ();
414 return ((int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse)) != 0;
417 ThrowIfDisposedAndClosed ();
420 throw new InvalidOperationException ("Bind has already been called for this socket");
422 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse, value ? 1 : 0);
426 public bool IsBound {
432 public LingerOption LingerState {
434 ThrowIfDisposedAndClosed ();
436 return (LingerOption) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Linger);
439 ThrowIfDisposedAndClosed ();
440 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Linger, value);
444 public bool MulticastLoopback {
446 ThrowIfDisposedAndClosed ();
448 /* Even though this option can be set for TCP sockets on Linux, throw
449 * this exception anyway to be compatible (the MSDN docs say
450 * "Setting this property on a Transmission Control Protocol (TCP)
451 * socket will have no effect." but the MS runtime throws the
453 if (protocol_type == ProtocolType.Tcp)
454 throw new SocketException ((int)SocketError.ProtocolOption);
456 switch (address_family) {
457 case AddressFamily.InterNetwork:
458 return ((int) GetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastLoopback)) != 0;
459 case AddressFamily.InterNetworkV6:
460 return ((int) GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback)) != 0;
462 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
466 ThrowIfDisposedAndClosed ();
468 /* Even though this option can be set for TCP sockets on Linux, throw
469 * this exception anyway to be compatible (the MSDN docs say
470 * "Setting this property on a Transmission Control Protocol (TCP)
471 * socket will have no effect." but the MS runtime throws the
473 if (protocol_type == ProtocolType.Tcp)
474 throw new SocketException ((int)SocketError.ProtocolOption);
476 switch (address_family) {
477 case AddressFamily.InterNetwork:
478 SetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastLoopback, value ? 1 : 0);
480 case AddressFamily.InterNetworkV6:
481 SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback, value ? 1 : 0);
484 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
489 public bool DualMode {
491 if (AddressFamily != AddressFamily.InterNetworkV6)
492 throw new NotSupportedException("This protocol version is not supported");
494 return ((int)GetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only) == 0);
497 if (AddressFamily != AddressFamily.InterNetworkV6)
498 throw new NotSupportedException("This protocol version is not supported");
500 SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, value ? 0 : 1);
504 private bool IsDualMode {
506 return AddressFamily == AddressFamily.InterNetworkV6 && DualMode;
510 [MonoTODO ("This doesn't do anything on Mono yet")]
511 public bool UseOnlyOverlappedIO {
512 get { return use_overlapped_io; }
513 set { use_overlapped_io = value; }
516 public IntPtr Handle {
517 get { return safe_handle.DangerousGetHandle (); }
520 // Wish: support non-IP endpoints.
521 public EndPoint LocalEndPoint {
523 ThrowIfDisposedAndClosed ();
525 /* If the seed EndPoint is null, Connect, Bind, etc has not yet
526 * been called. MS returns null in this case. */
527 if (seed_endpoint == null)
531 SocketAddress sa = LocalEndPoint_internal (safe_handle, (int) address_family, out error);
534 throw new SocketException (error);
536 return seed_endpoint.Create (sa);
540 static SocketAddress LocalEndPoint_internal (SafeSocketHandle safeHandle, int family, out int error)
542 bool release = false;
544 safeHandle.DangerousAddRef (ref release);
545 return LocalEndPoint_internal (safeHandle.DangerousGetHandle (), family, out error);
548 safeHandle.DangerousRelease ();
552 /* Returns the local endpoint details in addr and port */
553 [MethodImplAttribute(MethodImplOptions.InternalCall)]
554 extern static SocketAddress LocalEndPoint_internal (IntPtr socket, int family, out int error);
556 public SocketType SocketType {
557 get { return socket_type; }
560 public int SendTimeout {
562 ThrowIfDisposedAndClosed ();
564 return (int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendTimeout);
567 ThrowIfDisposedAndClosed ();
570 throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than -1");
572 /* According to the MSDN docs we should adjust values between 1 and
573 * 499 to 500, but the MS runtime doesn't do this. */
577 SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, value);
581 public int ReceiveTimeout {
583 ThrowIfDisposedAndClosed ();
585 return (int) GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout);
588 ThrowIfDisposedAndClosed ();
591 throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than -1");
596 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, value);
600 public AddressFamily AddressFamily {
601 get { return address_family; }
604 public bool Blocking {
605 get { return is_blocking; }
607 ThrowIfDisposedAndClosed ();
610 Blocking_internal (safe_handle, value, out error);
613 throw new SocketException (error);
619 static void Blocking_internal (SafeSocketHandle safeHandle, bool block, out int error)
621 bool release = false;
623 safeHandle.DangerousAddRef (ref release);
624 Blocking_internal (safeHandle.DangerousGetHandle (), block, out error);
627 safeHandle.DangerousRelease ();
631 [MethodImplAttribute(MethodImplOptions.InternalCall)]
632 internal extern static void Blocking_internal(IntPtr socket, bool block, out int error);
634 public bool Connected {
635 get { return is_connected; }
636 internal set { is_connected = value; }
639 public ProtocolType ProtocolType {
640 get { return protocol_type; }
643 public bool NoDelay {
645 ThrowIfDisposedAndClosed ();
648 return ((int) GetSocketOption (SocketOptionLevel.Tcp, SocketOptionName.NoDelay)) != 0;
652 ThrowIfDisposedAndClosed ();
655 SetSocketOption (SocketOptionLevel.Tcp, SocketOptionName.NoDelay, value ? 1 : 0);
659 public int ReceiveBufferSize {
661 ThrowIfDisposedAndClosed ();
663 return (int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer);
666 ThrowIfDisposedAndClosed ();
669 throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
671 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, value);
675 public int SendBufferSize {
677 ThrowIfDisposedAndClosed ();
679 return (int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendBuffer);
682 ThrowIfDisposedAndClosed ();
685 throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
687 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendBuffer, value);
693 ThrowIfDisposedAndClosed ();
695 switch (address_family) {
696 case AddressFamily.InterNetwork:
697 return (short) (int) GetSocketOption (SocketOptionLevel.IP, SocketOptionName.IpTimeToLive);
698 case AddressFamily.InterNetworkV6:
699 return (short) (int) GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.HopLimit);
701 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
705 ThrowIfDisposedAndClosed ();
708 throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
710 switch (address_family) {
711 case AddressFamily.InterNetwork:
712 SetSocketOption (SocketOptionLevel.IP, SocketOptionName.IpTimeToLive, value);
714 case AddressFamily.InterNetworkV6:
715 SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.HopLimit, value);
718 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
723 public EndPoint RemoteEndPoint {
725 ThrowIfDisposedAndClosed ();
727 /* If the seed EndPoint is null, Connect, Bind, etc has
728 * not yet been called. MS returns null in this case. */
729 if (!is_connected || seed_endpoint == null)
733 SocketAddress sa = RemoteEndPoint_internal (safe_handle, (int) address_family, out error);
736 throw new SocketException (error);
738 return seed_endpoint.Create (sa);
742 static SocketAddress RemoteEndPoint_internal (SafeSocketHandle safeHandle, int family, out int error)
744 bool release = false;
746 safeHandle.DangerousAddRef (ref release);
747 return RemoteEndPoint_internal (safeHandle.DangerousGetHandle (), family, out error);
750 safeHandle.DangerousRelease ();
754 /* Returns the remote endpoint details in addr and port */
755 [MethodImplAttribute(MethodImplOptions.InternalCall)]
756 extern static SocketAddress RemoteEndPoint_internal (IntPtr socket, int family, out int error);
762 public static void Select (IList checkRead, IList checkWrite, IList checkError, int microSeconds)
764 var list = new List<Socket> ();
765 AddSockets (list, checkRead, "checkRead");
766 AddSockets (list, checkWrite, "checkWrite");
767 AddSockets (list, checkError, "checkError");
770 throw new ArgumentNullException ("checkRead, checkWrite, checkError", "All the lists are null or empty.");
772 /* The 'sockets' array contains:
773 * - READ socket 0-n, null,
774 * - WRITE socket 0-n, null,
775 * - ERROR socket 0-n, null */
776 Socket [] sockets = list.ToArray ();
779 Select_internal (ref sockets, microSeconds, out error);
782 throw new SocketException (error);
784 if (sockets == null) {
785 if (checkRead != null)
787 if (checkWrite != null)
789 if (checkError != null)
795 int count = sockets.Length;
796 IList currentList = checkRead;
798 for (int i = 0; i < count; i++) {
799 Socket sock = sockets [i];
800 if (sock == null) { // separator
801 if (currentList != null) {
802 // Remove non-signaled sockets after the current one
803 int to_remove = currentList.Count - currentIdx;
804 for (int k = 0; k < to_remove; k++)
805 currentList.RemoveAt (currentIdx);
807 currentList = (mode == 0) ? checkWrite : checkError;
813 if (mode == 1 && currentList == checkWrite && !sock.is_connected) {
814 if ((int) sock.GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error) == 0)
815 sock.is_connected = true;
818 /* Remove non-signaled sockets before the current one */
819 while (((Socket) currentList [currentIdx]) != sock)
820 currentList.RemoveAt (currentIdx);
826 static void AddSockets (List<Socket> sockets, IList list, string name)
829 foreach (Socket sock in list) {
830 if (sock == null) // MS throws a NullRef
831 throw new ArgumentNullException ("name", "Contains a null element");
839 [MethodImplAttribute(MethodImplOptions.InternalCall)]
840 extern static void Select_internal (ref Socket [] sockets, int microSeconds, out int error);
846 public bool Poll (int time_us, SelectMode mode)
848 ThrowIfDisposedAndClosed ();
850 if (mode != SelectMode.SelectRead && mode != SelectMode.SelectWrite && mode != SelectMode.SelectError)
851 throw new NotSupportedException ("'mode' parameter is not valid.");
854 bool result = Poll_internal (safe_handle, mode, time_us, out error);
857 throw new SocketException (error);
859 if (mode == SelectMode.SelectWrite && result && !is_connected) {
860 /* Update the is_connected state; for non-blocking Connect()
861 * this is when we can find out that the connect succeeded. */
862 if ((int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error) == 0)
869 static bool Poll_internal (SafeSocketHandle safeHandle, SelectMode mode, int timeout, out int error)
871 bool release = false;
873 safeHandle.DangerousAddRef (ref release);
874 return Poll_internal (safeHandle.DangerousGetHandle (), mode, timeout, out error);
877 safeHandle.DangerousRelease ();
881 [MethodImplAttribute(MethodImplOptions.InternalCall)]
882 extern static bool Poll_internal (IntPtr socket, SelectMode mode, int timeout, out int error);
888 public Socket Accept()
890 ThrowIfDisposedAndClosed ();
893 SafeSocketHandle safe_handle = Accept_internal (this.safe_handle, out error, is_blocking);
897 error = SOCKET_CLOSED_CODE;
898 throw new SocketException(error);
901 Socket accepted = new Socket (this.AddressFamily, this.SocketType, this.ProtocolType, safe_handle) {
902 seed_endpoint = this.seed_endpoint,
903 Blocking = this.Blocking,
909 internal void Accept (Socket acceptSocket)
911 ThrowIfDisposedAndClosed ();
914 SafeSocketHandle safe_handle = Accept_internal (this.safe_handle, out error, is_blocking);
918 error = SOCKET_CLOSED_CODE;
919 throw new SocketException (error);
922 acceptSocket.address_family = this.AddressFamily;
923 acceptSocket.socket_type = this.SocketType;
924 acceptSocket.protocol_type = this.ProtocolType;
925 acceptSocket.safe_handle = safe_handle;
926 acceptSocket.is_connected = true;
927 acceptSocket.seed_endpoint = this.seed_endpoint;
928 acceptSocket.Blocking = this.Blocking;
930 // FIXME: figure out what if anything else needs to be reset
933 public bool AcceptAsync (SocketAsyncEventArgs e)
935 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
937 ThrowIfDisposedAndClosed ();
940 throw new InvalidOperationException ("You must call the Bind method before performing this operation.");
942 throw new InvalidOperationException ("You must call the Listen method before performing this operation.");
943 if (e.BufferList != null)
944 throw new ArgumentException ("Multiple buffers cannot be used with this method.");
946 throw new ArgumentOutOfRangeException ("e.Count");
948 Socket acceptSocket = e.AcceptSocket;
949 if (acceptSocket != null) {
950 if (acceptSocket.is_bound || acceptSocket.is_connected)
951 throw new InvalidOperationException ("AcceptSocket: The socket must not be bound or connected.");
955 e.Worker.Init (this, e, SocketOperation.Accept);
957 SocketAsyncResult sockares = e.Worker.result;
959 QueueSocketAsyncResult (readQ, e.Worker, sockares);
964 public IAsyncResult BeginAccept(AsyncCallback callback, object state)
966 ThrowIfDisposedAndClosed ();
968 if (!is_bound || !is_listening)
969 throw new InvalidOperationException ();
971 SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.Accept);
973 QueueSocketAsyncResult (readQ, sockares.Worker, sockares);
978 public IAsyncResult BeginAccept (int receiveSize, AsyncCallback callback, object state)
980 ThrowIfDisposedAndClosed ();
983 throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
985 SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.AcceptReceive) {
986 Buffer = new byte [receiveSize],
989 SockFlags = SocketFlags.None,
992 QueueSocketAsyncResult (readQ, sockares.Worker, sockares);
997 public IAsyncResult BeginAccept (Socket acceptSocket, int receiveSize, AsyncCallback callback, object state)
999 ThrowIfDisposedAndClosed ();
1001 if (receiveSize < 0)
1002 throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
1004 if (acceptSocket != null) {
1005 ThrowIfDisposedAndClosed (acceptSocket);
1007 if (acceptSocket.IsBound)
1008 throw new InvalidOperationException ();
1010 /* For some reason the MS runtime
1011 * barfs if the new socket is not TCP,
1012 * even though it's just about to blow
1013 * away all those parameters
1015 if (acceptSocket.ProtocolType != ProtocolType.Tcp)
1016 throw new SocketException ((int)SocketError.InvalidArgument);
1019 SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.AcceptReceive) {
1020 Buffer = new byte [receiveSize],
1023 SockFlags = SocketFlags.None,
1024 AcceptSocket = acceptSocket,
1027 QueueSocketAsyncResult (readQ, sockares.Worker, sockares);
1032 public Socket EndAccept (IAsyncResult result)
1036 return EndAccept (out buffer, out bytes, result);
1039 public Socket EndAccept (out byte[] buffer, IAsyncResult asyncResult)
1042 return EndAccept (out buffer, out bytes, asyncResult);
1045 public Socket EndAccept (out byte[] buffer, out int bytesTransferred, IAsyncResult asyncResult)
1047 ThrowIfDisposedAndClosed ();
1049 SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndAccept", "asyncResult");
1051 if (!sockares.IsCompleted)
1052 sockares.AsyncWaitHandle.WaitOne ();
1054 sockares.CheckIfThrowDelayedException ();
1056 buffer = sockares.Buffer;
1057 bytesTransferred = sockares.Total;
1059 return sockares.Socket;
1062 static SafeSocketHandle Accept_internal (SafeSocketHandle safeHandle, out int error, bool blocking)
1065 safeHandle.RegisterForBlockingSyscall ();
1066 var ret = Accept_internal (safeHandle.DangerousGetHandle (), out error, blocking);
1067 return new SafeSocketHandle (ret, true);
1069 safeHandle.UnRegisterForBlockingSyscall ();
1073 /* Creates a new system socket, returning the handle */
1074 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1075 extern static IntPtr Accept_internal (IntPtr sock, out int error, bool blocking);
1081 public void Bind (EndPoint local_end)
1083 ThrowIfDisposedAndClosed ();
1085 if (local_end == null)
1086 throw new ArgumentNullException("local_end");
1089 Bind_internal (safe_handle, local_end.Serialize(), out error);
1092 throw new SocketException (error);
1096 seed_endpoint = local_end;
1099 private static void Bind_internal (SafeSocketHandle safeHandle, SocketAddress sa, out int error)
1101 bool release = false;
1103 safeHandle.DangerousAddRef (ref release);
1104 Bind_internal (safeHandle.DangerousGetHandle (), sa, out error);
1107 safeHandle.DangerousRelease ();
1111 // Creates a new system socket, returning the handle
1112 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1113 private extern static void Bind_internal(IntPtr sock, SocketAddress sa, out int error);
1119 public void Listen (int backlog)
1121 ThrowIfDisposedAndClosed ();
1124 throw new SocketException ((int) SocketError.InvalidArgument);
1127 Listen_internal(safe_handle, backlog, out error);
1130 throw new SocketException (error);
1132 is_listening = true;
1135 static void Listen_internal (SafeSocketHandle safeHandle, int backlog, out int error)
1137 bool release = false;
1139 safeHandle.DangerousAddRef (ref release);
1140 Listen_internal (safeHandle.DangerousGetHandle (), backlog, out error);
1143 safeHandle.DangerousRelease ();
1147 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1148 extern static void Listen_internal (IntPtr sock, int backlog, out int error);
1154 public void Connect (IPAddress address, int port)
1156 Connect (new IPEndPoint (address, port));
1159 public void Connect (string host, int port)
1161 Connect (Dns.GetHostAddresses (host), port);
1164 public void Connect (IPAddress[] addresses, int port)
1166 ThrowIfDisposedAndClosed ();
1168 if (addresses == null)
1169 throw new ArgumentNullException ("addresses");
1170 if (this.AddressFamily != AddressFamily.InterNetwork && this.AddressFamily != AddressFamily.InterNetworkV6)
1171 throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
1173 throw new InvalidOperationException ();
1175 // FIXME: do non-blocking sockets Poll here?
1177 foreach (IPAddress address in addresses) {
1178 IPEndPoint iep = new IPEndPoint (address, port);
1180 Connect_internal (safe_handle, iep.Serialize (), out error);
1182 is_connected = true;
1184 seed_endpoint = iep;
1187 if (error != (int)SocketError.InProgress && error != (int)SocketError.WouldBlock)
1191 Poll (-1, SelectMode.SelectWrite);
1192 error = (int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
1194 is_connected = true;
1196 seed_endpoint = iep;
1203 throw new SocketException (error);
1207 public void Connect (EndPoint remoteEP)
1209 ThrowIfDisposedAndClosed ();
1211 if (remoteEP == null)
1212 throw new ArgumentNullException ("remoteEP");
1214 IPEndPoint ep = remoteEP as IPEndPoint;
1215 /* Dgram uses Any to 'disconnect' */
1216 if (ep != null && socket_type != SocketType.Dgram) {
1217 if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any))
1218 throw new SocketException ((int) SocketError.AddressNotAvailable);
1222 throw new InvalidOperationException ();
1224 SocketAddress serial = remoteEP.Serialize ();
1227 Connect_internal (safe_handle, serial, out error);
1229 if (error == 0 || error == 10035)
1230 seed_endpoint = remoteEP; // Keep the ep around for non-blocking sockets
1234 error = SOCKET_CLOSED_CODE;
1235 throw new SocketException (error);
1238 is_connected = !(socket_type == SocketType.Dgram && ep != null && (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)));
1242 public bool ConnectAsync (SocketAsyncEventArgs e)
1244 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1246 ThrowIfDisposedAndClosed ();
1249 throw new InvalidOperationException ("You may not perform this operation after calling the Listen method.");
1250 if (e.RemoteEndPoint == null)
1251 throw new ArgumentNullException ("remoteEP");
1254 e.Worker.Init (this, e, SocketOperation.Connect);
1256 SocketAsyncResult result = e.Worker.result;
1259 IPAddress [] addresses;
1262 if (!GetCheckedIPs (e, out addresses)) {
1263 result.EndPoint = e.RemoteEndPoint;
1264 ares = BeginConnect (e.RemoteEndPoint, SocketAsyncEventArgs.Dispatcher, e);
1266 DnsEndPoint dep = (e.RemoteEndPoint as DnsEndPoint);
1267 result.Addresses = addresses;
1268 result.Port = dep.Port;
1269 ares = BeginConnect (addresses, dep.Port, SocketAsyncEventArgs.Dispatcher, e);
1272 if (ares.IsCompleted && ares.CompletedSynchronously) {
1273 ((SocketAsyncResult) ares).CheckIfThrowDelayedException ();
1276 } catch (Exception exc) {
1277 result.Complete (exc, true);
1284 public IAsyncResult BeginConnect (IPAddress address, int port, AsyncCallback callback, object state)
1286 ThrowIfDisposedAndClosed ();
1288 if (address == null)
1289 throw new ArgumentNullException ("address");
1290 if (address.ToString ().Length == 0)
1291 throw new ArgumentException ("The length of the IP address is zero");
1292 if (port <= 0 || port > 65535)
1293 throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
1295 throw new InvalidOperationException ();
1297 return BeginConnect (new IPEndPoint (address, port), callback, state);
1300 public IAsyncResult BeginConnect (string host, int port, AsyncCallback callback, object state)
1302 ThrowIfDisposedAndClosed ();
1305 throw new ArgumentNullException ("host");
1306 if (address_family != AddressFamily.InterNetwork && address_family != AddressFamily.InterNetworkV6)
1307 throw new NotSupportedException ("This method is valid only for sockets in the InterNetwork and InterNetworkV6 families");
1308 if (port <= 0 || port > 65535)
1309 throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
1311 throw new InvalidOperationException ();
1313 return BeginConnect (Dns.GetHostAddresses (host), port, callback, state);
1316 public IAsyncResult BeginConnect (EndPoint end_point, AsyncCallback callback, object state)
1318 ThrowIfDisposedAndClosed ();
1320 if (end_point == null)
1321 throw new ArgumentNullException ("end_point");
1323 SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.Connect) {
1324 EndPoint = end_point,
1327 // Bug #75154: Connect() should not succeed for .Any addresses.
1328 if (end_point is IPEndPoint) {
1329 IPEndPoint ep = (IPEndPoint) end_point;
1330 if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)) {
1331 sockares.Complete (new SocketException ((int) SocketError.AddressNotAvailable), true);
1338 if (connect_in_progress) {
1339 // This could happen when multiple IPs are used
1340 // Calling connect() again will reset the connection attempt and cause
1341 // an error. Better to just close the socket and move on.
1342 connect_in_progress = false;
1343 safe_handle.Dispose ();
1344 var handle = Socket_internal (address_family, socket_type, protocol_type, out error);
1345 safe_handle = new SafeSocketHandle (handle, true);
1347 throw new SocketException (error);
1350 bool blk = is_blocking;
1353 Connect_internal (safe_handle, end_point.Serialize (), out error);
1359 is_connected = true;
1361 sockares.Complete (true);
1365 if (error != (int) SocketError.InProgress && error != (int) SocketError.WouldBlock) {
1367 is_connected = false;
1369 sockares.Complete (new SocketException (error), true);
1374 is_connected = false;
1376 connect_in_progress = true;
1378 socket_pool_queue (SocketAsyncWorker.Dispatcher, sockares);
1383 public IAsyncResult BeginConnect (IPAddress[] addresses, int port, AsyncCallback callback, object state)
1385 ThrowIfDisposedAndClosed ();
1387 if (addresses == null)
1388 throw new ArgumentNullException ("addresses");
1389 if (addresses.Length == 0)
1390 throw new ArgumentException ("Empty addresses list");
1391 if (this.AddressFamily != AddressFamily.InterNetwork && this.AddressFamily != AddressFamily.InterNetworkV6)
1392 throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
1393 if (port <= 0 || port > 65535)
1394 throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
1396 throw new InvalidOperationException ();
1398 SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.Connect) {
1399 Addresses = addresses,
1403 is_connected = false;
1405 return BeginMConnect (sockares);
1408 internal IAsyncResult BeginMConnect (SocketAsyncResult sockares)
1410 IAsyncResult ares = null;
1411 Exception exc = null;
1413 for (int i = sockares.CurrentAddress; i < sockares.Addresses.Length; i++) {
1415 sockares.CurrentAddress++;
1417 ares = BeginConnect (new IPEndPoint (sockares.Addresses [i], sockares.Port), null, sockares);
1418 if (ares.IsCompleted && ares.CompletedSynchronously) {
1419 ((SocketAsyncResult) ares).CheckIfThrowDelayedException ();
1420 sockares.DoMConnectCallback ();
1424 } catch (Exception e) {
1436 public void EndConnect (IAsyncResult result)
1438 ThrowIfDisposedAndClosed ();
1440 SocketAsyncResult sockares = ValidateEndIAsyncResult (result, "EndConnect", "result");
1442 if (!sockares.IsCompleted)
1443 sockares.AsyncWaitHandle.WaitOne();
1445 sockares.CheckIfThrowDelayedException();
1448 static void Connect_internal (SafeSocketHandle safeHandle, SocketAddress sa, out int error)
1451 safeHandle.RegisterForBlockingSyscall ();
1452 Connect_internal (safeHandle.DangerousGetHandle (), sa, out error);
1454 safeHandle.UnRegisterForBlockingSyscall ();
1458 /* Connects to the remote address */
1459 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1460 extern static void Connect_internal(IntPtr sock, SocketAddress sa, out int error);
1463 * - false when it is ok to use RemoteEndPoint
1464 * - true when addresses must be used (and addresses could be null/empty) */
1465 bool GetCheckedIPs (SocketAsyncEventArgs e, out IPAddress [] addresses)
1469 // Connect to the first address that match the host name, like:
1470 // http://blogs.msdn.com/ncl/archive/2009/07/20/new-ncl-features-in-net-4-0-beta-2.aspx
1471 // while skipping entries that do not match the address family
1472 DnsEndPoint dep = e.RemoteEndPoint as DnsEndPoint;
1474 addresses = Dns.GetHostAddresses (dep.Host);
1477 e.ConnectByNameError = null;
1486 /* According to the docs, the MS runtime will throw PlatformNotSupportedException
1487 * if the platform is newer than w2k. We should be able to cope... */
1488 public void Disconnect (bool reuseSocket)
1490 ThrowIfDisposedAndClosed ();
1493 Disconnect_internal (safe_handle, reuseSocket, out error);
1497 /* ERROR_NOT_SUPPORTED */
1498 throw new PlatformNotSupportedException ();
1500 throw new SocketException (error);
1504 is_connected = false;
1506 /* Do managed housekeeping here... */
1510 public bool DisconnectAsync (SocketAsyncEventArgs e)
1512 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1514 ThrowIfDisposedAndClosed ();
1517 e.Worker.Init (this, e, SocketOperation.Disconnect);
1519 SocketAsyncResult sockares = e.Worker.result;
1521 socket_pool_queue (SocketAsyncWorker.Dispatcher, sockares);
1527 public IAsyncResult BeginDisconnect (bool reuseSocket, AsyncCallback callback, object state)
1529 ThrowIfDisposedAndClosed ();
1531 SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.Disconnect) {
1532 ReuseSocket = reuseSocket,
1535 socket_pool_queue (SocketAsyncWorker.Dispatcher, sockares);
1540 public void EndDisconnect (IAsyncResult asyncResult)
1542 ThrowIfDisposedAndClosed ();
1544 SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndDisconnect", "asyncResult");
1546 if (!sockares.IsCompleted)
1547 sockares.AsyncWaitHandle.WaitOne ();
1549 sockares.CheckIfThrowDelayedException ();
1552 static void Disconnect_internal (SafeSocketHandle safeHandle, bool reuse, out int error)
1554 bool release = false;
1556 safeHandle.DangerousAddRef (ref release);
1557 Disconnect_internal (safeHandle.DangerousGetHandle (), reuse, out error);
1560 safeHandle.DangerousRelease ();
1564 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1565 extern static void Disconnect_internal (IntPtr sock, bool reuse, out int error);
1571 public int Receive (byte [] buffer)
1573 return Receive (buffer, SocketFlags.None);
1576 public int Receive (byte [] buffer, SocketFlags flags)
1578 ThrowIfDisposedAndClosed ();
1579 ThrowIfBufferNull (buffer);
1580 ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
1583 int ret = Receive_nochecks (buffer, 0, buffer.Length, flags, out error);
1585 if (error != SocketError.Success) {
1586 if (error == SocketError.WouldBlock && is_blocking) // This might happen when ReceiveTimeout is set
1587 throw new SocketException ((int) error, TIMEOUT_EXCEPTION_MSG);
1588 throw new SocketException ((int) error);
1594 public int Receive (byte [] buffer, int size, SocketFlags flags)
1596 ThrowIfDisposedAndClosed ();
1597 ThrowIfBufferNull (buffer);
1598 ThrowIfBufferOutOfRange (buffer, 0, size);
1601 int ret = Receive_nochecks (buffer, 0, size, flags, out error);
1603 if (error != SocketError.Success) {
1604 if (error == SocketError.WouldBlock && is_blocking) // This might happen when ReceiveTimeout is set
1605 throw new SocketException ((int) error, TIMEOUT_EXCEPTION_MSG);
1606 throw new SocketException ((int) error);
1612 public int Receive (byte [] buffer, int offset, int size, SocketFlags flags)
1614 ThrowIfDisposedAndClosed ();
1615 ThrowIfBufferNull (buffer);
1616 ThrowIfBufferOutOfRange (buffer, offset, size);
1619 int ret = Receive_nochecks (buffer, offset, size, flags, out error);
1621 if (error != SocketError.Success) {
1622 if (error == SocketError.WouldBlock && is_blocking) // This might happen when ReceiveTimeout is set
1623 throw new SocketException ((int) error, TIMEOUT_EXCEPTION_MSG);
1624 throw new SocketException ((int) error);
1630 public int Receive (byte [] buffer, int offset, int size, SocketFlags flags, out SocketError error)
1632 ThrowIfDisposedAndClosed ();
1633 ThrowIfBufferNull (buffer);
1634 ThrowIfBufferOutOfRange (buffer, offset, size);
1636 return Receive_nochecks (buffer, offset, size, flags, out error);
1639 public int Receive (IList<ArraySegment<byte>> buffers)
1642 int ret = Receive (buffers, SocketFlags.None, out error);
1644 if (error != SocketError.Success)
1645 throw new SocketException ((int) error);
1650 [CLSCompliant (false)]
1651 public int Receive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags)
1654 int ret = Receive (buffers, socketFlags, out error);
1656 if (error != SocketError.Success)
1657 throw new SocketException ((int) error);
1662 [CLSCompliant (false)]
1663 public int Receive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode)
1665 ThrowIfDisposedAndClosed ();
1667 if (buffers == null || buffers.Count == 0)
1668 throw new ArgumentNullException ("buffers");
1670 int numsegments = buffers.Count;
1674 /* Only example I can find of sending a byte array reference directly into an internal
1675 * call is in System.Runtime.Remoting/System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeSocket.cs,
1676 * so taking a lead from that... */
1677 WSABUF[] bufarray = new WSABUF[numsegments];
1678 GCHandle[] gch = new GCHandle[numsegments];
1680 for (int i = 0; i < numsegments; i++) {
1681 ArraySegment<byte> segment = buffers[i];
1683 if (segment.Offset < 0 || segment.Count < 0 || segment.Count > segment.Array.Length - segment.Offset)
1684 throw new ArgumentOutOfRangeException ("segment");
1686 gch[i] = GCHandle.Alloc (segment.Array, GCHandleType.Pinned);
1687 bufarray[i].len = segment.Count;
1688 bufarray[i].buf = Marshal.UnsafeAddrOfPinnedArrayElement (segment.Array, segment.Offset);
1692 ret = Receive_internal (safe_handle, bufarray, socketFlags, out nativeError);
1694 for (int i = 0; i < numsegments; i++) {
1695 if (gch[i].IsAllocated)
1700 errorCode = (SocketError) nativeError;
1705 public bool ReceiveAsync (SocketAsyncEventArgs e)
1707 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1709 ThrowIfDisposedAndClosed ();
1711 // LAME SPEC: the ArgumentException is never thrown, instead an NRE is
1712 // thrown when e.Buffer and e.BufferList are null (works fine when one is
1713 // set to a valid object)
1714 if (e.Buffer == null && e.BufferList == null)
1715 throw new NullReferenceException ("Either e.Buffer or e.BufferList must be valid buffers.");
1718 e.Worker.Init (this, e, e.Buffer != null ? SocketOperation.Receive : SocketOperation.ReceiveGeneric);
1720 SocketAsyncResult sockares = e.Worker.result;
1721 sockares.SockFlags = e.SocketFlags;
1723 if (e.Buffer != null) {
1724 sockares.Buffer = e.Buffer;
1725 sockares.Offset = e.Offset;
1726 sockares.Size = e.Count;
1728 sockares.Buffers = e.BufferList;
1731 // Receive takes care of ReceiveGeneric
1732 QueueSocketAsyncResult (readQ, e.Worker, sockares);
1737 public IAsyncResult BeginReceive (byte[] buffer, int offset, int size, SocketFlags socket_flags, AsyncCallback callback, object state)
1739 ThrowIfDisposedAndClosed ();
1740 ThrowIfBufferNull (buffer);
1741 ThrowIfBufferOutOfRange (buffer, offset, size);
1743 SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.Receive) {
1747 SockFlags = socket_flags,
1750 QueueSocketAsyncResult (readQ, sockares.Worker, sockares);
1755 public IAsyncResult BeginReceive (byte[] buffer, int offset, int size, SocketFlags flags, out SocketError error, AsyncCallback callback, object state)
1757 /* As far as I can tell from the docs and from experimentation, a pointer to the
1758 * SocketError parameter is not supposed to be saved for the async parts. And as we don't
1759 * set any socket errors in the setup code, we just have to set it to Success. */
1760 error = SocketError.Success;
1761 return BeginReceive (buffer, offset, size, flags, callback, state);
1764 [CLSCompliant (false)]
1765 public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, AsyncCallback callback, object state)
1767 ThrowIfDisposedAndClosed ();
1769 if (buffers == null)
1770 throw new ArgumentNullException ("buffers");
1772 SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveGeneric) {
1774 SockFlags = socketFlags,
1777 QueueSocketAsyncResult (readQ, sockares.Worker, sockares);
1782 [CLSCompliant (false)]
1783 public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
1785 /* I assume the same SocketError semantics as above */
1786 errorCode = SocketError.Success;
1787 return BeginReceive (buffers, socketFlags, callback, state);
1790 public int EndReceive (IAsyncResult result)
1793 int bytesReceived = EndReceive (result, out error);
1795 if (error != SocketError.Success) {
1796 if (error != SocketError.WouldBlock && error != SocketError.InProgress)
1797 is_connected = false;
1798 throw new SocketException ((int)error);
1801 return bytesReceived;
1804 public int EndReceive (IAsyncResult asyncResult, out SocketError errorCode)
1806 ThrowIfDisposedAndClosed ();
1808 SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndReceive", "asyncResult");
1810 if (!sockares.IsCompleted)
1811 sockares.AsyncWaitHandle.WaitOne ();
1813 // If no socket error occurred, call CheckIfThrowDelayedException in case there are other
1814 // kinds of exceptions that should be thrown.
1815 if ((errorCode = sockares.ErrorCode) == SocketError.Success)
1816 sockares.CheckIfThrowDelayedException();
1818 return sockares.Total;
1821 internal int Receive_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
1824 int ret = Receive_internal (safe_handle, buf, offset, size, flags, out nativeError);
1826 error = (SocketError) nativeError;
1827 if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress) {
1828 is_connected = false;
1831 is_connected = true;
1837 static int Receive_internal (SafeSocketHandle safeHandle, WSABUF[] bufarray, SocketFlags flags, out int error)
1840 safeHandle.RegisterForBlockingSyscall ();
1841 return Receive_internal (safeHandle.DangerousGetHandle (), bufarray, flags, out error);
1843 safeHandle.UnRegisterForBlockingSyscall ();
1847 [MethodImplAttribute (MethodImplOptions.InternalCall)]
1848 extern static int Receive_internal (IntPtr sock, WSABUF[] bufarray, SocketFlags flags, out int error);
1850 internal static int Receive_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, out int error)
1853 safeHandle.RegisterForBlockingSyscall ();
1854 return Receive_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, out error);
1856 safeHandle.UnRegisterForBlockingSyscall ();
1860 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1861 extern static int Receive_internal(IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags, out int error);
1867 public int ReceiveFrom (byte [] buffer, ref EndPoint remoteEP)
1869 ThrowIfDisposedAndClosed ();
1870 ThrowIfBufferNull (buffer);
1871 ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
1873 if (remoteEP == null)
1874 throw new ArgumentNullException ("remoteEP");
1876 return ReceiveFrom_nochecks (buffer, 0, buffer.Length, SocketFlags.None, ref remoteEP);
1879 public int ReceiveFrom (byte [] buffer, SocketFlags flags, ref EndPoint remoteEP)
1881 ThrowIfDisposedAndClosed ();
1882 ThrowIfBufferNull (buffer);
1883 ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
1885 if (remoteEP == null)
1886 throw new ArgumentNullException ("remoteEP");
1888 return ReceiveFrom_nochecks (buffer, 0, buffer.Length, flags, ref remoteEP);
1891 public int ReceiveFrom (byte [] buffer, int size, SocketFlags flags, ref EndPoint remoteEP)
1893 ThrowIfDisposedAndClosed ();
1894 ThrowIfBufferNull (buffer);
1895 ThrowIfBufferOutOfRange (buffer, 0, size);
1897 if (remoteEP == null)
1898 throw new ArgumentNullException ("remoteEP");
1900 return ReceiveFrom_nochecks (buffer, 0, size, flags, ref remoteEP);
1903 public int ReceiveFrom (byte [] buffer, int offset, int size, SocketFlags flags, ref EndPoint remoteEP)
1905 ThrowIfDisposedAndClosed ();
1906 ThrowIfBufferNull (buffer);
1907 ThrowIfBufferOutOfRange (buffer, offset, size);
1909 if (remoteEP == null)
1910 throw new ArgumentNullException ("remoteEP");
1912 return ReceiveFrom_nochecks (buffer, offset, size, flags, ref remoteEP);
1915 public bool ReceiveFromAsync (SocketAsyncEventArgs e)
1917 ThrowIfDisposedAndClosed ();
1919 // We do not support recv into multiple buffers yet
1920 if (e.BufferList != null)
1921 throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
1922 if (e.RemoteEndPoint == null)
1923 throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
1926 e.Worker.Init (this, e, SocketOperation.ReceiveFrom);
1928 SocketAsyncResult sockares = e.Worker.result;
1929 sockares.Buffer = e.Buffer;
1930 sockares.Offset = e.Offset;
1931 sockares.Size = e.Count;
1932 sockares.EndPoint = e.RemoteEndPoint;
1933 sockares.SockFlags = e.SocketFlags;
1935 QueueSocketAsyncResult (readQ, e.Worker, sockares);
1940 public IAsyncResult BeginReceiveFrom (byte[] buffer, int offset, int size, SocketFlags socket_flags, ref EndPoint remote_end, AsyncCallback callback, object state)
1942 ThrowIfDisposedAndClosed ();
1943 ThrowIfBufferNull (buffer);
1944 ThrowIfBufferOutOfRange (buffer, offset, size);
1946 if (remote_end == null)
1947 throw new ArgumentNullException ("remote_end");
1949 SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveFrom) {
1953 SockFlags = socket_flags,
1954 EndPoint = remote_end,
1957 QueueSocketAsyncResult (readQ, sockares.Worker, sockares);
1962 public int EndReceiveFrom(IAsyncResult result, ref EndPoint end_point)
1964 ThrowIfDisposedAndClosed ();
1966 if (end_point == null)
1967 throw new ArgumentNullException ("remote_end");
1969 SocketAsyncResult sockares = ValidateEndIAsyncResult (result, "EndReceiveFrom", "result");
1971 if (!sockares.IsCompleted)
1972 sockares.AsyncWaitHandle.WaitOne();
1974 sockares.CheckIfThrowDelayedException();
1976 end_point = sockares.EndPoint;
1978 return sockares.Total;
1981 internal int ReceiveFrom_nochecks (byte [] buf, int offset, int size, SocketFlags flags, ref EndPoint remote_end)
1984 return ReceiveFrom_nochecks_exc (buf, offset, size, flags, ref remote_end, true, out error);
1987 internal int ReceiveFrom_nochecks_exc (byte [] buf, int offset, int size, SocketFlags flags, ref EndPoint remote_end, bool throwOnError, out int error)
1989 SocketAddress sockaddr = remote_end.Serialize();
1991 int cnt = ReceiveFrom_internal (safe_handle, buf, offset, size, flags, ref sockaddr, out error);
1993 SocketError err = (SocketError) error;
1995 if (err != SocketError.WouldBlock && err != SocketError.InProgress) {
1996 is_connected = false;
1997 } else if (err == SocketError.WouldBlock && is_blocking) { // This might happen when ReceiveTimeout is set
1999 throw new SocketException ((int) SocketError.TimedOut, TIMEOUT_EXCEPTION_MSG);
2000 error = (int) SocketError.TimedOut;
2005 throw new SocketException (error);
2010 is_connected = true;
2013 /* If sockaddr is null then we're a connection oriented protocol and should ignore the
2014 * remote_end parameter (see MSDN documentation for Socket.ReceiveFrom(...) ) */
2015 if (sockaddr != null) {
2016 /* Stupidly, EndPoint.Create() is an instance method */
2017 remote_end = remote_end.Create (sockaddr);
2020 seed_endpoint = remote_end;
2025 static int ReceiveFrom_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, ref SocketAddress sockaddr, out int error)
2028 safeHandle.RegisterForBlockingSyscall ();
2029 return ReceiveFrom_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, ref sockaddr, out error);
2031 safeHandle.UnRegisterForBlockingSyscall ();
2035 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2036 extern static int ReceiveFrom_internal(IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags, ref SocketAddress sockaddr, out int error);
2040 #region ReceiveMessageFrom
2042 [MonoTODO ("Not implemented")]
2043 public int ReceiveMessageFrom (byte[] buffer, int offset, int size, ref SocketFlags socketFlags, ref EndPoint remoteEP, out IPPacketInformation ipPacketInformation)
2045 ThrowIfDisposedAndClosed ();
2046 ThrowIfBufferNull (buffer);
2047 ThrowIfBufferOutOfRange (buffer, offset, size);
2049 if (remoteEP == null)
2050 throw new ArgumentNullException ("remoteEP");
2052 // FIXME: figure out how we get hold of the IPPacketInformation
2053 throw new NotImplementedException ();
2056 [MonoTODO ("Not implemented")]
2057 public bool ReceiveMessageFromAsync (SocketAsyncEventArgs e)
2059 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
2061 ThrowIfDisposedAndClosed ();
2063 throw new NotImplementedException ();
2067 public IAsyncResult BeginReceiveMessageFrom (byte[] buffer, int offset, int size, SocketFlags socketFlags, ref EndPoint remoteEP, AsyncCallback callback, object state)
2069 ThrowIfDisposedAndClosed ();
2070 ThrowIfBufferNull (buffer);
2071 ThrowIfBufferOutOfRange (buffer, offset, size);
2073 if (remoteEP == null)
2074 throw new ArgumentNullException ("remoteEP");
2076 throw new NotImplementedException ();
2080 public int EndReceiveMessageFrom (IAsyncResult asyncResult, ref SocketFlags socketFlags, ref EndPoint endPoint, out IPPacketInformation ipPacketInformation)
2082 ThrowIfDisposedAndClosed ();
2084 if (endPoint == null)
2085 throw new ArgumentNullException ("endPoint");
2087 SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndReceiveMessageFrom", "asyncResult");
2089 throw new NotImplementedException ();
2096 public int Send (byte [] buffer)
2098 ThrowIfDisposedAndClosed ();
2099 ThrowIfBufferNull (buffer);
2100 ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
2103 int ret = Send_nochecks (buffer, 0, buffer.Length, SocketFlags.None, out error);
2105 if (error != SocketError.Success)
2106 throw new SocketException ((int) error);
2111 public int Send (byte [] buffer, SocketFlags flags)
2113 ThrowIfDisposedAndClosed ();
2114 ThrowIfBufferNull (buffer);
2115 ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
2118 int ret = Send_nochecks (buffer, 0, buffer.Length, flags, out error);
2120 if (error != SocketError.Success)
2121 throw new SocketException ((int) error);
2126 public int Send (byte [] buffer, int size, SocketFlags flags)
2128 ThrowIfDisposedAndClosed ();
2129 ThrowIfBufferNull (buffer);
2130 ThrowIfBufferOutOfRange (buffer, 0, size);
2133 int ret = Send_nochecks (buffer, 0, size, flags, out error);
2135 if (error != SocketError.Success)
2136 throw new SocketException ((int) error);
2141 public int Send (byte [] buffer, int offset, int size, SocketFlags flags)
2143 ThrowIfDisposedAndClosed ();
2144 ThrowIfBufferNull (buffer);
2145 ThrowIfBufferOutOfRange (buffer, offset, size);
2148 int ret = Send_nochecks (buffer, offset, size, flags, out error);
2150 if (error != SocketError.Success)
2151 throw new SocketException ((int) error);
2156 public int Send (byte [] buffer, int offset, int size, SocketFlags flags, out SocketError error)
2158 ThrowIfDisposedAndClosed ();
2159 ThrowIfBufferNull (buffer);
2160 ThrowIfBufferOutOfRange (buffer, offset, size);
2162 return Send_nochecks (buffer, offset, size, flags, out error);
2166 int Send (IList<ArraySegment<byte>> buffers)
2169 int ret = Send (buffers, SocketFlags.None, out error);
2171 if (error != SocketError.Success)
2172 throw new SocketException ((int) error);
2178 int Send (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags)
2181 int ret = Send (buffers, socketFlags, out error);
2183 if (error != SocketError.Success)
2184 throw new SocketException ((int) error);
2189 [CLSCompliant (false)]
2190 public int Send (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode)
2192 ThrowIfDisposedAndClosed ();
2194 if (buffers == null)
2195 throw new ArgumentNullException ("buffers");
2196 if (buffers.Count == 0)
2197 throw new ArgumentException ("Buffer is empty", "buffers");
2199 int numsegments = buffers.Count;
2203 WSABUF[] bufarray = new WSABUF[numsegments];
2204 GCHandle[] gch = new GCHandle[numsegments];
2206 for(int i = 0; i < numsegments; i++) {
2207 ArraySegment<byte> segment = buffers[i];
2209 if (segment.Offset < 0 || segment.Count < 0 || segment.Count > segment.Array.Length - segment.Offset)
2210 throw new ArgumentOutOfRangeException ("segment");
2212 gch[i] = GCHandle.Alloc (segment.Array, GCHandleType.Pinned);
2213 bufarray[i].len = segment.Count;
2214 bufarray[i].buf = Marshal.UnsafeAddrOfPinnedArrayElement (segment.Array, segment.Offset);
2218 ret = Send_internal (safe_handle, bufarray, socketFlags, out nativeError);
2220 for(int i = 0; i < numsegments; i++) {
2221 if (gch[i].IsAllocated) {
2227 errorCode = (SocketError)nativeError;
2232 internal int Send_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
2235 error = SocketError.Success;
2240 int ret = Send_internal (safe_handle, buf, offset, size, flags, out nativeError);
2242 error = (SocketError)nativeError;
2244 if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress) {
2245 is_connected = false;
2248 is_connected = true;
2254 public bool SendAsync (SocketAsyncEventArgs e)
2256 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
2258 ThrowIfDisposedAndClosed ();
2260 if (e.Buffer == null && e.BufferList == null)
2261 throw new NullReferenceException ("Either e.Buffer or e.BufferList must be valid buffers.");
2264 e.Worker.Init (this, e, e.Buffer != null ? SocketOperation.Send : SocketOperation.SendGeneric);
2266 SocketAsyncResult sockares = e.Worker.result;
2267 sockares.SockFlags = e.SocketFlags;
2269 if (e.Buffer != null) {
2270 sockares.Buffer = e.Buffer;
2271 sockares.Offset = e.Offset;
2272 sockares.Size = e.Count;
2274 sockares.Buffers = e.BufferList;
2277 // Send takes care of SendGeneric
2278 QueueSocketAsyncResult (writeQ, e.Worker, sockares);
2283 public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
2285 if (!is_connected) {
2286 errorCode = SocketError.NotConnected;
2287 throw new SocketException ((int) errorCode);
2290 errorCode = SocketError.Success;
2291 return BeginSend (buffer, offset, size, socketFlags, callback, state);
2294 public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socket_flags, AsyncCallback callback, object state)
2296 ThrowIfDisposedAndClosed ();
2297 ThrowIfBufferNull (buffer);
2298 ThrowIfBufferOutOfRange (buffer, offset, size);
2301 throw new SocketException ((int)SocketError.NotConnected);
2303 SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.Send) {
2307 SockFlags = socket_flags,
2310 QueueSocketAsyncResult (writeQ, sockares.Worker, sockares);
2315 public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, AsyncCallback callback, object state)
2317 ThrowIfDisposedAndClosed ();
2319 if (buffers == null)
2320 throw new ArgumentNullException ("buffers");
2322 throw new SocketException ((int)SocketError.NotConnected);
2324 SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.SendGeneric) {
2326 SockFlags = socketFlags,
2329 QueueSocketAsyncResult (writeQ, sockares.Worker, sockares);
2334 [CLSCompliant (false)]
2335 public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
2337 if (!is_connected) {
2338 errorCode = SocketError.NotConnected;
2339 throw new SocketException ((int)errorCode);
2342 errorCode = SocketError.Success;
2343 return BeginSend (buffers, socketFlags, callback, state);
2346 public int EndSend (IAsyncResult result)
2349 int bytesSent = EndSend (result, out error);
2351 if (error != SocketError.Success) {
2352 if (error != SocketError.WouldBlock && error != SocketError.InProgress)
2353 is_connected = false;
2354 throw new SocketException ((int)error);
2360 public int EndSend (IAsyncResult asyncResult, out SocketError errorCode)
2362 ThrowIfDisposedAndClosed ();
2364 SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndSend", "asyncResult");
2366 if (!sockares.IsCompleted)
2367 sockares.AsyncWaitHandle.WaitOne ();
2369 /* If no socket error occurred, call CheckIfThrowDelayedException in
2370 * case there are other kinds of exceptions that should be thrown.*/
2371 if ((errorCode = sockares.ErrorCode) == SocketError.Success)
2372 sockares.CheckIfThrowDelayedException ();
2374 return sockares.Total;
2377 static int Send_internal (SafeSocketHandle safeHandle, WSABUF[] bufarray, SocketFlags flags, out int error)
2379 bool release = false;
2381 safeHandle.DangerousAddRef (ref release);
2382 return Send_internal (safeHandle.DangerousGetHandle (), bufarray, flags, out error);
2385 safeHandle.DangerousRelease ();
2389 [MethodImplAttribute (MethodImplOptions.InternalCall)]
2390 extern static int Send_internal (IntPtr sock, WSABUF[] bufarray, SocketFlags flags, out int error);
2392 internal static int Send_internal (SafeSocketHandle safeHandle, byte[] buf, int offset, int count, SocketFlags flags, out int error)
2395 safeHandle.RegisterForBlockingSyscall ();
2396 return Send_internal (safeHandle.DangerousGetHandle (), buf, offset, count, flags, out error);
2398 safeHandle.UnRegisterForBlockingSyscall ();
2402 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2403 extern static int Send_internal(IntPtr sock, byte[] buf, int offset, int count, SocketFlags flags, out int error);
2409 public int SendTo (byte [] buffer, EndPoint remote_end)
2411 ThrowIfDisposedAndClosed ();
2412 ThrowIfBufferNull (buffer);
2413 ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
2415 if (remote_end == null)
2416 throw new ArgumentNullException ("remote_end");
2418 return SendTo_nochecks (buffer, 0, buffer.Length, SocketFlags.None, remote_end);
2421 public int SendTo (byte [] buffer, SocketFlags flags, EndPoint remote_end)
2423 ThrowIfDisposedAndClosed ();
2424 ThrowIfBufferNull (buffer);
2425 ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
2427 if (remote_end == null)
2428 throw new ArgumentNullException ("remote_end");
2430 return SendTo_nochecks (buffer, 0, buffer.Length, flags, remote_end);
2433 public int SendTo (byte [] buffer, int size, SocketFlags flags, EndPoint remote_end)
2435 ThrowIfDisposedAndClosed ();
2436 ThrowIfBufferNull (buffer);
2437 ThrowIfBufferOutOfRange (buffer, 0, size);
2439 if (remote_end == null)
2440 throw new ArgumentNullException ("remote_end");
2442 return SendTo_nochecks (buffer, 0, size, flags, remote_end);
2445 public int SendTo (byte [] buffer, int offset, int size, SocketFlags flags, EndPoint remote_end)
2447 ThrowIfDisposedAndClosed ();
2448 ThrowIfBufferNull (buffer);
2449 ThrowIfBufferOutOfRange (buffer, offset, size);
2451 if (remote_end == null)
2452 throw new ArgumentNullException("remote_end");
2454 return SendTo_nochecks (buffer, offset, size, flags, remote_end);
2457 internal int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags, EndPoint remote_end)
2460 int ret = SendTo_internal (safe_handle, buffer, offset, size, flags, remote_end.Serialize (), out error);
2462 SocketError err = (SocketError) error;
2464 if (err != SocketError.WouldBlock && err != SocketError.InProgress)
2465 is_connected = false;
2466 throw new SocketException (error);
2469 is_connected = true;
2471 seed_endpoint = remote_end;
2476 public bool SendToAsync (SocketAsyncEventArgs e)
2478 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
2480 ThrowIfDisposedAndClosed ();
2482 if (e.BufferList != null)
2483 throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
2484 if (e.RemoteEndPoint == null)
2485 throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
2488 e.Worker.Init (this, e, SocketOperation.SendTo);
2490 SocketAsyncResult sockares = e.Worker.result;
2491 sockares.Buffer = e.Buffer;
2492 sockares.Offset = e.Offset;
2493 sockares.Size = e.Count;
2494 sockares.SockFlags = e.SocketFlags;
2495 sockares.EndPoint = e.RemoteEndPoint;
2497 QueueSocketAsyncResult (writeQ, e.Worker, sockares);
2503 public IAsyncResult BeginSendTo(byte[] buffer, int offset, int size, SocketFlags socket_flags, EndPoint remote_end, AsyncCallback callback, object state)
2505 ThrowIfDisposedAndClosed ();
2506 ThrowIfBufferNull (buffer);
2507 ThrowIfBufferOutOfRange (buffer, offset, size);
2509 SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.SendTo) {
2513 SockFlags = socket_flags,
2514 EndPoint = remote_end,
2517 QueueSocketAsyncResult (writeQ, sockares.Worker, sockares);
2522 public int EndSendTo (IAsyncResult result)
2524 ThrowIfDisposedAndClosed ();
2526 SocketAsyncResult sockares = ValidateEndIAsyncResult (result, "EndSendTo", "result");
2528 if (!sockares.IsCompleted)
2529 sockares.AsyncWaitHandle.WaitOne();
2531 sockares.CheckIfThrowDelayedException();
2533 return sockares.Total;
2536 static int SendTo_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, SocketAddress sa, out int error)
2539 safeHandle.RegisterForBlockingSyscall ();
2540 return SendTo_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, sa, out error);
2542 safeHandle.UnRegisterForBlockingSyscall ();
2546 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2547 extern static int SendTo_internal (IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags, SocketAddress sa, out int error);
2553 public void SendFile (string fileName)
2555 ThrowIfDisposedAndClosed ();
2558 throw new NotSupportedException ();
2560 throw new InvalidOperationException ();
2562 SendFile (fileName, null, null, 0);
2565 public void SendFile (string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags)
2567 ThrowIfDisposedAndClosed ();
2570 throw new NotSupportedException ();
2572 throw new InvalidOperationException ();
2574 if (!SendFile_internal (safe_handle, fileName, preBuffer, postBuffer, flags)) {
2575 SocketException exc = new SocketException ();
2576 if (exc.ErrorCode == 2 || exc.ErrorCode == 3)
2577 throw new FileNotFoundException ();
2582 public IAsyncResult BeginSendFile (string fileName, AsyncCallback callback, object state)
2584 ThrowIfDisposedAndClosed ();
2587 throw new NotSupportedException ();
2588 if (!File.Exists (fileName))
2589 throw new FileNotFoundException ();
2591 return BeginSendFile (fileName, null, null, 0, callback, state);
2594 public IAsyncResult BeginSendFile (string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags, AsyncCallback callback, object state)
2596 ThrowIfDisposedAndClosed ();
2599 throw new NotSupportedException ();
2600 if (!File.Exists (fileName))
2601 throw new FileNotFoundException ();
2603 SendFileHandler handler = new SendFileHandler (SendFile);
2605 return new SendFileAsyncResult (handler, handler.BeginInvoke (fileName, preBuffer, postBuffer, flags, ar => callback (new SendFileAsyncResult (handler, ar)), state));
2608 public void EndSendFile (IAsyncResult asyncResult)
2610 ThrowIfDisposedAndClosed ();
2612 if (asyncResult == null)
2613 throw new ArgumentNullException ("asyncResult");
2615 SendFileAsyncResult ares = asyncResult as SendFileAsyncResult;
2617 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
2619 ares.Delegate.EndInvoke (ares.Original);
2622 static bool SendFile_internal (SafeSocketHandle safeHandle, string filename, byte [] pre_buffer, byte [] post_buffer, TransmitFileOptions flags)
2625 safeHandle.RegisterForBlockingSyscall ();
2626 return SendFile_internal (safeHandle.DangerousGetHandle (), filename, pre_buffer, post_buffer, flags);
2628 safeHandle.UnRegisterForBlockingSyscall ();
2632 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2633 extern static bool SendFile_internal (IntPtr sock, string filename, byte [] pre_buffer, byte [] post_buffer, TransmitFileOptions flags);
2635 delegate void SendFileHandler (string fileName, byte [] preBuffer, byte [] postBuffer, TransmitFileOptions flags);
2637 sealed class SendFileAsyncResult : IAsyncResult {
2641 public SendFileAsyncResult (SendFileHandler d, IAsyncResult ares)
2647 public object AsyncState {
2648 get { return ares.AsyncState; }
2651 public WaitHandle AsyncWaitHandle {
2652 get { return ares.AsyncWaitHandle; }
2655 public bool CompletedSynchronously {
2656 get { return ares.CompletedSynchronously; }
2659 public bool IsCompleted {
2660 get { return ares.IsCompleted; }
2663 public SendFileHandler Delegate {
2667 public IAsyncResult Original {
2668 get { return ares; }
2676 [MonoTODO ("Not implemented")]
2677 public bool SendPacketsAsync (SocketAsyncEventArgs e)
2679 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
2681 ThrowIfDisposedAndClosed ();
2683 throw new NotImplementedException ();
2688 #region DuplicateAndClose
2691 [MonoLimitation ("We do not support passing sockets across processes, we merely allow this API to pass the socket across AppDomains")]
2692 public SocketInformation DuplicateAndClose (int targetProcessId)
2694 var si = new SocketInformation ();
2696 (is_listening ? SocketInformationOptions.Listening : 0) |
2697 (is_connected ? SocketInformationOptions.Connected : 0) |
2698 (is_blocking ? 0 : SocketInformationOptions.NonBlocking) |
2699 (use_overlapped_io ? SocketInformationOptions.UseOnlyOverlappedIO : 0);
2701 si.ProtocolInformation = Mono.DataConverter.Pack ("iiiil", (int)address_family, (int)socket_type, (int)protocol_type, is_bound ? 1 : 0, (long)Handle);
2710 #region GetSocketOption
2712 public void GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, byte [] optionValue)
2714 ThrowIfDisposedAndClosed ();
2716 if (optionValue == null)
2717 throw new SocketException ((int) SocketError.Fault, "Error trying to dereference an invalid pointer");
2720 GetSocketOption_arr_internal (safe_handle, optionLevel, optionName, ref optionValue, out error);
2723 throw new SocketException (error);
2726 public byte [] GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int length)
2728 ThrowIfDisposedAndClosed ();
2731 byte[] byte_val = new byte [length];
2732 GetSocketOption_arr_internal (safe_handle, optionLevel, optionName, ref byte_val, out error);
2735 throw new SocketException (error);
2740 public object GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName)
2742 ThrowIfDisposedAndClosed ();
2746 GetSocketOption_obj_internal (safe_handle, optionLevel, optionName, out obj_val, out error);
2749 throw new SocketException (error);
2751 if (optionName == SocketOptionName.Linger)
2752 return (LingerOption) obj_val;
2753 else if (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)
2754 return (MulticastOption) obj_val;
2755 else if (obj_val is int)
2756 return (int) obj_val;
2761 static void GetSocketOption_arr_internal (SafeSocketHandle safeHandle, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val, out int error)
2763 bool release = false;
2765 safeHandle.DangerousAddRef (ref release);
2766 GetSocketOption_arr_internal (safeHandle.DangerousGetHandle (), level, name, ref byte_val, out error);
2769 safeHandle.DangerousRelease ();
2773 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2774 extern static void GetSocketOption_arr_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val, out int error);
2776 static void GetSocketOption_obj_internal (SafeSocketHandle safeHandle, SocketOptionLevel level, SocketOptionName name, out object obj_val, out int error)
2778 bool release = false;
2780 safeHandle.DangerousAddRef (ref release);
2781 GetSocketOption_obj_internal (safeHandle.DangerousGetHandle (), level, name, out obj_val, out error);
2784 safeHandle.DangerousRelease ();
2788 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2789 extern static void GetSocketOption_obj_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, out object obj_val, out int error);
2793 #region SetSocketOption
2795 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, byte [] optionValue)
2797 ThrowIfDisposedAndClosed ();
2799 // I'd throw an ArgumentNullException, but this is what MS does.
2800 if (optionValue == null)
2801 throw new SocketException ((int) SocketError.Fault, "Error trying to dereference an invalid pointer");
2804 SetSocketOption_internal (safe_handle, optionLevel, optionName, null, optionValue, 0, out error);
2807 if (error == (int) SocketError.InvalidArgument)
2808 throw new ArgumentException ();
2809 throw new SocketException (error);
2813 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, object optionValue)
2815 ThrowIfDisposedAndClosed ();
2817 // NOTE: if a null is passed, the byte[] overload is used instead...
2818 if (optionValue == null)
2819 throw new ArgumentNullException("optionValue");
2823 if (optionLevel == SocketOptionLevel.Socket && optionName == SocketOptionName.Linger) {
2824 LingerOption linger = optionValue as LingerOption;
2826 throw new ArgumentException ("A 'LingerOption' value must be specified.", "optionValue");
2827 SetSocketOption_internal (safe_handle, optionLevel, optionName, linger, null, 0, out error);
2828 } else if (optionLevel == SocketOptionLevel.IP && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
2829 MulticastOption multicast = optionValue as MulticastOption;
2830 if (multicast == null)
2831 throw new ArgumentException ("A 'MulticastOption' value must be specified.", "optionValue");
2832 SetSocketOption_internal (safe_handle, optionLevel, optionName, multicast, null, 0, out error);
2833 } else if (optionLevel == SocketOptionLevel.IPv6 && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
2834 IPv6MulticastOption multicast = optionValue as IPv6MulticastOption;
2835 if (multicast == null)
2836 throw new ArgumentException ("A 'IPv6MulticastOption' value must be specified.", "optionValue");
2837 SetSocketOption_internal (safe_handle, optionLevel, optionName, multicast, null, 0, out error);
2839 throw new ArgumentException ("Invalid value specified.", "optionValue");
2843 if (error == (int) SocketError.InvalidArgument)
2844 throw new ArgumentException ();
2845 throw new SocketException (error);
2849 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, bool optionValue)
2851 ThrowIfDisposedAndClosed ();
2854 int int_val = optionValue ? 1 : 0;
2855 SetSocketOption_internal (safe_handle, optionLevel, optionName, null, null, int_val, out error);
2858 if (error == (int) SocketError.InvalidArgument)
2859 throw new ArgumentException ();
2860 throw new SocketException (error);
2864 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int optionValue)
2866 ThrowIfDisposedAndClosed ();
2869 SetSocketOption_internal (safe_handle, optionLevel, optionName, null, null, optionValue, out error);
2872 throw new SocketException (error);
2876 static void SetSocketOption_internal (SafeSocketHandle safeHandle, SocketOptionLevel level, SocketOptionName name, object obj_val, byte [] byte_val, int int_val, out int error)
2878 bool release = false;
2880 safeHandle.DangerousAddRef (ref release);
2881 SetSocketOption_internal (safeHandle.DangerousGetHandle (), level, name, obj_val, byte_val, int_val, out error);
2884 safeHandle.DangerousRelease ();
2888 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2889 extern static void SetSocketOption_internal (IntPtr socket, SocketOptionLevel level, SocketOptionName name, object obj_val, byte [] byte_val, int int_val, out int error);
2895 public int IOControl (int ioctl_code, byte [] in_value, byte [] out_value)
2898 throw new ObjectDisposedException (GetType ().ToString ());
2901 int result = IOControl_internal (safe_handle, ioctl_code, in_value, out_value, out error);
2904 throw new SocketException (error);
2906 throw new InvalidOperationException ("Must use Blocking property instead.");
2911 public int IOControl (IOControlCode ioControlCode, byte[] optionInValue, byte[] optionOutValue)
2913 return IOControl ((int) ioControlCode, optionInValue, optionOutValue);
2916 static int IOControl_internal (SafeSocketHandle safeHandle, int ioctl_code, byte [] input, byte [] output, out int error)
2918 bool release = false;
2920 safeHandle.DangerousAddRef (ref release);
2921 return IOControl_internal (safeHandle.DangerousGetHandle (), ioctl_code, input, output, out error);
2924 safeHandle.DangerousRelease ();
2928 /* See Socket.IOControl, WSAIoctl documentation in MSDN. The common options between UNIX
2929 * and Winsock are FIONREAD, FIONBIO and SIOCATMARK. Anything else will depend on the system
2930 * except SIO_KEEPALIVE_VALS which is properly handled on both windows and linux. */
2931 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2932 extern static int IOControl_internal (IntPtr sock, int ioctl_code, byte [] input, byte [] output, out int error);
2938 public void Close ()
2944 public void Close (int timeout)
2946 linger_timeout = timeout;
2950 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2951 internal extern static void Close_internal (IntPtr socket, out int error);
2957 public void Shutdown (SocketShutdown how)
2959 ThrowIfDisposedAndClosed ();
2962 throw new SocketException (10057); // Not connected
2965 Shutdown_internal (safe_handle, how, out error);
2968 throw new SocketException (error);
2971 static void Shutdown_internal (SafeSocketHandle safeHandle, SocketShutdown how, out int error)
2973 bool release = false;
2975 safeHandle.DangerousAddRef (ref release);
2976 Shutdown_internal (safeHandle.DangerousGetHandle (), how, out error);
2979 safeHandle.DangerousRelease ();
2983 [MethodImplAttribute (MethodImplOptions.InternalCall)]
2984 extern static void Shutdown_internal (IntPtr socket, SocketShutdown how, out int error);
2990 protected virtual void Dispose (bool disposing)
2996 bool was_connected = is_connected;
2997 is_connected = false;
2999 if (safe_handle != null) {
3006 safe_handle.Dispose ();
3010 public void Dispose ()
3013 GC.SuppressFinalize (this);
3016 void Linger (IntPtr handle)
3018 if (!is_connected || linger_timeout <= 0)
3021 /* We don't want to receive any more data */
3023 Shutdown_internal (handle, SocketShutdown.Receive, out error);
3028 int seconds = linger_timeout / 1000;
3029 int ms = linger_timeout % 1000;
3031 /* If the other end closes, this will return 'true' with 'Available' == 0 */
3032 Poll_internal (handle, SelectMode.SelectRead, ms * 1000, out error);
3038 LingerOption linger = new LingerOption (true, seconds);
3039 SetSocketOption_internal (handle, SocketOptionLevel.Socket, SocketOptionName.Linger, linger, null, 0, out error);
3040 /* Not needed, we're closing upon return */
3048 void ThrowIfDisposedAndClosed (Socket socket)
3050 if (socket.is_disposed && socket.is_closed)
3051 throw new ObjectDisposedException (socket.GetType ().ToString ());
3054 void ThrowIfDisposedAndClosed ()
3056 if (is_disposed && is_closed)
3057 throw new ObjectDisposedException (GetType ().ToString ());
3060 void ThrowIfBufferNull (byte[] buffer)
3063 throw new ArgumentNullException ("buffer");
3066 void ThrowIfBufferOutOfRange (byte[] buffer, int offset, int size)
3069 throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
3070 if (offset > buffer.Length)
3071 throw new ArgumentOutOfRangeException ("offset", "offset must be <= buffer.Length");
3073 throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
3074 if (size > buffer.Length - offset)
3075 throw new ArgumentOutOfRangeException ("size", "size must be <= buffer.Length - offset");
3080 #if !NET_2_1 || MOBILE
3081 if (protocol_type == ProtocolType.Udp)
3082 throw new SocketException ((int)SocketError.ProtocolOption);
3086 SocketAsyncResult ValidateEndIAsyncResult (IAsyncResult ares, string methodName, string argName)
3089 throw new ArgumentNullException (argName);
3091 SocketAsyncResult sockares = ares as SocketAsyncResult;
3092 if (sockares == null)
3093 throw new ArgumentException ("Invalid IAsyncResult", argName);
3094 if (Interlocked.CompareExchange (ref sockares.EndCalled, 1, 0) == 1)
3095 throw new InvalidOperationException (methodName + " can only be called once per asynchronous operation");
3100 void QueueSocketAsyncResult (Queue<SocketAsyncWorker> queue, SocketAsyncWorker worker, SocketAsyncResult sockares)
3104 queue.Enqueue (worker);
3105 count = queue.Count;
3109 socket_pool_queue (SocketAsyncWorker.Dispatcher, sockares);
3112 [StructLayout (LayoutKind.Sequential)]
3118 [MethodImplAttribute(MethodImplOptions.InternalCall)]
3119 internal static extern void cancel_blocking_socket_operation (Thread thread);
3121 [MethodImplAttribute(MethodImplOptions.InternalCall)]
3122 internal static extern void socket_pool_queue (SocketAsyncCallback d, SocketAsyncResult r);