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<KeyValuePair<IntPtr, IOSelectorJob>> readQ = new Queue<KeyValuePair<IntPtr, IOSelectorJob>> (2);
90 internal Queue<KeyValuePair<IntPtr, IOSelectorJob>> writeQ = new Queue<KeyValuePair<IntPtr, IOSelectorJob>> (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 this.safe_handle = new SafeSocketHandle (Socket_internal (addressFamily, socketType, protocolType, out error), true);
209 throw new SocketException (error);
211 #if !NET_2_1 || MOBILE
217 public Socket (SocketInformation socketInformation)
219 this.is_listening = (socketInformation.Options & SocketInformationOptions.Listening) != 0;
220 this.is_connected = (socketInformation.Options & SocketInformationOptions.Connected) != 0;
221 this.is_blocking = (socketInformation.Options & SocketInformationOptions.NonBlocking) == 0;
222 this.use_overlapped_io = (socketInformation.Options & SocketInformationOptions.UseOnlyOverlappedIO) != 0;
224 var result = Mono.DataConverter.Unpack ("iiiil", socketInformation.ProtocolInformation, 0);
226 this.address_family = (AddressFamily) (int) result [0];
227 this.socket_type = (SocketType) (int) result [1];
228 this.protocol_type = (ProtocolType) (int) result [2];
229 this.is_bound = (ProtocolType) (int) result [3] != 0;
230 this.safe_handle = new SafeSocketHandle ((IntPtr) (long) result [4], true);
236 /* private constructor used by Accept, which already has a socket handle to use */
237 internal Socket(AddressFamily family, SocketType type, ProtocolType proto, SafeSocketHandle safe_handle)
239 this.address_family = family;
240 this.socket_type = type;
241 this.protocol_type = proto;
243 this.safe_handle = safe_handle;
244 this.is_connected = true;
252 void SocketDefaults ()
255 /* Need to test IPv6 further */
256 if (address_family == AddressFamily.InterNetwork
257 // || address_family == AddressFamily.InterNetworkV6
259 /* This is the default, but it probably has nasty side
260 * effects on Linux, as the socket option is kludged by
261 * turning on or off PMTU discovery... */
262 this.DontFragment = false;
265 /* Microsoft sets these to 8192, but we are going to keep them
266 * both to the OS defaults as these have a big performance impact.
267 * on WebClient performance. */
268 // this.ReceiveBufferSize = 8192;
269 // this.SendBufferSize = 8192;
270 } catch (SocketException) {
274 /* Creates a new system socket, returning the handle */
275 [MethodImplAttribute(MethodImplOptions.InternalCall)]
276 extern IntPtr Socket_internal (AddressFamily family, SocketType type, ProtocolType proto, out int error);
282 [ObsoleteAttribute ("Use OSSupportsIPv4 instead")]
283 public static bool SupportsIPv4 {
284 get { return ipv4_supported == 1; }
287 [ObsoleteAttribute ("Use OSSupportsIPv6 instead")]
288 public static bool SupportsIPv6 {
289 get { return ipv6_supported == 1; }
293 public static bool OSSupportsIPv4 {
294 get { return ipv4_supported == 1; }
297 public static bool OSSupportsIPv4 {
299 NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces ();
301 foreach (NetworkInterface adapter in nics) {
302 if (adapter.Supports (NetworkInterfaceComponent.IPv4))
312 public static bool OSSupportsIPv6 {
313 get { return ipv6_supported == 1; }
316 public static bool OSSupportsIPv6 {
318 NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces ();
320 foreach (NetworkInterface adapter in nics) {
321 if (adapter.Supports (NetworkInterfaceComponent.IPv6))
330 public int Available {
332 ThrowIfDisposedAndClosed ();
335 ret = Available_internal (safe_handle, out error);
338 throw new SocketException (error);
344 static int Available_internal (SafeSocketHandle safeHandle, out int error)
346 bool release = false;
348 safeHandle.DangerousAddRef (ref release);
349 return Available_internal (safeHandle.DangerousGetHandle (), out error);
352 safeHandle.DangerousRelease ();
356 /* Returns the amount of data waiting to be read on socket */
357 [MethodImplAttribute(MethodImplOptions.InternalCall)]
358 extern static int Available_internal (IntPtr socket, out int error);
360 public bool DontFragment {
362 ThrowIfDisposedAndClosed ();
364 switch (address_family) {
365 case AddressFamily.InterNetwork:
366 return ((int) GetSocketOption (SocketOptionLevel.IP, SocketOptionName.DontFragment)) != 0;
367 case AddressFamily.InterNetworkV6:
368 return ((int) GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.DontFragment)) != 0;
370 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
374 ThrowIfDisposedAndClosed ();
376 switch (address_family) {
377 case AddressFamily.InterNetwork:
378 SetSocketOption (SocketOptionLevel.IP, SocketOptionName.DontFragment, value ? 1 : 0);
380 case AddressFamily.InterNetworkV6:
381 SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.DontFragment, value ? 1 : 0);
384 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
389 public bool EnableBroadcast {
391 ThrowIfDisposedAndClosed ();
393 if (protocol_type != ProtocolType.Udp)
394 throw new SocketException ((int) SocketError.ProtocolOption);
396 return ((int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Broadcast)) != 0;
399 ThrowIfDisposedAndClosed ();
401 if (protocol_type != ProtocolType.Udp)
402 throw new SocketException ((int) SocketError.ProtocolOption);
404 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Broadcast, value ? 1 : 0);
408 public bool ExclusiveAddressUse {
410 ThrowIfDisposedAndClosed ();
412 return ((int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse)) != 0;
415 ThrowIfDisposedAndClosed ();
418 throw new InvalidOperationException ("Bind has already been called for this socket");
420 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse, value ? 1 : 0);
424 public bool IsBound {
430 public LingerOption LingerState {
432 ThrowIfDisposedAndClosed ();
434 return (LingerOption) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Linger);
437 ThrowIfDisposedAndClosed ();
438 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Linger, value);
442 public bool MulticastLoopback {
444 ThrowIfDisposedAndClosed ();
446 /* Even though this option can be set for TCP sockets on Linux, throw
447 * this exception anyway to be compatible (the MSDN docs say
448 * "Setting this property on a Transmission Control Protocol (TCP)
449 * socket will have no effect." but the MS runtime throws the
451 if (protocol_type == ProtocolType.Tcp)
452 throw new SocketException ((int)SocketError.ProtocolOption);
454 switch (address_family) {
455 case AddressFamily.InterNetwork:
456 return ((int) GetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastLoopback)) != 0;
457 case AddressFamily.InterNetworkV6:
458 return ((int) GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback)) != 0;
460 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
464 ThrowIfDisposedAndClosed ();
466 /* Even though this option can be set for TCP sockets on Linux, throw
467 * this exception anyway to be compatible (the MSDN docs say
468 * "Setting this property on a Transmission Control Protocol (TCP)
469 * socket will have no effect." but the MS runtime throws the
471 if (protocol_type == ProtocolType.Tcp)
472 throw new SocketException ((int)SocketError.ProtocolOption);
474 switch (address_family) {
475 case AddressFamily.InterNetwork:
476 SetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastLoopback, value ? 1 : 0);
478 case AddressFamily.InterNetworkV6:
479 SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback, value ? 1 : 0);
482 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
487 public bool DualMode {
489 if (AddressFamily != AddressFamily.InterNetworkV6)
490 throw new NotSupportedException("This protocol version is not supported");
492 return ((int)GetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only) == 0);
495 if (AddressFamily != AddressFamily.InterNetworkV6)
496 throw new NotSupportedException("This protocol version is not supported");
498 SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, value ? 0 : 1);
502 private bool IsDualMode {
504 return AddressFamily == AddressFamily.InterNetworkV6 && DualMode;
508 [MonoTODO ("This doesn't do anything on Mono yet")]
509 public bool UseOnlyOverlappedIO {
510 get { return use_overlapped_io; }
511 set { use_overlapped_io = value; }
514 public IntPtr Handle {
515 get { return safe_handle.DangerousGetHandle (); }
518 // Wish: support non-IP endpoints.
519 public EndPoint LocalEndPoint {
521 ThrowIfDisposedAndClosed ();
523 /* If the seed EndPoint is null, Connect, Bind, etc has not yet
524 * been called. MS returns null in this case. */
525 if (seed_endpoint == null)
529 SocketAddress sa = LocalEndPoint_internal (safe_handle, (int) address_family, out error);
532 throw new SocketException (error);
534 return seed_endpoint.Create (sa);
538 static SocketAddress LocalEndPoint_internal (SafeSocketHandle safeHandle, int family, out int error)
540 bool release = false;
542 safeHandle.DangerousAddRef (ref release);
543 return LocalEndPoint_internal (safeHandle.DangerousGetHandle (), family, out error);
546 safeHandle.DangerousRelease ();
550 /* Returns the local endpoint details in addr and port */
551 [MethodImplAttribute(MethodImplOptions.InternalCall)]
552 extern static SocketAddress LocalEndPoint_internal (IntPtr socket, int family, out int error);
554 public SocketType SocketType {
555 get { return socket_type; }
558 public int SendTimeout {
560 ThrowIfDisposedAndClosed ();
562 return (int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendTimeout);
565 ThrowIfDisposedAndClosed ();
568 throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than -1");
570 /* According to the MSDN docs we should adjust values between 1 and
571 * 499 to 500, but the MS runtime doesn't do this. */
575 SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, value);
579 public int ReceiveTimeout {
581 ThrowIfDisposedAndClosed ();
583 return (int) GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout);
586 ThrowIfDisposedAndClosed ();
589 throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than -1");
594 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, value);
598 public AddressFamily AddressFamily {
599 get { return address_family; }
602 public bool Blocking {
603 get { return is_blocking; }
605 ThrowIfDisposedAndClosed ();
608 Blocking_internal (safe_handle, value, out error);
611 throw new SocketException (error);
617 static void Blocking_internal (SafeSocketHandle safeHandle, bool block, out int error)
619 bool release = false;
621 safeHandle.DangerousAddRef (ref release);
622 Blocking_internal (safeHandle.DangerousGetHandle (), block, out error);
625 safeHandle.DangerousRelease ();
629 [MethodImplAttribute(MethodImplOptions.InternalCall)]
630 internal extern static void Blocking_internal(IntPtr socket, bool block, out int error);
632 public bool Connected {
633 get { return is_connected; }
634 internal set { is_connected = value; }
637 public ProtocolType ProtocolType {
638 get { return protocol_type; }
641 public bool NoDelay {
643 ThrowIfDisposedAndClosed ();
646 return ((int) GetSocketOption (SocketOptionLevel.Tcp, SocketOptionName.NoDelay)) != 0;
650 ThrowIfDisposedAndClosed ();
653 SetSocketOption (SocketOptionLevel.Tcp, SocketOptionName.NoDelay, value ? 1 : 0);
657 public int ReceiveBufferSize {
659 ThrowIfDisposedAndClosed ();
661 return (int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer);
664 ThrowIfDisposedAndClosed ();
667 throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
669 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, value);
673 public int SendBufferSize {
675 ThrowIfDisposedAndClosed ();
677 return (int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendBuffer);
680 ThrowIfDisposedAndClosed ();
683 throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
685 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendBuffer, value);
691 ThrowIfDisposedAndClosed ();
693 switch (address_family) {
694 case AddressFamily.InterNetwork:
695 return (short) (int) GetSocketOption (SocketOptionLevel.IP, SocketOptionName.IpTimeToLive);
696 case AddressFamily.InterNetworkV6:
697 return (short) (int) GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.HopLimit);
699 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
703 ThrowIfDisposedAndClosed ();
706 throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
708 switch (address_family) {
709 case AddressFamily.InterNetwork:
710 SetSocketOption (SocketOptionLevel.IP, SocketOptionName.IpTimeToLive, value);
712 case AddressFamily.InterNetworkV6:
713 SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.HopLimit, value);
716 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
721 public EndPoint RemoteEndPoint {
723 ThrowIfDisposedAndClosed ();
725 /* If the seed EndPoint is null, Connect, Bind, etc has
726 * not yet been called. MS returns null in this case. */
727 if (!is_connected || seed_endpoint == null)
731 SocketAddress sa = RemoteEndPoint_internal (safe_handle, (int) address_family, out error);
734 throw new SocketException (error);
736 return seed_endpoint.Create (sa);
740 static SocketAddress RemoteEndPoint_internal (SafeSocketHandle safeHandle, int family, out int error)
742 bool release = false;
744 safeHandle.DangerousAddRef (ref release);
745 return RemoteEndPoint_internal (safeHandle.DangerousGetHandle (), family, out error);
748 safeHandle.DangerousRelease ();
752 /* Returns the remote endpoint details in addr and port */
753 [MethodImplAttribute(MethodImplOptions.InternalCall)]
754 extern static SocketAddress RemoteEndPoint_internal (IntPtr socket, int family, out int error);
760 public static void Select (IList checkRead, IList checkWrite, IList checkError, int microSeconds)
762 var list = new List<Socket> ();
763 AddSockets (list, checkRead, "checkRead");
764 AddSockets (list, checkWrite, "checkWrite");
765 AddSockets (list, checkError, "checkError");
768 throw new ArgumentNullException ("checkRead, checkWrite, checkError", "All the lists are null or empty.");
770 /* The 'sockets' array contains:
771 * - READ socket 0-n, null,
772 * - WRITE socket 0-n, null,
773 * - ERROR socket 0-n, null */
774 Socket [] sockets = list.ToArray ();
777 Select_internal (ref sockets, microSeconds, out error);
780 throw new SocketException (error);
782 if (sockets == null) {
783 if (checkRead != null)
785 if (checkWrite != null)
787 if (checkError != null)
793 int count = sockets.Length;
794 IList currentList = checkRead;
796 for (int i = 0; i < count; i++) {
797 Socket sock = sockets [i];
798 if (sock == null) { // separator
799 if (currentList != null) {
800 // Remove non-signaled sockets after the current one
801 int to_remove = currentList.Count - currentIdx;
802 for (int k = 0; k < to_remove; k++)
803 currentList.RemoveAt (currentIdx);
805 currentList = (mode == 0) ? checkWrite : checkError;
811 if (mode == 1 && currentList == checkWrite && !sock.is_connected) {
812 if ((int) sock.GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error) == 0)
813 sock.is_connected = true;
816 /* Remove non-signaled sockets before the current one */
817 while (((Socket) currentList [currentIdx]) != sock)
818 currentList.RemoveAt (currentIdx);
824 static void AddSockets (List<Socket> sockets, IList list, string name)
827 foreach (Socket sock in list) {
828 if (sock == null) // MS throws a NullRef
829 throw new ArgumentNullException ("name", "Contains a null element");
837 [MethodImplAttribute(MethodImplOptions.InternalCall)]
838 extern static void Select_internal (ref Socket [] sockets, int microSeconds, out int error);
844 public bool Poll (int time_us, SelectMode mode)
846 ThrowIfDisposedAndClosed ();
848 if (mode != SelectMode.SelectRead && mode != SelectMode.SelectWrite && mode != SelectMode.SelectError)
849 throw new NotSupportedException ("'mode' parameter is not valid.");
852 bool result = Poll_internal (safe_handle, mode, time_us, out error);
855 throw new SocketException (error);
857 if (mode == SelectMode.SelectWrite && result && !is_connected) {
858 /* Update the is_connected state; for non-blocking Connect()
859 * this is when we can find out that the connect succeeded. */
860 if ((int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error) == 0)
867 static bool Poll_internal (SafeSocketHandle safeHandle, SelectMode mode, int timeout, out int error)
869 bool release = false;
871 safeHandle.DangerousAddRef (ref release);
872 return Poll_internal (safeHandle.DangerousGetHandle (), mode, timeout, out error);
875 safeHandle.DangerousRelease ();
879 [MethodImplAttribute(MethodImplOptions.InternalCall)]
880 extern static bool Poll_internal (IntPtr socket, SelectMode mode, int timeout, out int error);
886 public Socket Accept()
888 ThrowIfDisposedAndClosed ();
891 SafeSocketHandle safe_handle = Accept_internal (this.safe_handle, out error, is_blocking);
895 error = SOCKET_CLOSED_CODE;
896 throw new SocketException(error);
899 Socket accepted = new Socket (this.AddressFamily, this.SocketType, this.ProtocolType, safe_handle) {
900 seed_endpoint = this.seed_endpoint,
901 Blocking = this.Blocking,
907 internal void Accept (Socket acceptSocket)
909 ThrowIfDisposedAndClosed ();
912 SafeSocketHandle safe_handle = Accept_internal (this.safe_handle, out error, is_blocking);
916 error = SOCKET_CLOSED_CODE;
917 throw new SocketException (error);
920 acceptSocket.address_family = this.AddressFamily;
921 acceptSocket.socket_type = this.SocketType;
922 acceptSocket.protocol_type = this.ProtocolType;
923 acceptSocket.safe_handle = safe_handle;
924 acceptSocket.is_connected = true;
925 acceptSocket.seed_endpoint = this.seed_endpoint;
926 acceptSocket.Blocking = this.Blocking;
928 // FIXME: figure out what if anything else needs to be reset
931 public bool AcceptAsync (SocketAsyncEventArgs e)
933 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
935 ThrowIfDisposedAndClosed ();
938 throw new InvalidOperationException ("You must call the Bind method before performing this operation.");
940 throw new InvalidOperationException ("You must call the Listen method before performing this operation.");
941 if (e.BufferList != null)
942 throw new ArgumentException ("Multiple buffers cannot be used with this method.");
944 throw new ArgumentOutOfRangeException ("e.Count");
946 Socket acceptSocket = e.AcceptSocket;
947 if (acceptSocket != null) {
948 if (acceptSocket.is_bound || acceptSocket.is_connected)
949 throw new InvalidOperationException ("AcceptSocket: The socket must not be bound or connected.");
952 InitSocketAsyncEventArgs (e, AcceptAsyncCallback, e, SocketOperation.Accept);
954 QueueIOSelectorJob (readQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Read, BeginAcceptCallback, e.socket_async_result));
959 static AsyncCallback AcceptAsyncCallback = new AsyncCallback (ares => {
960 SocketAsyncEventArgs e = (SocketAsyncEventArgs) ((SocketAsyncResult) ares).AsyncState;
962 if (Interlocked.Exchange (ref e.in_progress, 0) != 1)
963 throw new InvalidOperationException ("No operation in progress");
966 e.AcceptSocket = e.current_socket.EndAccept (ares);
967 } catch (SocketException ex) {
968 e.SocketError = ex.SocketErrorCode;
969 } catch (ObjectDisposedException) {
970 e.SocketError = SocketError.OperationAborted;
972 if (e.AcceptSocket == null)
973 e.AcceptSocket = new Socket (e.current_socket.AddressFamily, e.current_socket.SocketType, e.current_socket.ProtocolType, null);
978 public IAsyncResult BeginAccept(AsyncCallback callback, object state)
980 ThrowIfDisposedAndClosed ();
982 if (!is_bound || !is_listening)
983 throw new InvalidOperationException ();
985 SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.Accept);
987 QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginAcceptCallback, sockares));
992 static IOAsyncCallback BeginAcceptCallback = new IOAsyncCallback (ares => {
993 SocketAsyncResult sockares = (SocketAsyncResult) ares;
994 Socket socket = null;
997 socket = sockares.socket.Accept ();
998 } catch (Exception e) {
999 sockares.Complete (e);
1003 sockares.Complete (socket);
1006 public IAsyncResult BeginAccept (int receiveSize, AsyncCallback callback, object state)
1008 ThrowIfDisposedAndClosed ();
1010 if (receiveSize < 0)
1011 throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
1013 SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.AcceptReceive) {
1014 Buffer = new byte [receiveSize],
1017 SockFlags = SocketFlags.None,
1020 QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginAcceptReceiveCallback, sockares));
1025 public IAsyncResult BeginAccept (Socket acceptSocket, int receiveSize, AsyncCallback callback, object state)
1027 ThrowIfDisposedAndClosed ();
1029 if (receiveSize < 0)
1030 throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
1032 if (acceptSocket != null) {
1033 ThrowIfDisposedAndClosed (acceptSocket);
1035 if (acceptSocket.IsBound)
1036 throw new InvalidOperationException ();
1038 /* For some reason the MS runtime
1039 * barfs if the new socket is not TCP,
1040 * even though it's just about to blow
1041 * away all those parameters
1043 if (acceptSocket.ProtocolType != ProtocolType.Tcp)
1044 throw new SocketException ((int)SocketError.InvalidArgument);
1047 SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.AcceptReceive) {
1048 Buffer = new byte [receiveSize],
1051 SockFlags = SocketFlags.None,
1052 AcceptSocket = acceptSocket,
1055 QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginAcceptReceiveCallback, sockares));
1060 static IOAsyncCallback BeginAcceptReceiveCallback = new IOAsyncCallback (ares => {
1061 SocketAsyncResult sockares = (SocketAsyncResult) ares;
1062 Socket acc_socket = null;
1065 if (sockares.AcceptSocket == null) {
1066 acc_socket = sockares.socket.Accept ();
1068 acc_socket = sockares.AcceptSocket;
1069 sockares.socket.Accept (acc_socket);
1071 } catch (Exception e) {
1072 sockares.Complete (e);
1076 /* It seems the MS runtime special-cases 0-length requested receive data. See bug 464201. */
1078 if (sockares.Size > 0) {
1081 total = acc_socket.Receive_nochecks (sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, out error);
1083 sockares.Complete (new SocketException ((int) error));
1086 } catch (Exception e) {
1087 sockares.Complete (e);
1092 sockares.Complete (acc_socket, total);
1095 public Socket EndAccept (IAsyncResult result)
1099 return EndAccept (out buffer, out bytes, result);
1102 public Socket EndAccept (out byte[] buffer, IAsyncResult asyncResult)
1105 return EndAccept (out buffer, out bytes, asyncResult);
1108 public Socket EndAccept (out byte[] buffer, out int bytesTransferred, IAsyncResult asyncResult)
1110 ThrowIfDisposedAndClosed ();
1112 SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndAccept", "asyncResult");
1114 if (!sockares.IsCompleted)
1115 sockares.AsyncWaitHandle.WaitOne ();
1117 sockares.CheckIfThrowDelayedException ();
1119 buffer = sockares.Buffer;
1120 bytesTransferred = sockares.Total;
1122 return sockares.AcceptedSocket;
1125 static SafeSocketHandle Accept_internal (SafeSocketHandle safeHandle, out int error, bool blocking)
1128 safeHandle.RegisterForBlockingSyscall ();
1129 var ret = Accept_internal (safeHandle.DangerousGetHandle (), out error, blocking);
1130 return new SafeSocketHandle (ret, true);
1132 safeHandle.UnRegisterForBlockingSyscall ();
1136 /* Creates a new system socket, returning the handle */
1137 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1138 extern static IntPtr Accept_internal (IntPtr sock, out int error, bool blocking);
1144 public void Bind (EndPoint local_end)
1146 ThrowIfDisposedAndClosed ();
1148 if (local_end == null)
1149 throw new ArgumentNullException("local_end");
1151 var ipEndPoint = local_end as IPEndPoint;
1152 if (ipEndPoint != null) {
1153 local_end = RemapIPEndPoint (ipEndPoint);
1157 Bind_internal (safe_handle, local_end.Serialize(), out error);
1160 throw new SocketException (error);
1164 seed_endpoint = local_end;
1167 private static void Bind_internal (SafeSocketHandle safeHandle, SocketAddress sa, out int error)
1169 bool release = false;
1171 safeHandle.DangerousAddRef (ref release);
1172 Bind_internal (safeHandle.DangerousGetHandle (), sa, out error);
1175 safeHandle.DangerousRelease ();
1179 // Creates a new system socket, returning the handle
1180 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1181 private extern static void Bind_internal(IntPtr sock, SocketAddress sa, out int error);
1187 public void Listen (int backlog)
1189 ThrowIfDisposedAndClosed ();
1192 throw new SocketException ((int) SocketError.InvalidArgument);
1195 Listen_internal(safe_handle, backlog, out error);
1198 throw new SocketException (error);
1200 is_listening = true;
1203 static void Listen_internal (SafeSocketHandle safeHandle, int backlog, out int error)
1205 bool release = false;
1207 safeHandle.DangerousAddRef (ref release);
1208 Listen_internal (safeHandle.DangerousGetHandle (), backlog, out error);
1211 safeHandle.DangerousRelease ();
1215 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1216 extern static void Listen_internal (IntPtr sock, int backlog, out int error);
1222 public void Connect (IPAddress address, int port)
1224 Connect (new IPEndPoint (address, port));
1227 public void Connect (string host, int port)
1229 Connect (Dns.GetHostAddresses (host), port);
1232 public void Connect (IPAddress[] addresses, int port)
1234 ThrowIfDisposedAndClosed ();
1236 if (addresses == null)
1237 throw new ArgumentNullException ("addresses");
1238 if (this.AddressFamily != AddressFamily.InterNetwork && this.AddressFamily != AddressFamily.InterNetworkV6)
1239 throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
1241 throw new InvalidOperationException ();
1243 // FIXME: do non-blocking sockets Poll here?
1245 foreach (IPAddress address in addresses) {
1246 IPEndPoint iep = new IPEndPoint (address, port);
1248 iep = RemapIPEndPoint (iep);
1250 Connect_internal (safe_handle, iep.Serialize (), out error);
1252 is_connected = true;
1254 seed_endpoint = iep;
1257 if (error != (int)SocketError.InProgress && error != (int)SocketError.WouldBlock)
1261 Poll (-1, SelectMode.SelectWrite);
1262 error = (int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
1264 is_connected = true;
1266 seed_endpoint = iep;
1273 throw new SocketException (error);
1277 public void Connect (EndPoint remoteEP)
1279 ThrowIfDisposedAndClosed ();
1281 if (remoteEP == null)
1282 throw new ArgumentNullException ("remoteEP");
1284 IPEndPoint ep = remoteEP as IPEndPoint;
1285 /* Dgram uses Any to 'disconnect' */
1286 if (ep != null && socket_type != SocketType.Dgram) {
1287 if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any))
1288 throw new SocketException ((int) SocketError.AddressNotAvailable);
1292 throw new InvalidOperationException ();
1295 remoteEP = RemapIPEndPoint (ep);
1298 SocketAddress serial = remoteEP.Serialize ();
1301 Connect_internal (safe_handle, serial, out error);
1303 if (error == 0 || error == 10035)
1304 seed_endpoint = remoteEP; // Keep the ep around for non-blocking sockets
1308 error = SOCKET_CLOSED_CODE;
1309 throw new SocketException (error);
1312 is_connected = !(socket_type == SocketType.Dgram && ep != null && (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)));
1316 public bool ConnectAsync (SocketAsyncEventArgs e)
1318 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1320 ThrowIfDisposedAndClosed ();
1323 throw new InvalidOperationException ("You may not perform this operation after calling the Listen method.");
1324 if (e.RemoteEndPoint == null)
1325 throw new ArgumentNullException ("remoteEP");
1327 InitSocketAsyncEventArgs (e, ConnectAsyncCallback, e, SocketOperation.Connect);
1330 IPAddress [] addresses;
1331 SocketAsyncResult ares;
1333 if (!GetCheckedIPs (e, out addresses)) {
1334 e.socket_async_result.EndPoint = e.RemoteEndPoint;
1335 ares = (SocketAsyncResult) BeginConnect (e.RemoteEndPoint, ConnectAsyncCallback, e);
1337 DnsEndPoint dep = (e.RemoteEndPoint as DnsEndPoint);
1338 e.socket_async_result.Addresses = addresses;
1339 e.socket_async_result.Port = dep.Port;
1340 ares = (SocketAsyncResult) BeginConnect (addresses, dep.Port, ConnectAsyncCallback, e);
1343 if (ares.IsCompleted && ares.CompletedSynchronously) {
1344 ares.CheckIfThrowDelayedException ();
1347 } catch (Exception exc) {
1348 e.socket_async_result.Complete (exc, true);
1355 static AsyncCallback ConnectAsyncCallback = new AsyncCallback (ares => {
1356 SocketAsyncEventArgs e = (SocketAsyncEventArgs) ((SocketAsyncResult) ares).AsyncState;
1358 if (Interlocked.Exchange (ref e.in_progress, 0) != 1)
1359 throw new InvalidOperationException ("No operation in progress");
1362 e.current_socket.EndConnect (ares);
1363 } catch (SocketException se) {
1364 e.SocketError = se.SocketErrorCode;
1365 } catch (ObjectDisposedException) {
1366 e.SocketError = SocketError.OperationAborted;
1372 public IAsyncResult BeginConnect (IPAddress address, int port, AsyncCallback callback, object state)
1374 ThrowIfDisposedAndClosed ();
1376 if (address == null)
1377 throw new ArgumentNullException ("address");
1378 if (address.ToString ().Length == 0)
1379 throw new ArgumentException ("The length of the IP address is zero");
1380 if (port <= 0 || port > 65535)
1381 throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
1383 throw new InvalidOperationException ();
1385 return BeginConnect (new IPEndPoint (address, port), callback, state);
1388 public IAsyncResult BeginConnect (string host, int port, AsyncCallback callback, object state)
1390 ThrowIfDisposedAndClosed ();
1393 throw new ArgumentNullException ("host");
1394 if (address_family != AddressFamily.InterNetwork && address_family != AddressFamily.InterNetworkV6)
1395 throw new NotSupportedException ("This method is valid only for sockets in the InterNetwork and InterNetworkV6 families");
1396 if (port <= 0 || port > 65535)
1397 throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
1399 throw new InvalidOperationException ();
1401 return BeginConnect (Dns.GetHostAddresses (host), port, callback, state);
1404 public IAsyncResult BeginConnect (EndPoint end_point, AsyncCallback callback, object state)
1406 ThrowIfDisposedAndClosed ();
1408 if (end_point == null)
1409 throw new ArgumentNullException ("end_point");
1411 SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.Connect) {
1412 EndPoint = end_point,
1415 // Bug #75154: Connect() should not succeed for .Any addresses.
1416 if (end_point is IPEndPoint) {
1417 IPEndPoint ep = (IPEndPoint) end_point;
1418 if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)) {
1419 sockares.Complete (new SocketException ((int) SocketError.AddressNotAvailable), true);
1423 end_point = RemapIPEndPoint (ep);
1428 if (connect_in_progress) {
1429 // This could happen when multiple IPs are used
1430 // Calling connect() again will reset the connection attempt and cause
1431 // an error. Better to just close the socket and move on.
1432 connect_in_progress = false;
1433 safe_handle.Dispose ();
1434 safe_handle = new SafeSocketHandle (Socket_internal (address_family, socket_type, protocol_type, out error), true);
1436 throw new SocketException (error);
1439 bool blk = is_blocking;
1442 Connect_internal (safe_handle, end_point.Serialize (), out error);
1448 is_connected = true;
1450 sockares.Complete (true);
1454 if (error != (int) SocketError.InProgress && error != (int) SocketError.WouldBlock) {
1456 is_connected = false;
1458 sockares.Complete (new SocketException (error), true);
1463 is_connected = false;
1465 connect_in_progress = true;
1467 IOSelector.Add (sockares.Handle, new IOSelectorJob (IOOperation.Write, BeginConnectCallback, sockares));
1472 public IAsyncResult BeginConnect (IPAddress[] addresses, int port, AsyncCallback callback, object state)
1474 ThrowIfDisposedAndClosed ();
1476 if (addresses == null)
1477 throw new ArgumentNullException ("addresses");
1478 if (addresses.Length == 0)
1479 throw new ArgumentException ("Empty addresses list");
1480 if (this.AddressFamily != AddressFamily.InterNetwork && this.AddressFamily != AddressFamily.InterNetworkV6)
1481 throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
1482 if (port <= 0 || port > 65535)
1483 throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
1485 throw new InvalidOperationException ();
1487 SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.Connect) {
1488 Addresses = addresses,
1492 is_connected = false;
1494 return BeginMConnect (sockares);
1497 internal IAsyncResult BeginMConnect (SocketAsyncResult sockares)
1499 SocketAsyncResult ares = null;
1500 Exception exc = null;
1501 AsyncCallback callback;
1503 for (int i = sockares.CurrentAddress; i < sockares.Addresses.Length; i++) {
1505 sockares.CurrentAddress++;
1507 ares = (SocketAsyncResult) BeginConnect (new IPEndPoint (sockares.Addresses [i], sockares.Port), null, sockares);
1508 if (ares.IsCompleted && ares.CompletedSynchronously) {
1509 ares.CheckIfThrowDelayedException ();
1511 callback = ares.AsyncCallback;
1512 if (callback != null)
1513 ThreadPool.UnsafeQueueUserWorkItem (_ => callback (ares), null);
1517 } catch (Exception e) {
1529 static IOAsyncCallback BeginConnectCallback = new IOAsyncCallback (ares => {
1530 SocketAsyncResult sockares = (SocketAsyncResult) ares;
1532 if (sockares.EndPoint == null) {
1533 sockares.Complete (new SocketException ((int)SocketError.AddressNotAvailable));
1537 SocketAsyncResult mconnect = sockares.AsyncState as SocketAsyncResult;
1538 bool is_mconnect = mconnect != null && mconnect.Addresses != null;
1541 EndPoint ep = sockares.EndPoint;
1542 int error_code = (int) sockares.socket.GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
1544 if (error_code == 0) {
1546 sockares = mconnect;
1548 sockares.socket.seed_endpoint = ep;
1549 sockares.socket.is_connected = true;
1550 sockares.socket.is_bound = true;
1551 sockares.socket.connect_in_progress = false;
1553 sockares.Complete ();
1558 sockares.socket.connect_in_progress = false;
1559 sockares.Complete (new SocketException (error_code));
1563 if (mconnect.CurrentAddress >= mconnect.Addresses.Length) {
1564 mconnect.Complete (new SocketException (error_code));
1568 mconnect.socket.BeginMConnect (mconnect);
1569 } catch (Exception e) {
1570 sockares.socket.connect_in_progress = false;
1573 sockares = mconnect;
1575 sockares.Complete (e);
1580 public void EndConnect (IAsyncResult result)
1582 ThrowIfDisposedAndClosed ();
1584 SocketAsyncResult sockares = ValidateEndIAsyncResult (result, "EndConnect", "result");
1586 if (!sockares.IsCompleted)
1587 sockares.AsyncWaitHandle.WaitOne();
1589 sockares.CheckIfThrowDelayedException();
1592 static void Connect_internal (SafeSocketHandle safeHandle, SocketAddress sa, out int error)
1595 safeHandle.RegisterForBlockingSyscall ();
1596 Connect_internal (safeHandle.DangerousGetHandle (), sa, out error);
1598 safeHandle.UnRegisterForBlockingSyscall ();
1602 /* Connects to the remote address */
1603 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1604 extern static void Connect_internal(IntPtr sock, SocketAddress sa, out int error);
1607 * - false when it is ok to use RemoteEndPoint
1608 * - true when addresses must be used (and addresses could be null/empty) */
1609 bool GetCheckedIPs (SocketAsyncEventArgs e, out IPAddress [] addresses)
1613 // Connect to the first address that match the host name, like:
1614 // http://blogs.msdn.com/ncl/archive/2009/07/20/new-ncl-features-in-net-4-0-beta-2.aspx
1615 // while skipping entries that do not match the address family
1616 DnsEndPoint dep = e.RemoteEndPoint as DnsEndPoint;
1618 addresses = Dns.GetHostAddresses (dep.Host);
1621 e.ConnectByNameError = null;
1630 /* According to the docs, the MS runtime will throw PlatformNotSupportedException
1631 * if the platform is newer than w2k. We should be able to cope... */
1632 public void Disconnect (bool reuseSocket)
1634 ThrowIfDisposedAndClosed ();
1637 Disconnect_internal (safe_handle, reuseSocket, out error);
1641 /* ERROR_NOT_SUPPORTED */
1642 throw new PlatformNotSupportedException ();
1644 throw new SocketException (error);
1648 is_connected = false;
1650 /* Do managed housekeeping here... */
1654 public bool DisconnectAsync (SocketAsyncEventArgs e)
1656 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1658 ThrowIfDisposedAndClosed ();
1660 InitSocketAsyncEventArgs (e, DisconnectAsyncCallback, e, SocketOperation.Disconnect);
1662 IOSelector.Add (e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Write, BeginDisconnectCallback, e.socket_async_result));
1667 static AsyncCallback DisconnectAsyncCallback = new AsyncCallback (ares => {
1668 SocketAsyncEventArgs e = (SocketAsyncEventArgs) ((SocketAsyncResult) ares).AsyncState;
1670 if (Interlocked.Exchange (ref e.in_progress, 0) != 1)
1671 throw new InvalidOperationException ("No operation in progress");
1674 e.current_socket.EndDisconnect (ares);
1675 } catch (SocketException ex) {
1676 e.SocketError = ex.SocketErrorCode;
1677 } catch (ObjectDisposedException) {
1678 e.SocketError = SocketError.OperationAborted;
1684 public IAsyncResult BeginDisconnect (bool reuseSocket, AsyncCallback callback, object state)
1686 ThrowIfDisposedAndClosed ();
1688 SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.Disconnect) {
1689 ReuseSocket = reuseSocket,
1692 IOSelector.Add (sockares.Handle, new IOSelectorJob (IOOperation.Write, BeginDisconnectCallback, sockares));
1697 static IOAsyncCallback BeginDisconnectCallback = new IOAsyncCallback (ares => {
1698 SocketAsyncResult sockares = (SocketAsyncResult) ares;
1701 sockares.socket.Disconnect (sockares.ReuseSocket);
1702 } catch (Exception e) {
1703 sockares.Complete (e);
1707 sockares.Complete ();
1710 public void EndDisconnect (IAsyncResult asyncResult)
1712 ThrowIfDisposedAndClosed ();
1714 SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndDisconnect", "asyncResult");
1716 if (!sockares.IsCompleted)
1717 sockares.AsyncWaitHandle.WaitOne ();
1719 sockares.CheckIfThrowDelayedException ();
1722 static void Disconnect_internal (SafeSocketHandle safeHandle, bool reuse, out int error)
1724 bool release = false;
1726 safeHandle.DangerousAddRef (ref release);
1727 Disconnect_internal (safeHandle.DangerousGetHandle (), reuse, out error);
1730 safeHandle.DangerousRelease ();
1734 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1735 extern static void Disconnect_internal (IntPtr sock, bool reuse, out int error);
1741 public int Receive (byte [] buffer)
1743 return Receive (buffer, SocketFlags.None);
1746 public int Receive (byte [] buffer, SocketFlags flags)
1748 ThrowIfDisposedAndClosed ();
1749 ThrowIfBufferNull (buffer);
1750 ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
1753 int ret = Receive_nochecks (buffer, 0, buffer.Length, flags, out error);
1755 if (error != SocketError.Success) {
1756 if (error == SocketError.WouldBlock && is_blocking) // This might happen when ReceiveTimeout is set
1757 throw new SocketException ((int) error, TIMEOUT_EXCEPTION_MSG);
1758 throw new SocketException ((int) error);
1764 public int Receive (byte [] buffer, int size, SocketFlags flags)
1766 ThrowIfDisposedAndClosed ();
1767 ThrowIfBufferNull (buffer);
1768 ThrowIfBufferOutOfRange (buffer, 0, size);
1771 int ret = Receive_nochecks (buffer, 0, size, flags, out error);
1773 if (error != SocketError.Success) {
1774 if (error == SocketError.WouldBlock && is_blocking) // This might happen when ReceiveTimeout is set
1775 throw new SocketException ((int) error, TIMEOUT_EXCEPTION_MSG);
1776 throw new SocketException ((int) error);
1782 public int Receive (byte [] buffer, int offset, int size, SocketFlags flags)
1784 ThrowIfDisposedAndClosed ();
1785 ThrowIfBufferNull (buffer);
1786 ThrowIfBufferOutOfRange (buffer, offset, size);
1789 int ret = Receive_nochecks (buffer, offset, size, flags, out error);
1791 if (error != SocketError.Success) {
1792 if (error == SocketError.WouldBlock && is_blocking) // This might happen when ReceiveTimeout is set
1793 throw new SocketException ((int) error, TIMEOUT_EXCEPTION_MSG);
1794 throw new SocketException ((int) error);
1800 public int Receive (byte [] buffer, int offset, int size, SocketFlags flags, out SocketError error)
1802 ThrowIfDisposedAndClosed ();
1803 ThrowIfBufferNull (buffer);
1804 ThrowIfBufferOutOfRange (buffer, offset, size);
1806 return Receive_nochecks (buffer, offset, size, flags, out error);
1809 public int Receive (IList<ArraySegment<byte>> buffers)
1812 int ret = Receive (buffers, SocketFlags.None, out error);
1814 if (error != SocketError.Success)
1815 throw new SocketException ((int) error);
1820 [CLSCompliant (false)]
1821 public int Receive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags)
1824 int ret = Receive (buffers, socketFlags, out error);
1826 if (error != SocketError.Success)
1827 throw new SocketException ((int) error);
1832 [CLSCompliant (false)]
1833 public int Receive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode)
1835 ThrowIfDisposedAndClosed ();
1837 if (buffers == null || buffers.Count == 0)
1838 throw new ArgumentNullException ("buffers");
1840 int numsegments = buffers.Count;
1844 /* Only example I can find of sending a byte array reference directly into an internal
1845 * call is in System.Runtime.Remoting/System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeSocket.cs,
1846 * so taking a lead from that... */
1847 WSABUF[] bufarray = new WSABUF[numsegments];
1848 GCHandle[] gch = new GCHandle[numsegments];
1850 for (int i = 0; i < numsegments; i++) {
1851 ArraySegment<byte> segment = buffers[i];
1853 if (segment.Offset < 0 || segment.Count < 0 || segment.Count > segment.Array.Length - segment.Offset)
1854 throw new ArgumentOutOfRangeException ("segment");
1856 gch[i] = GCHandle.Alloc (segment.Array, GCHandleType.Pinned);
1857 bufarray[i].len = segment.Count;
1858 bufarray[i].buf = Marshal.UnsafeAddrOfPinnedArrayElement (segment.Array, segment.Offset);
1862 ret = Receive_internal (safe_handle, bufarray, socketFlags, out nativeError);
1864 for (int i = 0; i < numsegments; i++) {
1865 if (gch[i].IsAllocated)
1870 errorCode = (SocketError) nativeError;
1875 public bool ReceiveAsync (SocketAsyncEventArgs e)
1877 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1879 ThrowIfDisposedAndClosed ();
1881 // LAME SPEC: the ArgumentException is never thrown, instead an NRE is
1882 // thrown when e.Buffer and e.BufferList are null (works fine when one is
1883 // set to a valid object)
1884 if (e.Buffer == null && e.BufferList == null)
1885 throw new NullReferenceException ("Either e.Buffer or e.BufferList must be valid buffers.");
1887 if (e.Buffer == null) {
1888 InitSocketAsyncEventArgs (e, ReceiveAsyncCallback, e, SocketOperation.ReceiveGeneric);
1890 e.socket_async_result.Buffers = e.BufferList;
1892 QueueIOSelectorJob (readQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveGenericCallback, e.socket_async_result));
1894 InitSocketAsyncEventArgs (e, ReceiveAsyncCallback, e, SocketOperation.Receive);
1896 e.socket_async_result.Buffer = e.Buffer;
1897 e.socket_async_result.Offset = e.Offset;
1898 e.socket_async_result.Size = e.Count;
1900 QueueIOSelectorJob (readQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveCallback, e.socket_async_result));
1906 static AsyncCallback ReceiveAsyncCallback = new AsyncCallback (ares => {
1907 SocketAsyncEventArgs e = (SocketAsyncEventArgs) ((SocketAsyncResult) ares).AsyncState;
1909 if (Interlocked.Exchange (ref e.in_progress, 0) != 1)
1910 throw new InvalidOperationException ("No operation in progress");
1913 e.BytesTransferred = e.current_socket.EndReceive (ares);
1914 } catch (SocketException se){
1915 e.SocketError = se.SocketErrorCode;
1916 } catch (ObjectDisposedException) {
1917 e.SocketError = SocketError.OperationAborted;
1923 public IAsyncResult BeginReceive (byte[] buffer, int offset, int size, SocketFlags socket_flags, AsyncCallback callback, object state)
1925 ThrowIfDisposedAndClosed ();
1926 ThrowIfBufferNull (buffer);
1927 ThrowIfBufferOutOfRange (buffer, offset, size);
1929 SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.Receive) {
1933 SockFlags = socket_flags,
1936 QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveCallback, sockares));
1941 public IAsyncResult BeginReceive (byte[] buffer, int offset, int size, SocketFlags flags, out SocketError error, AsyncCallback callback, object state)
1943 /* As far as I can tell from the docs and from experimentation, a pointer to the
1944 * SocketError parameter is not supposed to be saved for the async parts. And as we don't
1945 * set any socket errors in the setup code, we just have to set it to Success. */
1946 error = SocketError.Success;
1947 return BeginReceive (buffer, offset, size, flags, callback, state);
1950 static IOAsyncCallback BeginReceiveCallback = new IOAsyncCallback (ares => {
1951 SocketAsyncResult sockares = (SocketAsyncResult) ares;
1955 total = Receive_internal (sockares.socket.safe_handle, sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, out sockares.error);
1956 } catch (Exception e) {
1957 sockares.Complete (e);
1961 sockares.Complete (total);
1964 [CLSCompliant (false)]
1965 public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, AsyncCallback callback, object state)
1967 ThrowIfDisposedAndClosed ();
1969 if (buffers == null)
1970 throw new ArgumentNullException ("buffers");
1972 SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.ReceiveGeneric) {
1974 SockFlags = socketFlags,
1977 QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveGenericCallback, sockares));
1982 [CLSCompliant (false)]
1983 public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
1985 /* I assume the same SocketError semantics as above */
1986 errorCode = SocketError.Success;
1987 return BeginReceive (buffers, socketFlags, callback, state);
1990 static IOAsyncCallback BeginReceiveGenericCallback = new IOAsyncCallback (ares => {
1991 SocketAsyncResult sockares = (SocketAsyncResult) ares;
1995 total = sockares.socket.Receive (sockares.Buffers, sockares.SockFlags);
1996 } catch (Exception e) {
1997 sockares.Complete (e);
2001 sockares.Complete (total);
2004 public int EndReceive (IAsyncResult result)
2007 int bytesReceived = EndReceive (result, out error);
2009 if (error != SocketError.Success) {
2010 if (error != SocketError.WouldBlock && error != SocketError.InProgress)
2011 is_connected = false;
2012 throw new SocketException ((int)error);
2015 return bytesReceived;
2018 public int EndReceive (IAsyncResult asyncResult, out SocketError errorCode)
2020 ThrowIfDisposedAndClosed ();
2022 SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndReceive", "asyncResult");
2024 if (!sockares.IsCompleted)
2025 sockares.AsyncWaitHandle.WaitOne ();
2027 // If no socket error occurred, call CheckIfThrowDelayedException in case there are other
2028 // kinds of exceptions that should be thrown.
2029 if ((errorCode = sockares.ErrorCode) == SocketError.Success)
2030 sockares.CheckIfThrowDelayedException();
2032 return sockares.Total;
2035 int Receive_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
2038 int ret = Receive_internal (safe_handle, buf, offset, size, flags, out nativeError);
2040 error = (SocketError) nativeError;
2041 if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress) {
2042 is_connected = false;
2045 is_connected = true;
2051 static int Receive_internal (SafeSocketHandle safeHandle, WSABUF[] bufarray, SocketFlags flags, out int error)
2054 safeHandle.RegisterForBlockingSyscall ();
2055 return Receive_internal (safeHandle.DangerousGetHandle (), bufarray, flags, out error);
2057 safeHandle.UnRegisterForBlockingSyscall ();
2061 [MethodImplAttribute (MethodImplOptions.InternalCall)]
2062 extern static int Receive_internal (IntPtr sock, WSABUF[] bufarray, SocketFlags flags, out int error);
2064 static int Receive_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, out int error)
2067 safeHandle.RegisterForBlockingSyscall ();
2068 return Receive_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, out error);
2070 safeHandle.UnRegisterForBlockingSyscall ();
2074 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2075 extern static int Receive_internal(IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags, out int error);
2081 public int ReceiveFrom (byte [] buffer, ref EndPoint remoteEP)
2083 ThrowIfDisposedAndClosed ();
2084 ThrowIfBufferNull (buffer);
2086 return ReceiveFrom (buffer, 0, buffer.Length, SocketFlags.None, ref remoteEP);
2089 public int ReceiveFrom (byte [] buffer, SocketFlags flags, ref EndPoint remoteEP)
2091 ThrowIfDisposedAndClosed ();
2092 ThrowIfBufferNull (buffer);
2094 return ReceiveFrom (buffer, 0, buffer.Length, flags, ref remoteEP);
2097 public int ReceiveFrom (byte [] buffer, int size, SocketFlags flags, ref EndPoint remoteEP)
2099 ThrowIfDisposedAndClosed ();
2100 ThrowIfBufferNull (buffer);
2101 ThrowIfBufferOutOfRange (buffer, 0, size);
2103 return ReceiveFrom (buffer, 0, size, flags, ref remoteEP);
2106 public int ReceiveFrom (byte [] buffer, int offset, int size, SocketFlags flags, ref EndPoint remoteEP)
2108 ThrowIfDisposedAndClosed ();
2109 ThrowIfBufferNull (buffer);
2110 ThrowIfBufferOutOfRange (buffer, offset, size);
2112 if (remoteEP == null)
2113 throw new ArgumentNullException ("remoteEP");
2116 return ReceiveFrom_nochecks_exc (buffer, offset, size, flags, ref remoteEP, true, out error);
2119 public bool ReceiveFromAsync (SocketAsyncEventArgs e)
2121 ThrowIfDisposedAndClosed ();
2123 // We do not support recv into multiple buffers yet
2124 if (e.BufferList != null)
2125 throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
2126 if (e.RemoteEndPoint == null)
2127 throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
2129 InitSocketAsyncEventArgs (e, ReceiveFromAsyncCallback, e, SocketOperation.ReceiveFrom);
2131 e.socket_async_result.Buffer = e.Buffer;
2132 e.socket_async_result.Offset = e.Offset;
2133 e.socket_async_result.Size = e.Count;
2134 e.socket_async_result.EndPoint = e.RemoteEndPoint;
2135 e.socket_async_result.SockFlags = e.SocketFlags;
2137 QueueIOSelectorJob (readQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveFromCallback, e.socket_async_result));
2142 static AsyncCallback ReceiveFromAsyncCallback = new AsyncCallback (ares => {
2143 SocketAsyncEventArgs e = (SocketAsyncEventArgs) ((SocketAsyncResult) ares).AsyncState;
2145 if (Interlocked.Exchange (ref e.in_progress, 0) != 1)
2146 throw new InvalidOperationException ("No operation in progress");
2149 e.BytesTransferred = e.current_socket.EndReceiveFrom (ares, ref e.remote_ep);
2150 } catch (SocketException ex) {
2151 e.SocketError = ex.SocketErrorCode;
2152 } catch (ObjectDisposedException) {
2153 e.SocketError = SocketError.OperationAborted;
2159 public IAsyncResult BeginReceiveFrom (byte[] buffer, int offset, int size, SocketFlags socket_flags, ref EndPoint remote_end, AsyncCallback callback, object state)
2161 ThrowIfDisposedAndClosed ();
2162 ThrowIfBufferNull (buffer);
2163 ThrowIfBufferOutOfRange (buffer, offset, size);
2165 if (remote_end == null)
2166 throw new ArgumentNullException ("remote_end");
2168 SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.ReceiveFrom) {
2172 SockFlags = socket_flags,
2173 EndPoint = remote_end,
2176 QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveFromCallback, sockares));
2181 static IOAsyncCallback BeginReceiveFromCallback = new IOAsyncCallback (ares => {
2182 SocketAsyncResult sockares = (SocketAsyncResult) ares;
2187 total = sockares.socket.ReceiveFrom_nochecks_exc (sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, ref sockares.EndPoint, true, out error);
2188 } catch (Exception e) {
2189 sockares.Complete (e);
2193 sockares.Complete (total);
2196 public int EndReceiveFrom(IAsyncResult result, ref EndPoint end_point)
2198 ThrowIfDisposedAndClosed ();
2200 if (end_point == null)
2201 throw new ArgumentNullException ("remote_end");
2203 SocketAsyncResult sockares = ValidateEndIAsyncResult (result, "EndReceiveFrom", "result");
2205 if (!sockares.IsCompleted)
2206 sockares.AsyncWaitHandle.WaitOne();
2208 sockares.CheckIfThrowDelayedException();
2210 end_point = sockares.EndPoint;
2212 return sockares.Total;
2215 internal int ReceiveFrom_nochecks_exc (byte [] buf, int offset, int size, SocketFlags flags, ref EndPoint remote_end, bool throwOnError, out int error)
2217 SocketAddress sockaddr = remote_end.Serialize();
2219 int cnt = ReceiveFrom_internal (safe_handle, buf, offset, size, flags, ref sockaddr, out error);
2221 SocketError err = (SocketError) error;
2223 if (err != SocketError.WouldBlock && err != SocketError.InProgress) {
2224 is_connected = false;
2225 } else if (err == SocketError.WouldBlock && is_blocking) { // This might happen when ReceiveTimeout is set
2227 throw new SocketException ((int) SocketError.TimedOut, TIMEOUT_EXCEPTION_MSG);
2228 error = (int) SocketError.TimedOut;
2233 throw new SocketException (error);
2238 is_connected = true;
2241 /* If sockaddr is null then we're a connection oriented protocol and should ignore the
2242 * remote_end parameter (see MSDN documentation for Socket.ReceiveFrom(...) ) */
2243 if (sockaddr != null) {
2244 /* Stupidly, EndPoint.Create() is an instance method */
2245 remote_end = remote_end.Create (sockaddr);
2248 seed_endpoint = remote_end;
2253 static int ReceiveFrom_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, ref SocketAddress sockaddr, out int error)
2256 safeHandle.RegisterForBlockingSyscall ();
2257 return ReceiveFrom_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, ref sockaddr, out error);
2259 safeHandle.UnRegisterForBlockingSyscall ();
2263 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2264 extern static int ReceiveFrom_internal(IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags, ref SocketAddress sockaddr, out int error);
2268 #region ReceiveMessageFrom
2270 [MonoTODO ("Not implemented")]
2271 public int ReceiveMessageFrom (byte[] buffer, int offset, int size, ref SocketFlags socketFlags, ref EndPoint remoteEP, out IPPacketInformation ipPacketInformation)
2273 ThrowIfDisposedAndClosed ();
2274 ThrowIfBufferNull (buffer);
2275 ThrowIfBufferOutOfRange (buffer, offset, size);
2277 if (remoteEP == null)
2278 throw new ArgumentNullException ("remoteEP");
2280 // FIXME: figure out how we get hold of the IPPacketInformation
2281 throw new NotImplementedException ();
2284 [MonoTODO ("Not implemented")]
2285 public bool ReceiveMessageFromAsync (SocketAsyncEventArgs e)
2287 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
2289 ThrowIfDisposedAndClosed ();
2291 throw new NotImplementedException ();
2295 public IAsyncResult BeginReceiveMessageFrom (byte[] buffer, int offset, int size, SocketFlags socketFlags, ref EndPoint remoteEP, AsyncCallback callback, object state)
2297 ThrowIfDisposedAndClosed ();
2298 ThrowIfBufferNull (buffer);
2299 ThrowIfBufferOutOfRange (buffer, offset, size);
2301 if (remoteEP == null)
2302 throw new ArgumentNullException ("remoteEP");
2304 throw new NotImplementedException ();
2308 public int EndReceiveMessageFrom (IAsyncResult asyncResult, ref SocketFlags socketFlags, ref EndPoint endPoint, out IPPacketInformation ipPacketInformation)
2310 ThrowIfDisposedAndClosed ();
2312 if (endPoint == null)
2313 throw new ArgumentNullException ("endPoint");
2315 SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndReceiveMessageFrom", "asyncResult");
2317 throw new NotImplementedException ();
2324 public int Send (byte [] buffer)
2326 ThrowIfDisposedAndClosed ();
2327 ThrowIfBufferNull (buffer);
2328 ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
2331 int ret = Send_nochecks (buffer, 0, buffer.Length, SocketFlags.None, out error);
2333 if (error != SocketError.Success)
2334 throw new SocketException ((int) error);
2339 public int Send (byte [] buffer, SocketFlags flags)
2341 ThrowIfDisposedAndClosed ();
2342 ThrowIfBufferNull (buffer);
2343 ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
2346 int ret = Send_nochecks (buffer, 0, buffer.Length, flags, out error);
2348 if (error != SocketError.Success)
2349 throw new SocketException ((int) error);
2354 public int Send (byte [] buffer, int size, SocketFlags flags)
2356 ThrowIfDisposedAndClosed ();
2357 ThrowIfBufferNull (buffer);
2358 ThrowIfBufferOutOfRange (buffer, 0, size);
2361 int ret = Send_nochecks (buffer, 0, size, flags, out error);
2363 if (error != SocketError.Success)
2364 throw new SocketException ((int) error);
2369 public int Send (byte [] buffer, int offset, int size, SocketFlags flags)
2371 ThrowIfDisposedAndClosed ();
2372 ThrowIfBufferNull (buffer);
2373 ThrowIfBufferOutOfRange (buffer, offset, size);
2376 int ret = Send_nochecks (buffer, offset, size, flags, out error);
2378 if (error != SocketError.Success)
2379 throw new SocketException ((int) error);
2384 public int Send (byte [] buffer, int offset, int size, SocketFlags flags, out SocketError error)
2386 ThrowIfDisposedAndClosed ();
2387 ThrowIfBufferNull (buffer);
2388 ThrowIfBufferOutOfRange (buffer, offset, size);
2390 return Send_nochecks (buffer, offset, size, flags, out error);
2394 int Send (IList<ArraySegment<byte>> buffers)
2397 int ret = Send (buffers, SocketFlags.None, out error);
2399 if (error != SocketError.Success)
2400 throw new SocketException ((int) error);
2406 int Send (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags)
2409 int ret = Send (buffers, socketFlags, out error);
2411 if (error != SocketError.Success)
2412 throw new SocketException ((int) error);
2417 [CLSCompliant (false)]
2418 public int Send (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode)
2420 ThrowIfDisposedAndClosed ();
2422 if (buffers == null)
2423 throw new ArgumentNullException ("buffers");
2424 if (buffers.Count == 0)
2425 throw new ArgumentException ("Buffer is empty", "buffers");
2427 int numsegments = buffers.Count;
2431 WSABUF[] bufarray = new WSABUF[numsegments];
2432 GCHandle[] gch = new GCHandle[numsegments];
2434 for(int i = 0; i < numsegments; i++) {
2435 ArraySegment<byte> segment = buffers[i];
2437 if (segment.Offset < 0 || segment.Count < 0 || segment.Count > segment.Array.Length - segment.Offset)
2438 throw new ArgumentOutOfRangeException ("segment");
2440 gch[i] = GCHandle.Alloc (segment.Array, GCHandleType.Pinned);
2441 bufarray[i].len = segment.Count;
2442 bufarray[i].buf = Marshal.UnsafeAddrOfPinnedArrayElement (segment.Array, segment.Offset);
2446 ret = Send_internal (safe_handle, bufarray, socketFlags, out nativeError);
2448 for(int i = 0; i < numsegments; i++) {
2449 if (gch[i].IsAllocated) {
2455 errorCode = (SocketError)nativeError;
2460 int Send_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
2463 error = SocketError.Success;
2468 int ret = Send_internal (safe_handle, buf, offset, size, flags, out nativeError);
2470 error = (SocketError)nativeError;
2472 if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress) {
2473 is_connected = false;
2476 is_connected = true;
2482 public bool SendAsync (SocketAsyncEventArgs e)
2484 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
2486 ThrowIfDisposedAndClosed ();
2488 if (e.Buffer == null && e.BufferList == null)
2489 throw new NullReferenceException ("Either e.Buffer or e.BufferList must be valid buffers.");
2491 if (e.Buffer == null) {
2492 InitSocketAsyncEventArgs (e, SendAsyncCallback, e, SocketOperation.SendGeneric);
2494 e.socket_async_result.Buffers = e.BufferList;
2496 QueueIOSelectorJob (writeQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Write, BeginSendGenericCallback, e.socket_async_result));
2498 InitSocketAsyncEventArgs (e, SendAsyncCallback, e, SocketOperation.Send);
2500 e.socket_async_result.Buffer = e.Buffer;
2501 e.socket_async_result.Offset = e.Offset;
2502 e.socket_async_result.Size = e.Count;
2504 QueueIOSelectorJob (writeQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendCallback ((SocketAsyncResult) s, 0), e.socket_async_result));
2510 static AsyncCallback SendAsyncCallback = new AsyncCallback (ares => {
2511 SocketAsyncEventArgs e = (SocketAsyncEventArgs) ((SocketAsyncResult) ares).AsyncState;
2513 if (Interlocked.Exchange (ref e.in_progress, 0) != 1)
2514 throw new InvalidOperationException ("No operation in progress");
2517 e.BytesTransferred = e.current_socket.EndSend (ares);
2518 } catch (SocketException se){
2519 e.SocketError = se.SocketErrorCode;
2520 } catch (ObjectDisposedException) {
2521 e.SocketError = SocketError.OperationAborted;
2527 public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
2529 if (!is_connected) {
2530 errorCode = SocketError.NotConnected;
2531 throw new SocketException ((int) errorCode);
2534 errorCode = SocketError.Success;
2535 return BeginSend (buffer, offset, size, socketFlags, callback, state);
2538 public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socket_flags, AsyncCallback callback, object state)
2540 ThrowIfDisposedAndClosed ();
2541 ThrowIfBufferNull (buffer);
2542 ThrowIfBufferOutOfRange (buffer, offset, size);
2545 throw new SocketException ((int)SocketError.NotConnected);
2547 SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.Send) {
2551 SockFlags = socket_flags,
2554 QueueIOSelectorJob (writeQ, sockares.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendCallback ((SocketAsyncResult) s, 0), sockares));
2559 static void BeginSendCallback (SocketAsyncResult sockares, int sent_so_far)
2564 total = Socket.Send_internal (sockares.socket.safe_handle, sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, out sockares.error);
2565 } catch (Exception e) {
2566 sockares.Complete (e);
2570 if (sockares.error == 0) {
2571 sent_so_far += total;
2572 sockares.Offset += total;
2573 sockares.Size -= total;
2575 if (sockares.socket.is_disposed) {
2576 sockares.Complete (total);
2580 if (sockares.Size > 0) {
2581 IOSelector.Add (sockares.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendCallback ((SocketAsyncResult) s, sent_so_far), sockares));
2582 return; // Have to finish writing everything. See bug #74475.
2585 sockares.Total = sent_so_far;
2588 sockares.Complete (total);
2591 public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, AsyncCallback callback, object state)
2593 ThrowIfDisposedAndClosed ();
2595 if (buffers == null)
2596 throw new ArgumentNullException ("buffers");
2598 throw new SocketException ((int)SocketError.NotConnected);
2600 SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.SendGeneric) {
2602 SockFlags = socketFlags,
2605 QueueIOSelectorJob (writeQ, sockares.Handle, new IOSelectorJob (IOOperation.Write, BeginSendGenericCallback, sockares));
2610 [CLSCompliant (false)]
2611 public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
2613 if (!is_connected) {
2614 errorCode = SocketError.NotConnected;
2615 throw new SocketException ((int)errorCode);
2618 errorCode = SocketError.Success;
2619 return BeginSend (buffers, socketFlags, callback, state);
2622 static IOAsyncCallback BeginSendGenericCallback = new IOAsyncCallback (ares => {
2623 SocketAsyncResult sockares = (SocketAsyncResult) ares;
2627 total = sockares.socket.Send (sockares.Buffers, sockares.SockFlags);
2628 } catch (Exception e) {
2629 sockares.Complete (e);
2633 sockares.Complete (total);
2636 public int EndSend (IAsyncResult result)
2639 int bytesSent = EndSend (result, out error);
2641 if (error != SocketError.Success) {
2642 if (error != SocketError.WouldBlock && error != SocketError.InProgress)
2643 is_connected = false;
2644 throw new SocketException ((int)error);
2650 public int EndSend (IAsyncResult asyncResult, out SocketError errorCode)
2652 ThrowIfDisposedAndClosed ();
2654 SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndSend", "asyncResult");
2656 if (!sockares.IsCompleted)
2657 sockares.AsyncWaitHandle.WaitOne ();
2659 /* If no socket error occurred, call CheckIfThrowDelayedException in
2660 * case there are other kinds of exceptions that should be thrown.*/
2661 if ((errorCode = sockares.ErrorCode) == SocketError.Success)
2662 sockares.CheckIfThrowDelayedException ();
2664 return sockares.Total;
2667 static int Send_internal (SafeSocketHandle safeHandle, WSABUF[] bufarray, SocketFlags flags, out int error)
2669 bool release = false;
2671 safeHandle.DangerousAddRef (ref release);
2672 return Send_internal (safeHandle.DangerousGetHandle (), bufarray, flags, out error);
2675 safeHandle.DangerousRelease ();
2679 [MethodImplAttribute (MethodImplOptions.InternalCall)]
2680 extern static int Send_internal (IntPtr sock, WSABUF[] bufarray, SocketFlags flags, out int error);
2682 static int Send_internal (SafeSocketHandle safeHandle, byte[] buf, int offset, int count, SocketFlags flags, out int error)
2685 safeHandle.RegisterForBlockingSyscall ();
2686 return Send_internal (safeHandle.DangerousGetHandle (), buf, offset, count, flags, out error);
2688 safeHandle.UnRegisterForBlockingSyscall ();
2692 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2693 extern static int Send_internal(IntPtr sock, byte[] buf, int offset, int count, SocketFlags flags, out int error);
2699 public int SendTo (byte [] buffer, EndPoint remote_end)
2701 ThrowIfDisposedAndClosed ();
2702 ThrowIfBufferNull (buffer);
2704 return SendTo (buffer, 0, buffer.Length, SocketFlags.None, remote_end);
2707 public int SendTo (byte [] buffer, SocketFlags flags, EndPoint remote_end)
2709 ThrowIfDisposedAndClosed ();
2710 ThrowIfBufferNull (buffer);
2712 return SendTo (buffer, 0, buffer.Length, flags, remote_end);
2715 public int SendTo (byte [] buffer, int size, SocketFlags flags, EndPoint remote_end)
2717 return SendTo (buffer, 0, size, flags, remote_end);
2720 public int SendTo (byte [] buffer, int offset, int size, SocketFlags flags, EndPoint remote_end)
2722 ThrowIfDisposedAndClosed ();
2723 ThrowIfBufferNull (buffer);
2724 ThrowIfBufferOutOfRange (buffer, offset, size);
2726 if (remote_end == null)
2727 throw new ArgumentNullException("remote_end");
2729 return SendTo_nochecks (buffer, offset, size, flags, remote_end);
2732 public bool SendToAsync (SocketAsyncEventArgs e)
2734 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
2736 ThrowIfDisposedAndClosed ();
2738 if (e.BufferList != null)
2739 throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
2740 if (e.RemoteEndPoint == null)
2741 throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
2743 InitSocketAsyncEventArgs (e, SendToAsyncCallback, e, SocketOperation.SendTo);
2745 e.socket_async_result.Buffer = e.Buffer;
2746 e.socket_async_result.Offset = e.Offset;
2747 e.socket_async_result.Size = e.Count;
2748 e.socket_async_result.SockFlags = e.SocketFlags;
2749 e.socket_async_result.EndPoint = e.RemoteEndPoint;
2751 QueueIOSelectorJob (writeQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendToCallback ((SocketAsyncResult) s, 0), e.socket_async_result));
2756 static AsyncCallback SendToAsyncCallback = new AsyncCallback (ares => {
2757 SocketAsyncEventArgs e = (SocketAsyncEventArgs) ((SocketAsyncResult) ares).AsyncState;
2759 if (Interlocked.Exchange (ref e.in_progress, 0) != 1)
2760 throw new InvalidOperationException ("No operation in progress");
2763 e.BytesTransferred = e.current_socket.EndSendTo (ares);
2764 } catch (SocketException ex) {
2765 e.SocketError = ex.SocketErrorCode;
2766 } catch (ObjectDisposedException) {
2767 e.SocketError = SocketError.OperationAborted;
2773 public IAsyncResult BeginSendTo(byte[] buffer, int offset, int size, SocketFlags socket_flags, EndPoint remote_end, AsyncCallback callback, object state)
2775 ThrowIfDisposedAndClosed ();
2776 ThrowIfBufferNull (buffer);
2777 ThrowIfBufferOutOfRange (buffer, offset, size);
2779 SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.SendTo) {
2783 SockFlags = socket_flags,
2784 EndPoint = remote_end,
2787 QueueIOSelectorJob (writeQ, sockares.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendToCallback ((SocketAsyncResult) s, 0), sockares));
2792 static void BeginSendToCallback (SocketAsyncResult sockares, int sent_so_far)
2796 total = sockares.socket.SendTo_nochecks (sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, sockares.EndPoint);
2798 if (sockares.error == 0) {
2799 sent_so_far += total;
2800 sockares.Offset += total;
2801 sockares.Size -= total;
2804 if (sockares.Size > 0) {
2805 IOSelector.Add (sockares.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendToCallback ((SocketAsyncResult) s, sent_so_far), sockares));
2806 return; // Have to finish writing everything. See bug #74475.
2809 sockares.Total = sent_so_far;
2810 } catch (Exception e) {
2811 sockares.Complete (e);
2815 sockares.Complete ();
2818 public int EndSendTo (IAsyncResult result)
2820 ThrowIfDisposedAndClosed ();
2822 SocketAsyncResult sockares = ValidateEndIAsyncResult (result, "EndSendTo", "result");
2824 if (!sockares.IsCompleted)
2825 sockares.AsyncWaitHandle.WaitOne();
2827 sockares.CheckIfThrowDelayedException();
2829 return sockares.Total;
2832 int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags, EndPoint remote_end)
2835 int ret = SendTo_internal (safe_handle, buffer, offset, size, flags, remote_end.Serialize (), out error);
2837 SocketError err = (SocketError) error;
2839 if (err != SocketError.WouldBlock && err != SocketError.InProgress)
2840 is_connected = false;
2841 throw new SocketException (error);
2844 is_connected = true;
2846 seed_endpoint = remote_end;
2851 static int SendTo_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, SocketAddress sa, out int error)
2854 safeHandle.RegisterForBlockingSyscall ();
2855 return SendTo_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, sa, out error);
2857 safeHandle.UnRegisterForBlockingSyscall ();
2861 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2862 extern static int SendTo_internal (IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags, SocketAddress sa, out int error);
2868 public void SendFile (string fileName)
2870 ThrowIfDisposedAndClosed ();
2873 throw new NotSupportedException ();
2875 throw new InvalidOperationException ();
2877 SendFile (fileName, null, null, 0);
2880 public void SendFile (string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags)
2882 ThrowIfDisposedAndClosed ();
2885 throw new NotSupportedException ();
2887 throw new InvalidOperationException ();
2889 if (!SendFile_internal (safe_handle, fileName, preBuffer, postBuffer, flags)) {
2890 SocketException exc = new SocketException ();
2891 if (exc.ErrorCode == 2 || exc.ErrorCode == 3)
2892 throw new FileNotFoundException ();
2897 public IAsyncResult BeginSendFile (string fileName, AsyncCallback callback, object state)
2899 ThrowIfDisposedAndClosed ();
2902 throw new NotSupportedException ();
2903 if (!File.Exists (fileName))
2904 throw new FileNotFoundException ();
2906 return BeginSendFile (fileName, null, null, 0, callback, state);
2909 public IAsyncResult BeginSendFile (string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags, AsyncCallback callback, object state)
2911 ThrowIfDisposedAndClosed ();
2914 throw new NotSupportedException ();
2915 if (!File.Exists (fileName))
2916 throw new FileNotFoundException ();
2918 SendFileHandler handler = new SendFileHandler (SendFile);
2920 return new SendFileAsyncResult (handler, handler.BeginInvoke (fileName, preBuffer, postBuffer, flags, ar => callback (new SendFileAsyncResult (handler, ar)), state));
2923 public void EndSendFile (IAsyncResult asyncResult)
2925 ThrowIfDisposedAndClosed ();
2927 if (asyncResult == null)
2928 throw new ArgumentNullException ("asyncResult");
2930 SendFileAsyncResult ares = asyncResult as SendFileAsyncResult;
2932 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
2934 ares.Delegate.EndInvoke (ares.Original);
2937 static bool SendFile_internal (SafeSocketHandle safeHandle, string filename, byte [] pre_buffer, byte [] post_buffer, TransmitFileOptions flags)
2940 safeHandle.RegisterForBlockingSyscall ();
2941 return SendFile_internal (safeHandle.DangerousGetHandle (), filename, pre_buffer, post_buffer, flags);
2943 safeHandle.UnRegisterForBlockingSyscall ();
2947 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2948 extern static bool SendFile_internal (IntPtr sock, string filename, byte [] pre_buffer, byte [] post_buffer, TransmitFileOptions flags);
2950 delegate void SendFileHandler (string fileName, byte [] preBuffer, byte [] postBuffer, TransmitFileOptions flags);
2952 sealed class SendFileAsyncResult : IAsyncResult {
2956 public SendFileAsyncResult (SendFileHandler d, IAsyncResult ares)
2962 public object AsyncState {
2963 get { return ares.AsyncState; }
2966 public WaitHandle AsyncWaitHandle {
2967 get { return ares.AsyncWaitHandle; }
2970 public bool CompletedSynchronously {
2971 get { return ares.CompletedSynchronously; }
2974 public bool IsCompleted {
2975 get { return ares.IsCompleted; }
2978 public SendFileHandler Delegate {
2982 public IAsyncResult Original {
2983 get { return ares; }
2991 [MonoTODO ("Not implemented")]
2992 public bool SendPacketsAsync (SocketAsyncEventArgs e)
2994 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
2996 ThrowIfDisposedAndClosed ();
2998 throw new NotImplementedException ();
3003 #region DuplicateAndClose
3006 [MonoLimitation ("We do not support passing sockets across processes, we merely allow this API to pass the socket across AppDomains")]
3007 public SocketInformation DuplicateAndClose (int targetProcessId)
3009 var si = new SocketInformation ();
3011 (is_listening ? SocketInformationOptions.Listening : 0) |
3012 (is_connected ? SocketInformationOptions.Connected : 0) |
3013 (is_blocking ? 0 : SocketInformationOptions.NonBlocking) |
3014 (use_overlapped_io ? SocketInformationOptions.UseOnlyOverlappedIO : 0);
3016 si.ProtocolInformation = Mono.DataConverter.Pack ("iiiil", (int)address_family, (int)socket_type, (int)protocol_type, is_bound ? 1 : 0, (long)Handle);
3025 #region GetSocketOption
3027 public void GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, byte [] optionValue)
3029 ThrowIfDisposedAndClosed ();
3031 if (optionValue == null)
3032 throw new SocketException ((int) SocketError.Fault, "Error trying to dereference an invalid pointer");
3035 GetSocketOption_arr_internal (safe_handle, optionLevel, optionName, ref optionValue, out error);
3038 throw new SocketException (error);
3041 public byte [] GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int length)
3043 ThrowIfDisposedAndClosed ();
3046 byte[] byte_val = new byte [length];
3047 GetSocketOption_arr_internal (safe_handle, optionLevel, optionName, ref byte_val, out error);
3050 throw new SocketException (error);
3055 public object GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName)
3057 ThrowIfDisposedAndClosed ();
3061 GetSocketOption_obj_internal (safe_handle, optionLevel, optionName, out obj_val, out error);
3064 throw new SocketException (error);
3066 if (optionName == SocketOptionName.Linger)
3067 return (LingerOption) obj_val;
3068 else if (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)
3069 return (MulticastOption) obj_val;
3070 else if (obj_val is int)
3071 return (int) obj_val;
3076 static void GetSocketOption_arr_internal (SafeSocketHandle safeHandle, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val, out int error)
3078 bool release = false;
3080 safeHandle.DangerousAddRef (ref release);
3081 GetSocketOption_arr_internal (safeHandle.DangerousGetHandle (), level, name, ref byte_val, out error);
3084 safeHandle.DangerousRelease ();
3088 [MethodImplAttribute(MethodImplOptions.InternalCall)]
3089 extern static void GetSocketOption_arr_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val, out int error);
3091 static void GetSocketOption_obj_internal (SafeSocketHandle safeHandle, SocketOptionLevel level, SocketOptionName name, out object obj_val, out int error)
3093 bool release = false;
3095 safeHandle.DangerousAddRef (ref release);
3096 GetSocketOption_obj_internal (safeHandle.DangerousGetHandle (), level, name, out obj_val, out error);
3099 safeHandle.DangerousRelease ();
3103 [MethodImplAttribute(MethodImplOptions.InternalCall)]
3104 extern static void GetSocketOption_obj_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, out object obj_val, out int error);
3108 #region SetSocketOption
3110 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, byte [] optionValue)
3112 ThrowIfDisposedAndClosed ();
3114 // I'd throw an ArgumentNullException, but this is what MS does.
3115 if (optionValue == null)
3116 throw new SocketException ((int) SocketError.Fault, "Error trying to dereference an invalid pointer");
3119 SetSocketOption_internal (safe_handle, optionLevel, optionName, null, optionValue, 0, out error);
3122 if (error == (int) SocketError.InvalidArgument)
3123 throw new ArgumentException ();
3124 throw new SocketException (error);
3128 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, object optionValue)
3130 ThrowIfDisposedAndClosed ();
3132 // NOTE: if a null is passed, the byte[] overload is used instead...
3133 if (optionValue == null)
3134 throw new ArgumentNullException("optionValue");
3138 if (optionLevel == SocketOptionLevel.Socket && optionName == SocketOptionName.Linger) {
3139 LingerOption linger = optionValue as LingerOption;
3141 throw new ArgumentException ("A 'LingerOption' value must be specified.", "optionValue");
3142 SetSocketOption_internal (safe_handle, optionLevel, optionName, linger, null, 0, out error);
3143 } else if (optionLevel == SocketOptionLevel.IP && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
3144 MulticastOption multicast = optionValue as MulticastOption;
3145 if (multicast == null)
3146 throw new ArgumentException ("A 'MulticastOption' value must be specified.", "optionValue");
3147 SetSocketOption_internal (safe_handle, optionLevel, optionName, multicast, null, 0, out error);
3148 } else if (optionLevel == SocketOptionLevel.IPv6 && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
3149 IPv6MulticastOption multicast = optionValue as IPv6MulticastOption;
3150 if (multicast == null)
3151 throw new ArgumentException ("A 'IPv6MulticastOption' value must be specified.", "optionValue");
3152 SetSocketOption_internal (safe_handle, optionLevel, optionName, multicast, null, 0, out error);
3154 throw new ArgumentException ("Invalid value specified.", "optionValue");
3158 if (error == (int) SocketError.InvalidArgument)
3159 throw new ArgumentException ();
3160 throw new SocketException (error);
3164 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, bool optionValue)
3166 ThrowIfDisposedAndClosed ();
3169 int int_val = optionValue ? 1 : 0;
3170 SetSocketOption_internal (safe_handle, optionLevel, optionName, null, null, int_val, out error);
3173 if (error == (int) SocketError.InvalidArgument)
3174 throw new ArgumentException ();
3175 throw new SocketException (error);
3179 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int optionValue)
3181 ThrowIfDisposedAndClosed ();
3184 SetSocketOption_internal (safe_handle, optionLevel, optionName, null, null, optionValue, out error);
3187 throw new SocketException (error);
3191 static void SetSocketOption_internal (SafeSocketHandle safeHandle, SocketOptionLevel level, SocketOptionName name, object obj_val, byte [] byte_val, int int_val, out int error)
3193 bool release = false;
3195 safeHandle.DangerousAddRef (ref release);
3196 SetSocketOption_internal (safeHandle.DangerousGetHandle (), level, name, obj_val, byte_val, int_val, out error);
3199 safeHandle.DangerousRelease ();
3203 [MethodImplAttribute(MethodImplOptions.InternalCall)]
3204 extern static void SetSocketOption_internal (IntPtr socket, SocketOptionLevel level, SocketOptionName name, object obj_val, byte [] byte_val, int int_val, out int error);
3210 public int IOControl (int ioctl_code, byte [] in_value, byte [] out_value)
3213 throw new ObjectDisposedException (GetType ().ToString ());
3216 int result = IOControl_internal (safe_handle, ioctl_code, in_value, out_value, out error);
3219 throw new SocketException (error);
3221 throw new InvalidOperationException ("Must use Blocking property instead.");
3226 public int IOControl (IOControlCode ioControlCode, byte[] optionInValue, byte[] optionOutValue)
3228 return IOControl ((int) ioControlCode, optionInValue, optionOutValue);
3231 static int IOControl_internal (SafeSocketHandle safeHandle, int ioctl_code, byte [] input, byte [] output, out int error)
3233 bool release = false;
3235 safeHandle.DangerousAddRef (ref release);
3236 return IOControl_internal (safeHandle.DangerousGetHandle (), ioctl_code, input, output, out error);
3239 safeHandle.DangerousRelease ();
3243 /* See Socket.IOControl, WSAIoctl documentation in MSDN. The common options between UNIX
3244 * and Winsock are FIONREAD, FIONBIO and SIOCATMARK. Anything else will depend on the system
3245 * except SIO_KEEPALIVE_VALS which is properly handled on both windows and linux. */
3246 [MethodImplAttribute(MethodImplOptions.InternalCall)]
3247 extern static int IOControl_internal (IntPtr sock, int ioctl_code, byte [] input, byte [] output, out int error);
3253 public void Close ()
3259 public void Close (int timeout)
3261 linger_timeout = timeout;
3265 [MethodImplAttribute(MethodImplOptions.InternalCall)]
3266 internal extern static void Close_internal (IntPtr socket, out int error);
3272 public void Shutdown (SocketShutdown how)
3274 ThrowIfDisposedAndClosed ();
3277 throw new SocketException (10057); // Not connected
3280 Shutdown_internal (safe_handle, how, out error);
3283 throw new SocketException (error);
3286 static void Shutdown_internal (SafeSocketHandle safeHandle, SocketShutdown how, out int error)
3288 bool release = false;
3290 safeHandle.DangerousAddRef (ref release);
3291 Shutdown_internal (safeHandle.DangerousGetHandle (), how, out error);
3294 safeHandle.DangerousRelease ();
3298 [MethodImplAttribute (MethodImplOptions.InternalCall)]
3299 internal extern static void Shutdown_internal (IntPtr socket, SocketShutdown how, out int error);
3305 protected virtual void Dispose (bool disposing)
3311 bool was_connected = is_connected;
3312 is_connected = false;
3314 if (safe_handle != null) {
3321 safe_handle.Dispose ();
3325 public void Dispose ()
3328 GC.SuppressFinalize (this);
3331 void Linger (IntPtr handle)
3333 if (!is_connected || linger_timeout <= 0)
3336 /* We don't want to receive any more data */
3338 Shutdown_internal (handle, SocketShutdown.Receive, out error);
3343 int seconds = linger_timeout / 1000;
3344 int ms = linger_timeout % 1000;
3346 /* If the other end closes, this will return 'true' with 'Available' == 0 */
3347 Poll_internal (handle, SelectMode.SelectRead, ms * 1000, out error);
3353 LingerOption linger = new LingerOption (true, seconds);
3354 SetSocketOption_internal (handle, SocketOptionLevel.Socket, SocketOptionName.Linger, linger, null, 0, out error);
3355 /* Not needed, we're closing upon return */
3363 void ThrowIfDisposedAndClosed (Socket socket)
3365 if (socket.is_disposed && socket.is_closed)
3366 throw new ObjectDisposedException (socket.GetType ().ToString ());
3369 void ThrowIfDisposedAndClosed ()
3371 if (is_disposed && is_closed)
3372 throw new ObjectDisposedException (GetType ().ToString ());
3375 void ThrowIfBufferNull (byte[] buffer)
3378 throw new ArgumentNullException ("buffer");
3381 void ThrowIfBufferOutOfRange (byte[] buffer, int offset, int size)
3384 throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
3385 if (offset > buffer.Length)
3386 throw new ArgumentOutOfRangeException ("offset", "offset must be <= buffer.Length");
3388 throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
3389 if (size > buffer.Length - offset)
3390 throw new ArgumentOutOfRangeException ("size", "size must be <= buffer.Length - offset");
3395 #if !NET_2_1 || MOBILE
3396 if (protocol_type == ProtocolType.Udp)
3397 throw new SocketException ((int)SocketError.ProtocolOption);
3401 SocketAsyncResult ValidateEndIAsyncResult (IAsyncResult ares, string methodName, string argName)
3404 throw new ArgumentNullException (argName);
3406 SocketAsyncResult sockares = ares as SocketAsyncResult;
3407 if (sockares == null)
3408 throw new ArgumentException ("Invalid IAsyncResult", argName);
3409 if (Interlocked.CompareExchange (ref sockares.EndCalled, 1, 0) == 1)
3410 throw new InvalidOperationException (methodName + " can only be called once per asynchronous operation");
3415 void QueueIOSelectorJob (Queue<KeyValuePair<IntPtr, IOSelectorJob>> queue, IntPtr handle, IOSelectorJob job)
3419 queue.Enqueue (new KeyValuePair<IntPtr, IOSelectorJob> (handle, job));
3420 count = queue.Count;
3424 IOSelector.Add (handle, job);
3427 void InitSocketAsyncEventArgs (SocketAsyncEventArgs e, AsyncCallback callback, object state, SocketOperation operation)
3429 e.socket_async_result.Init (this, callback, state, operation);
3431 e.current_socket = this;
3432 e.SetLastOperation (SocketOperationToSocketAsyncOperation (operation));
3433 e.SocketError = SocketError.Success;
3434 e.BytesTransferred = 0;
3437 SocketAsyncOperation SocketOperationToSocketAsyncOperation (SocketOperation op)
3440 case SocketOperation.Connect:
3441 return SocketAsyncOperation.Connect;
3442 case SocketOperation.Accept:
3443 return SocketAsyncOperation.Accept;
3444 case SocketOperation.Disconnect:
3445 return SocketAsyncOperation.Disconnect;
3446 case SocketOperation.Receive:
3447 case SocketOperation.ReceiveGeneric:
3448 return SocketAsyncOperation.Receive;
3449 case SocketOperation.ReceiveFrom:
3450 return SocketAsyncOperation.ReceiveFrom;
3451 case SocketOperation.Send:
3452 case SocketOperation.SendGeneric:
3453 return SocketAsyncOperation.Send;
3454 case SocketOperation.SendTo:
3455 return SocketAsyncOperation.SendTo;
3457 throw new NotImplementedException (String.Format ("Operation {0} is not implemented", op));
3461 IPEndPoint RemapIPEndPoint (IPEndPoint input) {
3462 // If socket is DualMode ensure we automatically handle mapping IPv4 addresses to IPv6.
3463 if (IsDualMode && input.AddressFamily == AddressFamily.InterNetwork)
3464 return new IPEndPoint (input.Address.MapToIPv6 (), input.Port);
3469 [StructLayout (LayoutKind.Sequential)]
3475 [MethodImplAttribute(MethodImplOptions.InternalCall)]
3476 internal static extern void cancel_blocking_socket_operation (Thread thread);
3478 [MethodImplAttribute(MethodImplOptions.InternalCall)]
3479 internal static extern bool SupportsPortReuse ();