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 acc_socket = null;
996 if (sockares.AcceptSocket == null) {
997 acc_socket = sockares.socket.Accept ();
999 acc_socket = sockares.AcceptSocket;
1000 sockares.socket.Accept (acc_socket);
1003 } catch (Exception e) {
1004 sockares.Complete (e);
1007 sockares.Complete (acc_socket);
1010 public IAsyncResult BeginAccept (int receiveSize, AsyncCallback callback, object state)
1012 ThrowIfDisposedAndClosed ();
1014 if (receiveSize < 0)
1015 throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
1017 SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.AcceptReceive) {
1018 Buffer = new byte [receiveSize],
1021 SockFlags = SocketFlags.None,
1024 QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginAcceptReceiveCallback, sockares));
1029 public IAsyncResult BeginAccept (Socket acceptSocket, int receiveSize, AsyncCallback callback, object state)
1031 ThrowIfDisposedAndClosed ();
1033 if (receiveSize < 0)
1034 throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
1036 if (acceptSocket != null) {
1037 ThrowIfDisposedAndClosed (acceptSocket);
1039 if (acceptSocket.IsBound)
1040 throw new InvalidOperationException ();
1042 /* For some reason the MS runtime
1043 * barfs if the new socket is not TCP,
1044 * even though it's just about to blow
1045 * away all those parameters
1047 if (acceptSocket.ProtocolType != ProtocolType.Tcp)
1048 throw new SocketException ((int)SocketError.InvalidArgument);
1051 SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.AcceptReceive) {
1052 Buffer = new byte [receiveSize],
1055 SockFlags = SocketFlags.None,
1056 AcceptSocket = acceptSocket,
1059 QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginAcceptReceiveCallback, sockares));
1064 static IOAsyncCallback BeginAcceptReceiveCallback = new IOAsyncCallback (ares => {
1065 SocketAsyncResult sockares = (SocketAsyncResult) ares;
1066 Socket acc_socket = null;
1069 if (sockares.AcceptSocket == null) {
1070 acc_socket = sockares.socket.Accept ();
1072 acc_socket = sockares.AcceptSocket;
1073 sockares.socket.Accept (acc_socket);
1075 } catch (Exception e) {
1076 sockares.Complete (e);
1080 /* It seems the MS runtime special-cases 0-length requested receive data. See bug 464201. */
1082 if (sockares.Size > 0) {
1085 total = acc_socket.Receive_nochecks (sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, out error);
1087 sockares.Complete (new SocketException ((int) error));
1090 } catch (Exception e) {
1091 sockares.Complete (e);
1096 sockares.Complete (acc_socket, total);
1099 public Socket EndAccept (IAsyncResult result)
1103 return EndAccept (out buffer, out bytes, result);
1106 public Socket EndAccept (out byte[] buffer, IAsyncResult asyncResult)
1109 return EndAccept (out buffer, out bytes, asyncResult);
1112 public Socket EndAccept (out byte[] buffer, out int bytesTransferred, IAsyncResult asyncResult)
1114 ThrowIfDisposedAndClosed ();
1116 SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndAccept", "asyncResult");
1118 if (!sockares.IsCompleted)
1119 sockares.AsyncWaitHandle.WaitOne ();
1121 sockares.CheckIfThrowDelayedException ();
1123 buffer = sockares.Buffer;
1124 bytesTransferred = sockares.Total;
1126 return sockares.AcceptedSocket;
1129 static SafeSocketHandle Accept_internal (SafeSocketHandle safeHandle, out int error, bool blocking)
1132 safeHandle.RegisterForBlockingSyscall ();
1133 var ret = Accept_internal (safeHandle.DangerousGetHandle (), out error, blocking);
1134 return new SafeSocketHandle (ret, true);
1136 safeHandle.UnRegisterForBlockingSyscall ();
1140 /* Creates a new system socket, returning the handle */
1141 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1142 extern static IntPtr Accept_internal (IntPtr sock, out int error, bool blocking);
1148 public void Bind (EndPoint local_end)
1150 ThrowIfDisposedAndClosed ();
1152 if (local_end == null)
1153 throw new ArgumentNullException("local_end");
1155 var ipEndPoint = local_end as IPEndPoint;
1156 if (ipEndPoint != null) {
1157 local_end = RemapIPEndPoint (ipEndPoint);
1161 Bind_internal (safe_handle, local_end.Serialize(), out error);
1164 throw new SocketException (error);
1168 seed_endpoint = local_end;
1171 private static void Bind_internal (SafeSocketHandle safeHandle, SocketAddress sa, out int error)
1173 bool release = false;
1175 safeHandle.DangerousAddRef (ref release);
1176 Bind_internal (safeHandle.DangerousGetHandle (), sa, out error);
1179 safeHandle.DangerousRelease ();
1183 // Creates a new system socket, returning the handle
1184 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1185 private extern static void Bind_internal(IntPtr sock, SocketAddress sa, out int error);
1191 public void Listen (int backlog)
1193 ThrowIfDisposedAndClosed ();
1196 throw new SocketException ((int) SocketError.InvalidArgument);
1199 Listen_internal(safe_handle, backlog, out error);
1202 throw new SocketException (error);
1204 is_listening = true;
1207 static void Listen_internal (SafeSocketHandle safeHandle, int backlog, out int error)
1209 bool release = false;
1211 safeHandle.DangerousAddRef (ref release);
1212 Listen_internal (safeHandle.DangerousGetHandle (), backlog, out error);
1215 safeHandle.DangerousRelease ();
1219 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1220 extern static void Listen_internal (IntPtr sock, int backlog, out int error);
1226 public void Connect (IPAddress address, int port)
1228 Connect (new IPEndPoint (address, port));
1231 public void Connect (string host, int port)
1233 Connect (Dns.GetHostAddresses (host), port);
1236 public void Connect (IPAddress[] addresses, int port)
1238 ThrowIfDisposedAndClosed ();
1240 if (addresses == null)
1241 throw new ArgumentNullException ("addresses");
1242 if (this.AddressFamily != AddressFamily.InterNetwork && this.AddressFamily != AddressFamily.InterNetworkV6)
1243 throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
1245 throw new InvalidOperationException ();
1247 // FIXME: do non-blocking sockets Poll here?
1249 foreach (IPAddress address in addresses) {
1250 IPEndPoint iep = new IPEndPoint (address, port);
1252 iep = RemapIPEndPoint (iep);
1254 Connect_internal (safe_handle, iep.Serialize (), out error);
1256 is_connected = true;
1258 seed_endpoint = iep;
1261 if (error != (int)SocketError.InProgress && error != (int)SocketError.WouldBlock)
1265 Poll (-1, SelectMode.SelectWrite);
1266 error = (int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
1268 is_connected = true;
1270 seed_endpoint = iep;
1277 throw new SocketException (error);
1281 public void Connect (EndPoint remoteEP)
1283 ThrowIfDisposedAndClosed ();
1285 if (remoteEP == null)
1286 throw new ArgumentNullException ("remoteEP");
1288 IPEndPoint ep = remoteEP as IPEndPoint;
1289 /* Dgram uses Any to 'disconnect' */
1290 if (ep != null && socket_type != SocketType.Dgram) {
1291 if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any))
1292 throw new SocketException ((int) SocketError.AddressNotAvailable);
1296 throw new InvalidOperationException ();
1299 remoteEP = RemapIPEndPoint (ep);
1302 SocketAddress serial = remoteEP.Serialize ();
1305 Connect_internal (safe_handle, serial, out error);
1307 if (error == 0 || error == 10035)
1308 seed_endpoint = remoteEP; // Keep the ep around for non-blocking sockets
1312 error = SOCKET_CLOSED_CODE;
1313 throw new SocketException (error);
1316 is_connected = !(socket_type == SocketType.Dgram && ep != null && (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)));
1320 public bool ConnectAsync (SocketAsyncEventArgs e)
1322 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1324 ThrowIfDisposedAndClosed ();
1327 throw new InvalidOperationException ("You may not perform this operation after calling the Listen method.");
1328 if (e.RemoteEndPoint == null)
1329 throw new ArgumentNullException ("remoteEP");
1331 InitSocketAsyncEventArgs (e, ConnectAsyncCallback, e, SocketOperation.Connect);
1334 IPAddress [] addresses;
1335 SocketAsyncResult ares;
1337 if (!GetCheckedIPs (e, out addresses)) {
1338 e.socket_async_result.EndPoint = e.RemoteEndPoint;
1339 ares = (SocketAsyncResult) BeginConnect (e.RemoteEndPoint, ConnectAsyncCallback, e);
1341 DnsEndPoint dep = (e.RemoteEndPoint as DnsEndPoint);
1342 e.socket_async_result.Addresses = addresses;
1343 e.socket_async_result.Port = dep.Port;
1344 ares = (SocketAsyncResult) BeginConnect (addresses, dep.Port, ConnectAsyncCallback, e);
1347 if (ares.IsCompleted && ares.CompletedSynchronously) {
1348 ares.CheckIfThrowDelayedException ();
1351 } catch (Exception exc) {
1352 e.socket_async_result.Complete (exc, true);
1359 static AsyncCallback ConnectAsyncCallback = new AsyncCallback (ares => {
1360 SocketAsyncEventArgs e = (SocketAsyncEventArgs) ((SocketAsyncResult) ares).AsyncState;
1362 if (Interlocked.Exchange (ref e.in_progress, 0) != 1)
1363 throw new InvalidOperationException ("No operation in progress");
1366 e.current_socket.EndConnect (ares);
1367 } catch (SocketException se) {
1368 e.SocketError = se.SocketErrorCode;
1369 } catch (ObjectDisposedException) {
1370 e.SocketError = SocketError.OperationAborted;
1376 public IAsyncResult BeginConnect (IPAddress address, int port, AsyncCallback callback, object state)
1378 ThrowIfDisposedAndClosed ();
1380 if (address == null)
1381 throw new ArgumentNullException ("address");
1382 if (address.ToString ().Length == 0)
1383 throw new ArgumentException ("The length of the IP address is zero");
1384 if (port <= 0 || port > 65535)
1385 throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
1387 throw new InvalidOperationException ();
1389 return BeginConnect (new IPEndPoint (address, port), callback, state);
1392 public IAsyncResult BeginConnect (string host, int port, AsyncCallback callback, object state)
1394 ThrowIfDisposedAndClosed ();
1397 throw new ArgumentNullException ("host");
1398 if (address_family != AddressFamily.InterNetwork && address_family != AddressFamily.InterNetworkV6)
1399 throw new NotSupportedException ("This method is valid only for sockets in the InterNetwork and InterNetworkV6 families");
1400 if (port <= 0 || port > 65535)
1401 throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
1403 throw new InvalidOperationException ();
1405 return BeginConnect (Dns.GetHostAddresses (host), port, callback, state);
1408 public IAsyncResult BeginConnect (EndPoint end_point, AsyncCallback callback, object state)
1410 ThrowIfDisposedAndClosed ();
1412 if (end_point == null)
1413 throw new ArgumentNullException ("end_point");
1415 SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.Connect) {
1416 EndPoint = end_point,
1419 // Bug #75154: Connect() should not succeed for .Any addresses.
1420 if (end_point is IPEndPoint) {
1421 IPEndPoint ep = (IPEndPoint) end_point;
1422 if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)) {
1423 sockares.Complete (new SocketException ((int) SocketError.AddressNotAvailable), true);
1427 end_point = RemapIPEndPoint (ep);
1432 if (connect_in_progress) {
1433 // This could happen when multiple IPs are used
1434 // Calling connect() again will reset the connection attempt and cause
1435 // an error. Better to just close the socket and move on.
1436 connect_in_progress = false;
1437 safe_handle.Dispose ();
1438 safe_handle = new SafeSocketHandle (Socket_internal (address_family, socket_type, protocol_type, out error), true);
1440 throw new SocketException (error);
1443 bool blk = is_blocking;
1446 Connect_internal (safe_handle, end_point.Serialize (), out error);
1452 is_connected = true;
1454 sockares.Complete (true);
1458 if (error != (int) SocketError.InProgress && error != (int) SocketError.WouldBlock) {
1460 is_connected = false;
1462 sockares.Complete (new SocketException (error), true);
1467 is_connected = false;
1469 connect_in_progress = true;
1471 IOSelector.Add (sockares.Handle, new IOSelectorJob (IOOperation.Write, BeginConnectCallback, sockares));
1476 public IAsyncResult BeginConnect (IPAddress[] addresses, int port, AsyncCallback callback, object state)
1478 ThrowIfDisposedAndClosed ();
1480 if (addresses == null)
1481 throw new ArgumentNullException ("addresses");
1482 if (addresses.Length == 0)
1483 throw new ArgumentException ("Empty addresses list");
1484 if (this.AddressFamily != AddressFamily.InterNetwork && this.AddressFamily != AddressFamily.InterNetworkV6)
1485 throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
1486 if (port <= 0 || port > 65535)
1487 throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
1489 throw new InvalidOperationException ();
1491 SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.Connect) {
1492 Addresses = addresses,
1496 is_connected = false;
1498 return BeginMConnect (sockares);
1501 internal IAsyncResult BeginMConnect (SocketAsyncResult sockares)
1503 SocketAsyncResult ares = null;
1504 Exception exc = null;
1505 AsyncCallback callback;
1507 for (int i = sockares.CurrentAddress; i < sockares.Addresses.Length; i++) {
1509 sockares.CurrentAddress++;
1511 ares = (SocketAsyncResult) BeginConnect (new IPEndPoint (sockares.Addresses [i], sockares.Port), null, sockares);
1512 if (ares.IsCompleted && ares.CompletedSynchronously) {
1513 ares.CheckIfThrowDelayedException ();
1515 callback = ares.AsyncCallback;
1516 if (callback != null)
1517 ThreadPool.UnsafeQueueUserWorkItem (_ => callback (ares), null);
1521 } catch (Exception e) {
1533 static IOAsyncCallback BeginConnectCallback = new IOAsyncCallback (ares => {
1534 SocketAsyncResult sockares = (SocketAsyncResult) ares;
1536 if (sockares.EndPoint == null) {
1537 sockares.Complete (new SocketException ((int)SocketError.AddressNotAvailable));
1541 SocketAsyncResult mconnect = sockares.AsyncState as SocketAsyncResult;
1542 bool is_mconnect = mconnect != null && mconnect.Addresses != null;
1545 EndPoint ep = sockares.EndPoint;
1546 int error_code = (int) sockares.socket.GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
1548 if (error_code == 0) {
1550 sockares = mconnect;
1552 sockares.socket.seed_endpoint = ep;
1553 sockares.socket.is_connected = true;
1554 sockares.socket.is_bound = true;
1555 sockares.socket.connect_in_progress = false;
1557 sockares.Complete ();
1562 sockares.socket.connect_in_progress = false;
1563 sockares.Complete (new SocketException (error_code));
1567 if (mconnect.CurrentAddress >= mconnect.Addresses.Length) {
1568 mconnect.Complete (new SocketException (error_code));
1572 mconnect.socket.BeginMConnect (mconnect);
1573 } catch (Exception e) {
1574 sockares.socket.connect_in_progress = false;
1577 sockares = mconnect;
1579 sockares.Complete (e);
1584 public void EndConnect (IAsyncResult result)
1586 ThrowIfDisposedAndClosed ();
1588 SocketAsyncResult sockares = ValidateEndIAsyncResult (result, "EndConnect", "result");
1590 if (!sockares.IsCompleted)
1591 sockares.AsyncWaitHandle.WaitOne();
1593 sockares.CheckIfThrowDelayedException();
1596 static void Connect_internal (SafeSocketHandle safeHandle, SocketAddress sa, out int error)
1599 safeHandle.RegisterForBlockingSyscall ();
1600 Connect_internal (safeHandle.DangerousGetHandle (), sa, out error);
1602 safeHandle.UnRegisterForBlockingSyscall ();
1606 /* Connects to the remote address */
1607 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1608 extern static void Connect_internal(IntPtr sock, SocketAddress sa, out int error);
1611 * - false when it is ok to use RemoteEndPoint
1612 * - true when addresses must be used (and addresses could be null/empty) */
1613 bool GetCheckedIPs (SocketAsyncEventArgs e, out IPAddress [] addresses)
1617 // Connect to the first address that match the host name, like:
1618 // http://blogs.msdn.com/ncl/archive/2009/07/20/new-ncl-features-in-net-4-0-beta-2.aspx
1619 // while skipping entries that do not match the address family
1620 DnsEndPoint dep = e.RemoteEndPoint as DnsEndPoint;
1622 addresses = Dns.GetHostAddresses (dep.Host);
1625 e.ConnectByNameError = null;
1634 /* According to the docs, the MS runtime will throw PlatformNotSupportedException
1635 * if the platform is newer than w2k. We should be able to cope... */
1636 public void Disconnect (bool reuseSocket)
1638 ThrowIfDisposedAndClosed ();
1641 Disconnect_internal (safe_handle, reuseSocket, out error);
1645 /* ERROR_NOT_SUPPORTED */
1646 throw new PlatformNotSupportedException ();
1648 throw new SocketException (error);
1652 is_connected = false;
1654 /* Do managed housekeeping here... */
1658 public bool DisconnectAsync (SocketAsyncEventArgs e)
1660 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1662 ThrowIfDisposedAndClosed ();
1664 InitSocketAsyncEventArgs (e, DisconnectAsyncCallback, e, SocketOperation.Disconnect);
1666 IOSelector.Add (e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Write, BeginDisconnectCallback, e.socket_async_result));
1671 static AsyncCallback DisconnectAsyncCallback = new AsyncCallback (ares => {
1672 SocketAsyncEventArgs e = (SocketAsyncEventArgs) ((SocketAsyncResult) ares).AsyncState;
1674 if (Interlocked.Exchange (ref e.in_progress, 0) != 1)
1675 throw new InvalidOperationException ("No operation in progress");
1678 e.current_socket.EndDisconnect (ares);
1679 } catch (SocketException ex) {
1680 e.SocketError = ex.SocketErrorCode;
1681 } catch (ObjectDisposedException) {
1682 e.SocketError = SocketError.OperationAborted;
1688 public IAsyncResult BeginDisconnect (bool reuseSocket, AsyncCallback callback, object state)
1690 ThrowIfDisposedAndClosed ();
1692 SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.Disconnect) {
1693 ReuseSocket = reuseSocket,
1696 IOSelector.Add (sockares.Handle, new IOSelectorJob (IOOperation.Write, BeginDisconnectCallback, sockares));
1701 static IOAsyncCallback BeginDisconnectCallback = new IOAsyncCallback (ares => {
1702 SocketAsyncResult sockares = (SocketAsyncResult) ares;
1705 sockares.socket.Disconnect (sockares.ReuseSocket);
1706 } catch (Exception e) {
1707 sockares.Complete (e);
1711 sockares.Complete ();
1714 public void EndDisconnect (IAsyncResult asyncResult)
1716 ThrowIfDisposedAndClosed ();
1718 SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndDisconnect", "asyncResult");
1720 if (!sockares.IsCompleted)
1721 sockares.AsyncWaitHandle.WaitOne ();
1723 sockares.CheckIfThrowDelayedException ();
1726 static void Disconnect_internal (SafeSocketHandle safeHandle, bool reuse, out int error)
1728 bool release = false;
1730 safeHandle.DangerousAddRef (ref release);
1731 Disconnect_internal (safeHandle.DangerousGetHandle (), reuse, out error);
1734 safeHandle.DangerousRelease ();
1738 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1739 extern static void Disconnect_internal (IntPtr sock, bool reuse, out int error);
1745 public int Receive (byte [] buffer)
1747 return Receive (buffer, SocketFlags.None);
1750 public int Receive (byte [] buffer, SocketFlags flags)
1752 ThrowIfDisposedAndClosed ();
1753 ThrowIfBufferNull (buffer);
1754 ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
1757 int ret = Receive_nochecks (buffer, 0, buffer.Length, flags, out error);
1759 if (error != SocketError.Success) {
1760 if (error == SocketError.WouldBlock && is_blocking) // This might happen when ReceiveTimeout is set
1761 throw new SocketException ((int) error, TIMEOUT_EXCEPTION_MSG);
1762 throw new SocketException ((int) error);
1768 public int Receive (byte [] buffer, int size, SocketFlags flags)
1770 ThrowIfDisposedAndClosed ();
1771 ThrowIfBufferNull (buffer);
1772 ThrowIfBufferOutOfRange (buffer, 0, size);
1775 int ret = Receive_nochecks (buffer, 0, size, flags, out error);
1777 if (error != SocketError.Success) {
1778 if (error == SocketError.WouldBlock && is_blocking) // This might happen when ReceiveTimeout is set
1779 throw new SocketException ((int) error, TIMEOUT_EXCEPTION_MSG);
1780 throw new SocketException ((int) error);
1786 public int Receive (byte [] buffer, int offset, int size, SocketFlags flags)
1788 ThrowIfDisposedAndClosed ();
1789 ThrowIfBufferNull (buffer);
1790 ThrowIfBufferOutOfRange (buffer, offset, size);
1793 int ret = Receive_nochecks (buffer, offset, size, flags, out error);
1795 if (error != SocketError.Success) {
1796 if (error == SocketError.WouldBlock && is_blocking) // This might happen when ReceiveTimeout is set
1797 throw new SocketException ((int) error, TIMEOUT_EXCEPTION_MSG);
1798 throw new SocketException ((int) error);
1804 public int Receive (byte [] buffer, int offset, int size, SocketFlags flags, out SocketError error)
1806 ThrowIfDisposedAndClosed ();
1807 ThrowIfBufferNull (buffer);
1808 ThrowIfBufferOutOfRange (buffer, offset, size);
1810 return Receive_nochecks (buffer, offset, size, flags, out error);
1813 public int Receive (IList<ArraySegment<byte>> buffers)
1816 int ret = Receive (buffers, SocketFlags.None, out error);
1818 if (error != SocketError.Success)
1819 throw new SocketException ((int) error);
1824 [CLSCompliant (false)]
1825 public int Receive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags)
1828 int ret = Receive (buffers, socketFlags, out error);
1830 if (error != SocketError.Success)
1831 throw new SocketException ((int) error);
1836 [CLSCompliant (false)]
1837 public int Receive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode)
1839 ThrowIfDisposedAndClosed ();
1841 if (buffers == null || buffers.Count == 0)
1842 throw new ArgumentNullException ("buffers");
1844 int numsegments = buffers.Count;
1848 /* Only example I can find of sending a byte array reference directly into an internal
1849 * call is in System.Runtime.Remoting/System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeSocket.cs,
1850 * so taking a lead from that... */
1851 WSABUF[] bufarray = new WSABUF[numsegments];
1852 GCHandle[] gch = new GCHandle[numsegments];
1854 for (int i = 0; i < numsegments; i++) {
1855 ArraySegment<byte> segment = buffers[i];
1857 if (segment.Offset < 0 || segment.Count < 0 || segment.Count > segment.Array.Length - segment.Offset)
1858 throw new ArgumentOutOfRangeException ("segment");
1860 gch[i] = GCHandle.Alloc (segment.Array, GCHandleType.Pinned);
1861 bufarray[i].len = segment.Count;
1862 bufarray[i].buf = Marshal.UnsafeAddrOfPinnedArrayElement (segment.Array, segment.Offset);
1866 ret = Receive_internal (safe_handle, bufarray, socketFlags, out nativeError);
1868 for (int i = 0; i < numsegments; i++) {
1869 if (gch[i].IsAllocated)
1874 errorCode = (SocketError) nativeError;
1879 public bool ReceiveAsync (SocketAsyncEventArgs e)
1881 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1883 ThrowIfDisposedAndClosed ();
1885 // LAME SPEC: the ArgumentException is never thrown, instead an NRE is
1886 // thrown when e.Buffer and e.BufferList are null (works fine when one is
1887 // set to a valid object)
1888 if (e.Buffer == null && e.BufferList == null)
1889 throw new NullReferenceException ("Either e.Buffer or e.BufferList must be valid buffers.");
1891 if (e.Buffer == null) {
1892 InitSocketAsyncEventArgs (e, ReceiveAsyncCallback, e, SocketOperation.ReceiveGeneric);
1894 e.socket_async_result.Buffers = e.BufferList;
1896 QueueIOSelectorJob (readQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveGenericCallback, e.socket_async_result));
1898 InitSocketAsyncEventArgs (e, ReceiveAsyncCallback, e, SocketOperation.Receive);
1900 e.socket_async_result.Buffer = e.Buffer;
1901 e.socket_async_result.Offset = e.Offset;
1902 e.socket_async_result.Size = e.Count;
1904 QueueIOSelectorJob (readQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveCallback, e.socket_async_result));
1910 static AsyncCallback ReceiveAsyncCallback = new AsyncCallback (ares => {
1911 SocketAsyncEventArgs e = (SocketAsyncEventArgs) ((SocketAsyncResult) ares).AsyncState;
1913 if (Interlocked.Exchange (ref e.in_progress, 0) != 1)
1914 throw new InvalidOperationException ("No operation in progress");
1917 e.BytesTransferred = e.current_socket.EndReceive (ares);
1918 } catch (SocketException se){
1919 e.SocketError = se.SocketErrorCode;
1920 } catch (ObjectDisposedException) {
1921 e.SocketError = SocketError.OperationAborted;
1927 public IAsyncResult BeginReceive (byte[] buffer, int offset, int size, SocketFlags socket_flags, AsyncCallback callback, object state)
1929 ThrowIfDisposedAndClosed ();
1930 ThrowIfBufferNull (buffer);
1931 ThrowIfBufferOutOfRange (buffer, offset, size);
1933 SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.Receive) {
1937 SockFlags = socket_flags,
1940 QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveCallback, sockares));
1945 public IAsyncResult BeginReceive (byte[] buffer, int offset, int size, SocketFlags flags, out SocketError error, AsyncCallback callback, object state)
1947 /* As far as I can tell from the docs and from experimentation, a pointer to the
1948 * SocketError parameter is not supposed to be saved for the async parts. And as we don't
1949 * set any socket errors in the setup code, we just have to set it to Success. */
1950 error = SocketError.Success;
1951 return BeginReceive (buffer, offset, size, flags, callback, state);
1954 static IOAsyncCallback BeginReceiveCallback = new IOAsyncCallback (ares => {
1955 SocketAsyncResult sockares = (SocketAsyncResult) ares;
1959 total = Receive_internal (sockares.socket.safe_handle, sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, out sockares.error);
1960 } catch (Exception e) {
1961 sockares.Complete (e);
1965 sockares.Complete (total);
1968 [CLSCompliant (false)]
1969 public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, AsyncCallback callback, object state)
1971 ThrowIfDisposedAndClosed ();
1973 if (buffers == null)
1974 throw new ArgumentNullException ("buffers");
1976 SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.ReceiveGeneric) {
1978 SockFlags = socketFlags,
1981 QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveGenericCallback, sockares));
1986 [CLSCompliant (false)]
1987 public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
1989 /* I assume the same SocketError semantics as above */
1990 errorCode = SocketError.Success;
1991 return BeginReceive (buffers, socketFlags, callback, state);
1994 static IOAsyncCallback BeginReceiveGenericCallback = new IOAsyncCallback (ares => {
1995 SocketAsyncResult sockares = (SocketAsyncResult) ares;
1999 total = sockares.socket.Receive (sockares.Buffers, sockares.SockFlags);
2000 } catch (Exception e) {
2001 sockares.Complete (e);
2005 sockares.Complete (total);
2008 public int EndReceive (IAsyncResult result)
2011 int bytesReceived = EndReceive (result, out error);
2013 if (error != SocketError.Success) {
2014 if (error != SocketError.WouldBlock && error != SocketError.InProgress)
2015 is_connected = false;
2016 throw new SocketException ((int)error);
2019 return bytesReceived;
2022 public int EndReceive (IAsyncResult asyncResult, out SocketError errorCode)
2024 ThrowIfDisposedAndClosed ();
2026 SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndReceive", "asyncResult");
2028 if (!sockares.IsCompleted)
2029 sockares.AsyncWaitHandle.WaitOne ();
2031 // If no socket error occurred, call CheckIfThrowDelayedException in case there are other
2032 // kinds of exceptions that should be thrown.
2033 if ((errorCode = sockares.ErrorCode) == SocketError.Success)
2034 sockares.CheckIfThrowDelayedException();
2036 return sockares.Total;
2039 int Receive_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
2042 int ret = Receive_internal (safe_handle, buf, offset, size, flags, out nativeError);
2044 error = (SocketError) nativeError;
2045 if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress) {
2046 is_connected = false;
2049 is_connected = true;
2055 static int Receive_internal (SafeSocketHandle safeHandle, WSABUF[] bufarray, SocketFlags flags, out int error)
2058 safeHandle.RegisterForBlockingSyscall ();
2059 return Receive_internal (safeHandle.DangerousGetHandle (), bufarray, flags, out error);
2061 safeHandle.UnRegisterForBlockingSyscall ();
2065 [MethodImplAttribute (MethodImplOptions.InternalCall)]
2066 extern static int Receive_internal (IntPtr sock, WSABUF[] bufarray, SocketFlags flags, out int error);
2068 static int Receive_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, out int error)
2071 safeHandle.RegisterForBlockingSyscall ();
2072 return Receive_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, out error);
2074 safeHandle.UnRegisterForBlockingSyscall ();
2078 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2079 extern static int Receive_internal(IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags, out int error);
2085 public int ReceiveFrom (byte [] buffer, ref EndPoint remoteEP)
2087 ThrowIfDisposedAndClosed ();
2088 ThrowIfBufferNull (buffer);
2090 return ReceiveFrom (buffer, 0, buffer.Length, SocketFlags.None, ref remoteEP);
2093 public int ReceiveFrom (byte [] buffer, SocketFlags flags, ref EndPoint remoteEP)
2095 ThrowIfDisposedAndClosed ();
2096 ThrowIfBufferNull (buffer);
2098 return ReceiveFrom (buffer, 0, buffer.Length, flags, ref remoteEP);
2101 public int ReceiveFrom (byte [] buffer, int size, SocketFlags flags, ref EndPoint remoteEP)
2103 ThrowIfDisposedAndClosed ();
2104 ThrowIfBufferNull (buffer);
2105 ThrowIfBufferOutOfRange (buffer, 0, size);
2107 return ReceiveFrom (buffer, 0, size, flags, ref remoteEP);
2110 public int ReceiveFrom (byte [] buffer, int offset, int size, SocketFlags flags, ref EndPoint remoteEP)
2112 ThrowIfDisposedAndClosed ();
2113 ThrowIfBufferNull (buffer);
2114 ThrowIfBufferOutOfRange (buffer, offset, size);
2116 if (remoteEP == null)
2117 throw new ArgumentNullException ("remoteEP");
2120 return ReceiveFrom_nochecks_exc (buffer, offset, size, flags, ref remoteEP, true, out error);
2123 public bool ReceiveFromAsync (SocketAsyncEventArgs e)
2125 ThrowIfDisposedAndClosed ();
2127 // We do not support recv into multiple buffers yet
2128 if (e.BufferList != null)
2129 throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
2130 if (e.RemoteEndPoint == null)
2131 throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
2133 InitSocketAsyncEventArgs (e, ReceiveFromAsyncCallback, e, SocketOperation.ReceiveFrom);
2135 e.socket_async_result.Buffer = e.Buffer;
2136 e.socket_async_result.Offset = e.Offset;
2137 e.socket_async_result.Size = e.Count;
2138 e.socket_async_result.EndPoint = e.RemoteEndPoint;
2139 e.socket_async_result.SockFlags = e.SocketFlags;
2141 QueueIOSelectorJob (readQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveFromCallback, e.socket_async_result));
2146 static AsyncCallback ReceiveFromAsyncCallback = new AsyncCallback (ares => {
2147 SocketAsyncEventArgs e = (SocketAsyncEventArgs) ((SocketAsyncResult) ares).AsyncState;
2149 if (Interlocked.Exchange (ref e.in_progress, 0) != 1)
2150 throw new InvalidOperationException ("No operation in progress");
2153 e.BytesTransferred = e.current_socket.EndReceiveFrom (ares, ref e.remote_ep);
2154 } catch (SocketException ex) {
2155 e.SocketError = ex.SocketErrorCode;
2156 } catch (ObjectDisposedException) {
2157 e.SocketError = SocketError.OperationAborted;
2163 public IAsyncResult BeginReceiveFrom (byte[] buffer, int offset, int size, SocketFlags socket_flags, ref EndPoint remote_end, AsyncCallback callback, object state)
2165 ThrowIfDisposedAndClosed ();
2166 ThrowIfBufferNull (buffer);
2167 ThrowIfBufferOutOfRange (buffer, offset, size);
2169 if (remote_end == null)
2170 throw new ArgumentNullException ("remote_end");
2172 SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.ReceiveFrom) {
2176 SockFlags = socket_flags,
2177 EndPoint = remote_end,
2180 QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveFromCallback, sockares));
2185 static IOAsyncCallback BeginReceiveFromCallback = new IOAsyncCallback (ares => {
2186 SocketAsyncResult sockares = (SocketAsyncResult) ares;
2191 total = sockares.socket.ReceiveFrom_nochecks_exc (sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, ref sockares.EndPoint, true, out error);
2192 } catch (Exception e) {
2193 sockares.Complete (e);
2197 sockares.Complete (total);
2200 public int EndReceiveFrom(IAsyncResult result, ref EndPoint end_point)
2202 ThrowIfDisposedAndClosed ();
2204 if (end_point == null)
2205 throw new ArgumentNullException ("remote_end");
2207 SocketAsyncResult sockares = ValidateEndIAsyncResult (result, "EndReceiveFrom", "result");
2209 if (!sockares.IsCompleted)
2210 sockares.AsyncWaitHandle.WaitOne();
2212 sockares.CheckIfThrowDelayedException();
2214 end_point = sockares.EndPoint;
2216 return sockares.Total;
2219 internal int ReceiveFrom_nochecks_exc (byte [] buf, int offset, int size, SocketFlags flags, ref EndPoint remote_end, bool throwOnError, out int error)
2221 SocketAddress sockaddr = remote_end.Serialize();
2223 int cnt = ReceiveFrom_internal (safe_handle, buf, offset, size, flags, ref sockaddr, out error);
2225 SocketError err = (SocketError) error;
2227 if (err != SocketError.WouldBlock && err != SocketError.InProgress) {
2228 is_connected = false;
2229 } else if (err == SocketError.WouldBlock && is_blocking) { // This might happen when ReceiveTimeout is set
2231 throw new SocketException ((int) SocketError.TimedOut, TIMEOUT_EXCEPTION_MSG);
2232 error = (int) SocketError.TimedOut;
2237 throw new SocketException (error);
2242 is_connected = true;
2245 /* If sockaddr is null then we're a connection oriented protocol and should ignore the
2246 * remote_end parameter (see MSDN documentation for Socket.ReceiveFrom(...) ) */
2247 if (sockaddr != null) {
2248 /* Stupidly, EndPoint.Create() is an instance method */
2249 remote_end = remote_end.Create (sockaddr);
2252 seed_endpoint = remote_end;
2257 static int ReceiveFrom_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, ref SocketAddress sockaddr, out int error)
2260 safeHandle.RegisterForBlockingSyscall ();
2261 return ReceiveFrom_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, ref sockaddr, out error);
2263 safeHandle.UnRegisterForBlockingSyscall ();
2267 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2268 extern static int ReceiveFrom_internal(IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags, ref SocketAddress sockaddr, out int error);
2272 #region ReceiveMessageFrom
2274 [MonoTODO ("Not implemented")]
2275 public int ReceiveMessageFrom (byte[] buffer, int offset, int size, ref SocketFlags socketFlags, ref EndPoint remoteEP, out IPPacketInformation ipPacketInformation)
2277 ThrowIfDisposedAndClosed ();
2278 ThrowIfBufferNull (buffer);
2279 ThrowIfBufferOutOfRange (buffer, offset, size);
2281 if (remoteEP == null)
2282 throw new ArgumentNullException ("remoteEP");
2284 // FIXME: figure out how we get hold of the IPPacketInformation
2285 throw new NotImplementedException ();
2288 [MonoTODO ("Not implemented")]
2289 public bool ReceiveMessageFromAsync (SocketAsyncEventArgs e)
2291 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
2293 ThrowIfDisposedAndClosed ();
2295 throw new NotImplementedException ();
2299 public IAsyncResult BeginReceiveMessageFrom (byte[] buffer, int offset, int size, SocketFlags socketFlags, ref EndPoint remoteEP, AsyncCallback callback, object state)
2301 ThrowIfDisposedAndClosed ();
2302 ThrowIfBufferNull (buffer);
2303 ThrowIfBufferOutOfRange (buffer, offset, size);
2305 if (remoteEP == null)
2306 throw new ArgumentNullException ("remoteEP");
2308 throw new NotImplementedException ();
2312 public int EndReceiveMessageFrom (IAsyncResult asyncResult, ref SocketFlags socketFlags, ref EndPoint endPoint, out IPPacketInformation ipPacketInformation)
2314 ThrowIfDisposedAndClosed ();
2316 if (endPoint == null)
2317 throw new ArgumentNullException ("endPoint");
2319 SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndReceiveMessageFrom", "asyncResult");
2321 throw new NotImplementedException ();
2328 public int Send (byte [] buffer)
2330 ThrowIfDisposedAndClosed ();
2331 ThrowIfBufferNull (buffer);
2332 ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
2335 int ret = Send_nochecks (buffer, 0, buffer.Length, SocketFlags.None, out error);
2337 if (error != SocketError.Success)
2338 throw new SocketException ((int) error);
2343 public int Send (byte [] buffer, SocketFlags flags)
2345 ThrowIfDisposedAndClosed ();
2346 ThrowIfBufferNull (buffer);
2347 ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
2350 int ret = Send_nochecks (buffer, 0, buffer.Length, flags, out error);
2352 if (error != SocketError.Success)
2353 throw new SocketException ((int) error);
2358 public int Send (byte [] buffer, int size, SocketFlags flags)
2360 ThrowIfDisposedAndClosed ();
2361 ThrowIfBufferNull (buffer);
2362 ThrowIfBufferOutOfRange (buffer, 0, size);
2365 int ret = Send_nochecks (buffer, 0, size, flags, out error);
2367 if (error != SocketError.Success)
2368 throw new SocketException ((int) error);
2373 public int Send (byte [] buffer, int offset, int size, SocketFlags flags)
2375 ThrowIfDisposedAndClosed ();
2376 ThrowIfBufferNull (buffer);
2377 ThrowIfBufferOutOfRange (buffer, offset, size);
2380 int ret = Send_nochecks (buffer, offset, size, flags, out error);
2382 if (error != SocketError.Success)
2383 throw new SocketException ((int) error);
2388 public int Send (byte [] buffer, int offset, int size, SocketFlags flags, out SocketError error)
2390 ThrowIfDisposedAndClosed ();
2391 ThrowIfBufferNull (buffer);
2392 ThrowIfBufferOutOfRange (buffer, offset, size);
2394 return Send_nochecks (buffer, offset, size, flags, out error);
2398 int Send (IList<ArraySegment<byte>> buffers)
2401 int ret = Send (buffers, SocketFlags.None, out error);
2403 if (error != SocketError.Success)
2404 throw new SocketException ((int) error);
2410 int Send (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags)
2413 int ret = Send (buffers, socketFlags, out error);
2415 if (error != SocketError.Success)
2416 throw new SocketException ((int) error);
2421 [CLSCompliant (false)]
2422 public int Send (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode)
2424 ThrowIfDisposedAndClosed ();
2426 if (buffers == null)
2427 throw new ArgumentNullException ("buffers");
2428 if (buffers.Count == 0)
2429 throw new ArgumentException ("Buffer is empty", "buffers");
2431 int numsegments = buffers.Count;
2435 WSABUF[] bufarray = new WSABUF[numsegments];
2436 GCHandle[] gch = new GCHandle[numsegments];
2438 for(int i = 0; i < numsegments; i++) {
2439 ArraySegment<byte> segment = buffers[i];
2441 if (segment.Offset < 0 || segment.Count < 0 || segment.Count > segment.Array.Length - segment.Offset)
2442 throw new ArgumentOutOfRangeException ("segment");
2444 gch[i] = GCHandle.Alloc (segment.Array, GCHandleType.Pinned);
2445 bufarray[i].len = segment.Count;
2446 bufarray[i].buf = Marshal.UnsafeAddrOfPinnedArrayElement (segment.Array, segment.Offset);
2450 ret = Send_internal (safe_handle, bufarray, socketFlags, out nativeError);
2452 for(int i = 0; i < numsegments; i++) {
2453 if (gch[i].IsAllocated) {
2459 errorCode = (SocketError)nativeError;
2464 int Send_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
2467 error = SocketError.Success;
2472 int ret = Send_internal (safe_handle, buf, offset, size, flags, out nativeError);
2474 error = (SocketError)nativeError;
2476 if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress) {
2477 is_connected = false;
2480 is_connected = true;
2486 public bool SendAsync (SocketAsyncEventArgs e)
2488 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
2490 ThrowIfDisposedAndClosed ();
2492 if (e.Buffer == null && e.BufferList == null)
2493 throw new NullReferenceException ("Either e.Buffer or e.BufferList must be valid buffers.");
2495 if (e.Buffer == null) {
2496 InitSocketAsyncEventArgs (e, SendAsyncCallback, e, SocketOperation.SendGeneric);
2498 e.socket_async_result.Buffers = e.BufferList;
2500 QueueIOSelectorJob (writeQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Write, BeginSendGenericCallback, e.socket_async_result));
2502 InitSocketAsyncEventArgs (e, SendAsyncCallback, e, SocketOperation.Send);
2504 e.socket_async_result.Buffer = e.Buffer;
2505 e.socket_async_result.Offset = e.Offset;
2506 e.socket_async_result.Size = e.Count;
2508 QueueIOSelectorJob (writeQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendCallback ((SocketAsyncResult) s, 0), e.socket_async_result));
2514 static AsyncCallback SendAsyncCallback = new AsyncCallback (ares => {
2515 SocketAsyncEventArgs e = (SocketAsyncEventArgs) ((SocketAsyncResult) ares).AsyncState;
2517 if (Interlocked.Exchange (ref e.in_progress, 0) != 1)
2518 throw new InvalidOperationException ("No operation in progress");
2521 e.BytesTransferred = e.current_socket.EndSend (ares);
2522 } catch (SocketException se){
2523 e.SocketError = se.SocketErrorCode;
2524 } catch (ObjectDisposedException) {
2525 e.SocketError = SocketError.OperationAborted;
2531 public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
2533 if (!is_connected) {
2534 errorCode = SocketError.NotConnected;
2535 throw new SocketException ((int) errorCode);
2538 errorCode = SocketError.Success;
2539 return BeginSend (buffer, offset, size, socketFlags, callback, state);
2542 public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socket_flags, AsyncCallback callback, object state)
2544 ThrowIfDisposedAndClosed ();
2545 ThrowIfBufferNull (buffer);
2546 ThrowIfBufferOutOfRange (buffer, offset, size);
2549 throw new SocketException ((int)SocketError.NotConnected);
2551 SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.Send) {
2555 SockFlags = socket_flags,
2558 QueueIOSelectorJob (writeQ, sockares.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendCallback ((SocketAsyncResult) s, 0), sockares));
2563 static void BeginSendCallback (SocketAsyncResult sockares, int sent_so_far)
2568 total = Socket.Send_internal (sockares.socket.safe_handle, sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, out sockares.error);
2569 } catch (Exception e) {
2570 sockares.Complete (e);
2574 if (sockares.error == 0) {
2575 sent_so_far += total;
2576 sockares.Offset += total;
2577 sockares.Size -= total;
2579 if (sockares.socket.is_disposed) {
2580 sockares.Complete (total);
2584 if (sockares.Size > 0) {
2585 IOSelector.Add (sockares.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendCallback ((SocketAsyncResult) s, sent_so_far), sockares));
2586 return; // Have to finish writing everything. See bug #74475.
2589 sockares.Total = sent_so_far;
2592 sockares.Complete (total);
2595 public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, AsyncCallback callback, object state)
2597 ThrowIfDisposedAndClosed ();
2599 if (buffers == null)
2600 throw new ArgumentNullException ("buffers");
2602 throw new SocketException ((int)SocketError.NotConnected);
2604 SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.SendGeneric) {
2606 SockFlags = socketFlags,
2609 QueueIOSelectorJob (writeQ, sockares.Handle, new IOSelectorJob (IOOperation.Write, BeginSendGenericCallback, sockares));
2614 [CLSCompliant (false)]
2615 public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
2617 if (!is_connected) {
2618 errorCode = SocketError.NotConnected;
2619 throw new SocketException ((int)errorCode);
2622 errorCode = SocketError.Success;
2623 return BeginSend (buffers, socketFlags, callback, state);
2626 static IOAsyncCallback BeginSendGenericCallback = new IOAsyncCallback (ares => {
2627 SocketAsyncResult sockares = (SocketAsyncResult) ares;
2631 total = sockares.socket.Send (sockares.Buffers, sockares.SockFlags);
2632 } catch (Exception e) {
2633 sockares.Complete (e);
2637 sockares.Complete (total);
2640 public int EndSend (IAsyncResult result)
2643 int bytesSent = EndSend (result, out error);
2645 if (error != SocketError.Success) {
2646 if (error != SocketError.WouldBlock && error != SocketError.InProgress)
2647 is_connected = false;
2648 throw new SocketException ((int)error);
2654 public int EndSend (IAsyncResult asyncResult, out SocketError errorCode)
2656 ThrowIfDisposedAndClosed ();
2658 SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndSend", "asyncResult");
2660 if (!sockares.IsCompleted)
2661 sockares.AsyncWaitHandle.WaitOne ();
2663 /* If no socket error occurred, call CheckIfThrowDelayedException in
2664 * case there are other kinds of exceptions that should be thrown.*/
2665 if ((errorCode = sockares.ErrorCode) == SocketError.Success)
2666 sockares.CheckIfThrowDelayedException ();
2668 return sockares.Total;
2671 static int Send_internal (SafeSocketHandle safeHandle, WSABUF[] bufarray, SocketFlags flags, out int error)
2673 bool release = false;
2675 safeHandle.DangerousAddRef (ref release);
2676 return Send_internal (safeHandle.DangerousGetHandle (), bufarray, flags, out error);
2679 safeHandle.DangerousRelease ();
2683 [MethodImplAttribute (MethodImplOptions.InternalCall)]
2684 extern static int Send_internal (IntPtr sock, WSABUF[] bufarray, SocketFlags flags, out int error);
2686 static int Send_internal (SafeSocketHandle safeHandle, byte[] buf, int offset, int count, SocketFlags flags, out int error)
2689 safeHandle.RegisterForBlockingSyscall ();
2690 return Send_internal (safeHandle.DangerousGetHandle (), buf, offset, count, flags, out error);
2692 safeHandle.UnRegisterForBlockingSyscall ();
2696 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2697 extern static int Send_internal(IntPtr sock, byte[] buf, int offset, int count, SocketFlags flags, out int error);
2703 public int SendTo (byte [] buffer, EndPoint remote_end)
2705 ThrowIfDisposedAndClosed ();
2706 ThrowIfBufferNull (buffer);
2708 return SendTo (buffer, 0, buffer.Length, SocketFlags.None, remote_end);
2711 public int SendTo (byte [] buffer, SocketFlags flags, EndPoint remote_end)
2713 ThrowIfDisposedAndClosed ();
2714 ThrowIfBufferNull (buffer);
2716 return SendTo (buffer, 0, buffer.Length, flags, remote_end);
2719 public int SendTo (byte [] buffer, int size, SocketFlags flags, EndPoint remote_end)
2721 return SendTo (buffer, 0, size, flags, remote_end);
2724 public int SendTo (byte [] buffer, int offset, int size, SocketFlags flags, EndPoint remote_end)
2726 ThrowIfDisposedAndClosed ();
2727 ThrowIfBufferNull (buffer);
2728 ThrowIfBufferOutOfRange (buffer, offset, size);
2730 if (remote_end == null)
2731 throw new ArgumentNullException("remote_end");
2733 return SendTo_nochecks (buffer, offset, size, flags, remote_end);
2736 public bool SendToAsync (SocketAsyncEventArgs e)
2738 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
2740 ThrowIfDisposedAndClosed ();
2742 if (e.BufferList != null)
2743 throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
2744 if (e.RemoteEndPoint == null)
2745 throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
2747 InitSocketAsyncEventArgs (e, SendToAsyncCallback, e, SocketOperation.SendTo);
2749 e.socket_async_result.Buffer = e.Buffer;
2750 e.socket_async_result.Offset = e.Offset;
2751 e.socket_async_result.Size = e.Count;
2752 e.socket_async_result.SockFlags = e.SocketFlags;
2753 e.socket_async_result.EndPoint = e.RemoteEndPoint;
2755 QueueIOSelectorJob (writeQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendToCallback ((SocketAsyncResult) s, 0), e.socket_async_result));
2760 static AsyncCallback SendToAsyncCallback = new AsyncCallback (ares => {
2761 SocketAsyncEventArgs e = (SocketAsyncEventArgs) ((SocketAsyncResult) ares).AsyncState;
2763 if (Interlocked.Exchange (ref e.in_progress, 0) != 1)
2764 throw new InvalidOperationException ("No operation in progress");
2767 e.BytesTransferred = e.current_socket.EndSendTo (ares);
2768 } catch (SocketException ex) {
2769 e.SocketError = ex.SocketErrorCode;
2770 } catch (ObjectDisposedException) {
2771 e.SocketError = SocketError.OperationAborted;
2777 public IAsyncResult BeginSendTo(byte[] buffer, int offset, int size, SocketFlags socket_flags, EndPoint remote_end, AsyncCallback callback, object state)
2779 ThrowIfDisposedAndClosed ();
2780 ThrowIfBufferNull (buffer);
2781 ThrowIfBufferOutOfRange (buffer, offset, size);
2783 SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.SendTo) {
2787 SockFlags = socket_flags,
2788 EndPoint = remote_end,
2791 QueueIOSelectorJob (writeQ, sockares.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendToCallback ((SocketAsyncResult) s, 0), sockares));
2796 static void BeginSendToCallback (SocketAsyncResult sockares, int sent_so_far)
2800 total = sockares.socket.SendTo_nochecks (sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, sockares.EndPoint);
2802 if (sockares.error == 0) {
2803 sent_so_far += total;
2804 sockares.Offset += total;
2805 sockares.Size -= total;
2808 if (sockares.Size > 0) {
2809 IOSelector.Add (sockares.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendToCallback ((SocketAsyncResult) s, sent_so_far), sockares));
2810 return; // Have to finish writing everything. See bug #74475.
2813 sockares.Total = sent_so_far;
2814 } catch (Exception e) {
2815 sockares.Complete (e);
2819 sockares.Complete ();
2822 public int EndSendTo (IAsyncResult result)
2824 ThrowIfDisposedAndClosed ();
2826 SocketAsyncResult sockares = ValidateEndIAsyncResult (result, "EndSendTo", "result");
2828 if (!sockares.IsCompleted)
2829 sockares.AsyncWaitHandle.WaitOne();
2831 sockares.CheckIfThrowDelayedException();
2833 return sockares.Total;
2836 int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags, EndPoint remote_end)
2839 int ret = SendTo_internal (safe_handle, buffer, offset, size, flags, remote_end.Serialize (), out error);
2841 SocketError err = (SocketError) error;
2843 if (err != SocketError.WouldBlock && err != SocketError.InProgress)
2844 is_connected = false;
2845 throw new SocketException (error);
2848 is_connected = true;
2850 seed_endpoint = remote_end;
2855 static int SendTo_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, SocketAddress sa, out int error)
2858 safeHandle.RegisterForBlockingSyscall ();
2859 return SendTo_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, sa, out error);
2861 safeHandle.UnRegisterForBlockingSyscall ();
2865 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2866 extern static int SendTo_internal (IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags, SocketAddress sa, out int error);
2872 public void SendFile (string fileName)
2874 ThrowIfDisposedAndClosed ();
2877 throw new NotSupportedException ();
2879 throw new InvalidOperationException ();
2881 SendFile (fileName, null, null, 0);
2884 public void SendFile (string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags)
2886 ThrowIfDisposedAndClosed ();
2889 throw new NotSupportedException ();
2891 throw new InvalidOperationException ();
2893 if (!SendFile_internal (safe_handle, fileName, preBuffer, postBuffer, flags)) {
2894 SocketException exc = new SocketException ();
2895 if (exc.ErrorCode == 2 || exc.ErrorCode == 3)
2896 throw new FileNotFoundException ();
2901 public IAsyncResult BeginSendFile (string fileName, AsyncCallback callback, object state)
2903 ThrowIfDisposedAndClosed ();
2906 throw new NotSupportedException ();
2907 if (!File.Exists (fileName))
2908 throw new FileNotFoundException ();
2910 return BeginSendFile (fileName, null, null, 0, callback, state);
2913 public IAsyncResult BeginSendFile (string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags, AsyncCallback callback, object state)
2915 ThrowIfDisposedAndClosed ();
2918 throw new NotSupportedException ();
2919 if (!File.Exists (fileName))
2920 throw new FileNotFoundException ();
2922 SendFileHandler handler = new SendFileHandler (SendFile);
2924 return new SendFileAsyncResult (handler, handler.BeginInvoke (fileName, preBuffer, postBuffer, flags, ar => callback (new SendFileAsyncResult (handler, ar)), state));
2927 public void EndSendFile (IAsyncResult asyncResult)
2929 ThrowIfDisposedAndClosed ();
2931 if (asyncResult == null)
2932 throw new ArgumentNullException ("asyncResult");
2934 SendFileAsyncResult ares = asyncResult as SendFileAsyncResult;
2936 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
2938 ares.Delegate.EndInvoke (ares.Original);
2941 static bool SendFile_internal (SafeSocketHandle safeHandle, string filename, byte [] pre_buffer, byte [] post_buffer, TransmitFileOptions flags)
2944 safeHandle.RegisterForBlockingSyscall ();
2945 return SendFile_internal (safeHandle.DangerousGetHandle (), filename, pre_buffer, post_buffer, flags);
2947 safeHandle.UnRegisterForBlockingSyscall ();
2951 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2952 extern static bool SendFile_internal (IntPtr sock, string filename, byte [] pre_buffer, byte [] post_buffer, TransmitFileOptions flags);
2954 delegate void SendFileHandler (string fileName, byte [] preBuffer, byte [] postBuffer, TransmitFileOptions flags);
2956 sealed class SendFileAsyncResult : IAsyncResult {
2960 public SendFileAsyncResult (SendFileHandler d, IAsyncResult ares)
2966 public object AsyncState {
2967 get { return ares.AsyncState; }
2970 public WaitHandle AsyncWaitHandle {
2971 get { return ares.AsyncWaitHandle; }
2974 public bool CompletedSynchronously {
2975 get { return ares.CompletedSynchronously; }
2978 public bool IsCompleted {
2979 get { return ares.IsCompleted; }
2982 public SendFileHandler Delegate {
2986 public IAsyncResult Original {
2987 get { return ares; }
2995 [MonoTODO ("Not implemented")]
2996 public bool SendPacketsAsync (SocketAsyncEventArgs e)
2998 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
3000 ThrowIfDisposedAndClosed ();
3002 throw new NotImplementedException ();
3007 #region DuplicateAndClose
3010 [MonoLimitation ("We do not support passing sockets across processes, we merely allow this API to pass the socket across AppDomains")]
3011 public SocketInformation DuplicateAndClose (int targetProcessId)
3013 var si = new SocketInformation ();
3015 (is_listening ? SocketInformationOptions.Listening : 0) |
3016 (is_connected ? SocketInformationOptions.Connected : 0) |
3017 (is_blocking ? 0 : SocketInformationOptions.NonBlocking) |
3018 (use_overlapped_io ? SocketInformationOptions.UseOnlyOverlappedIO : 0);
3020 si.ProtocolInformation = Mono.DataConverter.Pack ("iiiil", (int)address_family, (int)socket_type, (int)protocol_type, is_bound ? 1 : 0, (long)Handle);
3029 #region GetSocketOption
3031 public void GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, byte [] optionValue)
3033 ThrowIfDisposedAndClosed ();
3035 if (optionValue == null)
3036 throw new SocketException ((int) SocketError.Fault, "Error trying to dereference an invalid pointer");
3039 GetSocketOption_arr_internal (safe_handle, optionLevel, optionName, ref optionValue, out error);
3042 throw new SocketException (error);
3045 public byte [] GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int length)
3047 ThrowIfDisposedAndClosed ();
3050 byte[] byte_val = new byte [length];
3051 GetSocketOption_arr_internal (safe_handle, optionLevel, optionName, ref byte_val, out error);
3054 throw new SocketException (error);
3059 public object GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName)
3061 ThrowIfDisposedAndClosed ();
3065 GetSocketOption_obj_internal (safe_handle, optionLevel, optionName, out obj_val, out error);
3068 throw new SocketException (error);
3070 if (optionName == SocketOptionName.Linger)
3071 return (LingerOption) obj_val;
3072 else if (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)
3073 return (MulticastOption) obj_val;
3074 else if (obj_val is int)
3075 return (int) obj_val;
3080 static void GetSocketOption_arr_internal (SafeSocketHandle safeHandle, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val, out int error)
3082 bool release = false;
3084 safeHandle.DangerousAddRef (ref release);
3085 GetSocketOption_arr_internal (safeHandle.DangerousGetHandle (), level, name, ref byte_val, out error);
3088 safeHandle.DangerousRelease ();
3092 [MethodImplAttribute(MethodImplOptions.InternalCall)]
3093 extern static void GetSocketOption_arr_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val, out int error);
3095 static void GetSocketOption_obj_internal (SafeSocketHandle safeHandle, SocketOptionLevel level, SocketOptionName name, out object obj_val, out int error)
3097 bool release = false;
3099 safeHandle.DangerousAddRef (ref release);
3100 GetSocketOption_obj_internal (safeHandle.DangerousGetHandle (), level, name, out obj_val, out error);
3103 safeHandle.DangerousRelease ();
3107 [MethodImplAttribute(MethodImplOptions.InternalCall)]
3108 extern static void GetSocketOption_obj_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, out object obj_val, out int error);
3112 #region SetSocketOption
3114 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, byte [] optionValue)
3116 ThrowIfDisposedAndClosed ();
3118 // I'd throw an ArgumentNullException, but this is what MS does.
3119 if (optionValue == null)
3120 throw new SocketException ((int) SocketError.Fault, "Error trying to dereference an invalid pointer");
3123 SetSocketOption_internal (safe_handle, optionLevel, optionName, null, optionValue, 0, out error);
3126 if (error == (int) SocketError.InvalidArgument)
3127 throw new ArgumentException ();
3128 throw new SocketException (error);
3132 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, object optionValue)
3134 ThrowIfDisposedAndClosed ();
3136 // NOTE: if a null is passed, the byte[] overload is used instead...
3137 if (optionValue == null)
3138 throw new ArgumentNullException("optionValue");
3142 if (optionLevel == SocketOptionLevel.Socket && optionName == SocketOptionName.Linger) {
3143 LingerOption linger = optionValue as LingerOption;
3145 throw new ArgumentException ("A 'LingerOption' value must be specified.", "optionValue");
3146 SetSocketOption_internal (safe_handle, optionLevel, optionName, linger, null, 0, out error);
3147 } else if (optionLevel == SocketOptionLevel.IP && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
3148 MulticastOption multicast = optionValue as MulticastOption;
3149 if (multicast == null)
3150 throw new ArgumentException ("A 'MulticastOption' value must be specified.", "optionValue");
3151 SetSocketOption_internal (safe_handle, optionLevel, optionName, multicast, null, 0, out error);
3152 } else if (optionLevel == SocketOptionLevel.IPv6 && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
3153 IPv6MulticastOption multicast = optionValue as IPv6MulticastOption;
3154 if (multicast == null)
3155 throw new ArgumentException ("A 'IPv6MulticastOption' value must be specified.", "optionValue");
3156 SetSocketOption_internal (safe_handle, optionLevel, optionName, multicast, null, 0, out error);
3158 throw new ArgumentException ("Invalid value specified.", "optionValue");
3162 if (error == (int) SocketError.InvalidArgument)
3163 throw new ArgumentException ();
3164 throw new SocketException (error);
3168 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, bool optionValue)
3170 int int_val = optionValue ? 1 : 0;
3172 SetSocketOption (optionLevel, optionName, int_val);
3175 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int optionValue)
3177 ThrowIfDisposedAndClosed ();
3179 if (optionName == SocketOptionName.ReuseAddress && optionValue != 0 && !SupportsPortReuse ())
3180 throw new SocketException ((int) SocketError.OperationNotSupported, "Operating system sockets do not support ReuseAddress.\nIf your socket is not intended to bind to the same address and port multiple times remove this option, otherwise you should ignore this exception inside a try catch and check that ReuseAddress is true before binding to the same address and port multiple times.");
3183 SetSocketOption_internal (safe_handle, optionLevel, optionName, null, null, optionValue, out error);
3186 if (error == (int) SocketError.InvalidArgument)
3187 throw new ArgumentException ();
3188 throw new SocketException (error);
3192 static void SetSocketOption_internal (SafeSocketHandle safeHandle, SocketOptionLevel level, SocketOptionName name, object obj_val, byte [] byte_val, int int_val, out int error)
3194 bool release = false;
3196 safeHandle.DangerousAddRef (ref release);
3197 SetSocketOption_internal (safeHandle.DangerousGetHandle (), level, name, obj_val, byte_val, int_val, out error);
3200 safeHandle.DangerousRelease ();
3204 [MethodImplAttribute(MethodImplOptions.InternalCall)]
3205 extern static void SetSocketOption_internal (IntPtr socket, SocketOptionLevel level, SocketOptionName name, object obj_val, byte [] byte_val, int int_val, out int error);
3211 public int IOControl (int ioctl_code, byte [] in_value, byte [] out_value)
3214 throw new ObjectDisposedException (GetType ().ToString ());
3217 int result = IOControl_internal (safe_handle, ioctl_code, in_value, out_value, out error);
3220 throw new SocketException (error);
3222 throw new InvalidOperationException ("Must use Blocking property instead.");
3227 public int IOControl (IOControlCode ioControlCode, byte[] optionInValue, byte[] optionOutValue)
3229 return IOControl ((int) ioControlCode, optionInValue, optionOutValue);
3232 static int IOControl_internal (SafeSocketHandle safeHandle, int ioctl_code, byte [] input, byte [] output, out int error)
3234 bool release = false;
3236 safeHandle.DangerousAddRef (ref release);
3237 return IOControl_internal (safeHandle.DangerousGetHandle (), ioctl_code, input, output, out error);
3240 safeHandle.DangerousRelease ();
3244 /* See Socket.IOControl, WSAIoctl documentation in MSDN. The common options between UNIX
3245 * and Winsock are FIONREAD, FIONBIO and SIOCATMARK. Anything else will depend on the system
3246 * except SIO_KEEPALIVE_VALS which is properly handled on both windows and linux. */
3247 [MethodImplAttribute(MethodImplOptions.InternalCall)]
3248 extern static int IOControl_internal (IntPtr sock, int ioctl_code, byte [] input, byte [] output, out int error);
3254 public void Close ()
3260 public void Close (int timeout)
3262 linger_timeout = timeout;
3266 [MethodImplAttribute(MethodImplOptions.InternalCall)]
3267 internal extern static void Close_internal (IntPtr socket, out int error);
3273 public void Shutdown (SocketShutdown how)
3275 ThrowIfDisposedAndClosed ();
3278 throw new SocketException (10057); // Not connected
3281 Shutdown_internal (safe_handle, how, out error);
3284 throw new SocketException (error);
3287 static void Shutdown_internal (SafeSocketHandle safeHandle, SocketShutdown how, out int error)
3289 bool release = false;
3291 safeHandle.DangerousAddRef (ref release);
3292 Shutdown_internal (safeHandle.DangerousGetHandle (), how, out error);
3295 safeHandle.DangerousRelease ();
3299 [MethodImplAttribute (MethodImplOptions.InternalCall)]
3300 internal extern static void Shutdown_internal (IntPtr socket, SocketShutdown how, out int error);
3306 protected virtual void Dispose (bool disposing)
3312 bool was_connected = is_connected;
3313 is_connected = false;
3315 if (safe_handle != null) {
3322 safe_handle.Dispose ();
3326 public void Dispose ()
3329 GC.SuppressFinalize (this);
3332 void Linger (IntPtr handle)
3334 if (!is_connected || linger_timeout <= 0)
3337 /* We don't want to receive any more data */
3339 Shutdown_internal (handle, SocketShutdown.Receive, out error);
3344 int seconds = linger_timeout / 1000;
3345 int ms = linger_timeout % 1000;
3347 /* If the other end closes, this will return 'true' with 'Available' == 0 */
3348 Poll_internal (handle, SelectMode.SelectRead, ms * 1000, out error);
3354 LingerOption linger = new LingerOption (true, seconds);
3355 SetSocketOption_internal (handle, SocketOptionLevel.Socket, SocketOptionName.Linger, linger, null, 0, out error);
3356 /* Not needed, we're closing upon return */
3364 void ThrowIfDisposedAndClosed (Socket socket)
3366 if (socket.is_disposed && socket.is_closed)
3367 throw new ObjectDisposedException (socket.GetType ().ToString ());
3370 void ThrowIfDisposedAndClosed ()
3372 if (is_disposed && is_closed)
3373 throw new ObjectDisposedException (GetType ().ToString ());
3376 void ThrowIfBufferNull (byte[] buffer)
3379 throw new ArgumentNullException ("buffer");
3382 void ThrowIfBufferOutOfRange (byte[] buffer, int offset, int size)
3385 throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
3386 if (offset > buffer.Length)
3387 throw new ArgumentOutOfRangeException ("offset", "offset must be <= buffer.Length");
3389 throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
3390 if (size > buffer.Length - offset)
3391 throw new ArgumentOutOfRangeException ("size", "size must be <= buffer.Length - offset");
3396 #if !NET_2_1 || MOBILE
3397 if (protocol_type == ProtocolType.Udp)
3398 throw new SocketException ((int)SocketError.ProtocolOption);
3402 SocketAsyncResult ValidateEndIAsyncResult (IAsyncResult ares, string methodName, string argName)
3405 throw new ArgumentNullException (argName);
3407 SocketAsyncResult sockares = ares as SocketAsyncResult;
3408 if (sockares == null)
3409 throw new ArgumentException ("Invalid IAsyncResult", argName);
3410 if (Interlocked.CompareExchange (ref sockares.EndCalled, 1, 0) == 1)
3411 throw new InvalidOperationException (methodName + " can only be called once per asynchronous operation");
3416 void QueueIOSelectorJob (Queue<KeyValuePair<IntPtr, IOSelectorJob>> queue, IntPtr handle, IOSelectorJob job)
3420 queue.Enqueue (new KeyValuePair<IntPtr, IOSelectorJob> (handle, job));
3421 count = queue.Count;
3425 IOSelector.Add (handle, job);
3428 void InitSocketAsyncEventArgs (SocketAsyncEventArgs e, AsyncCallback callback, object state, SocketOperation operation)
3430 e.socket_async_result.Init (this, callback, state, operation);
3431 if (e.AcceptSocket != null) {
3432 e.socket_async_result.AcceptSocket = e.AcceptSocket;
3434 e.current_socket = this;
3435 e.SetLastOperation (SocketOperationToSocketAsyncOperation (operation));
3436 e.SocketError = SocketError.Success;
3437 e.BytesTransferred = 0;
3440 SocketAsyncOperation SocketOperationToSocketAsyncOperation (SocketOperation op)
3443 case SocketOperation.Connect:
3444 return SocketAsyncOperation.Connect;
3445 case SocketOperation.Accept:
3446 return SocketAsyncOperation.Accept;
3447 case SocketOperation.Disconnect:
3448 return SocketAsyncOperation.Disconnect;
3449 case SocketOperation.Receive:
3450 case SocketOperation.ReceiveGeneric:
3451 return SocketAsyncOperation.Receive;
3452 case SocketOperation.ReceiveFrom:
3453 return SocketAsyncOperation.ReceiveFrom;
3454 case SocketOperation.Send:
3455 case SocketOperation.SendGeneric:
3456 return SocketAsyncOperation.Send;
3457 case SocketOperation.SendTo:
3458 return SocketAsyncOperation.SendTo;
3460 throw new NotImplementedException (String.Format ("Operation {0} is not implemented", op));
3464 IPEndPoint RemapIPEndPoint (IPEndPoint input) {
3465 // If socket is DualMode ensure we automatically handle mapping IPv4 addresses to IPv6.
3466 if (IsDualMode && input.AddressFamily == AddressFamily.InterNetwork)
3467 return new IPEndPoint (input.Address.MapToIPv6 (), input.Port);
3472 [StructLayout (LayoutKind.Sequential)]
3478 [MethodImplAttribute(MethodImplOptions.InternalCall)]
3479 internal static extern void cancel_blocking_socket_operation (Thread thread);
3481 [MethodImplAttribute(MethodImplOptions.InternalCall)]
3482 internal static extern bool SupportsPortReuse ();