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 /* the field "safe_handle" is looked up by name by the runtime */
74 SafeSocketHandle safe_handle;
76 AddressFamily address_family;
77 SocketType socket_type;
78 ProtocolType protocol_type;
81 * This EndPoint is used when creating new endpoints. Because
82 * there are many types of EndPoints possible,
83 * seed_endpoint.Create(addr) is used for creating new ones.
84 * As such, this value is set on Bind, SentTo, ReceiveFrom,
87 internal EndPoint seed_endpoint = null;
89 internal Queue<SocketAsyncWorker> readQ = new Queue<SocketAsyncWorker> (2);
90 internal Queue<SocketAsyncWorker> writeQ = new Queue<SocketAsyncWorker> (2);
92 internal bool is_blocking = true;
93 internal bool is_bound;
95 /* When true, the socket was connected at the time of the last IO operation */
96 internal bool is_connected;
98 internal bool is_disposed;
99 internal bool connect_in_progress;
105 if (ipv4_supported == -1) {
107 Socket tmp = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
116 if (ipv6_supported == -1) {
117 // We need to put a try/catch around ConfigurationManager methods as will always throw an exception
118 // when run in a mono embedded application. This occurs as embedded applications do not have a setup
119 // for application config. The exception is not thrown when called from a normal .NET application.
121 // We, then, need to guard calls to the ConfigurationManager. If the config is not found or throws an
122 // exception, will fall through to the existing Socket / API directly below in the code.
124 // Also note that catching ConfigurationErrorsException specifically would require library dependency
125 // System.Configuration, and wanted to avoid that.
127 #if CONFIGURATION_DEP
129 SettingsSection config;
130 config = (SettingsSection) System.Configuration.ConfigurationManager.GetSection ("system.net/settings");
132 ipv6_supported = config.Ipv6.Enabled ? -1 : 0;
138 NetConfig config = System.Configuration.ConfigurationSettings.GetConfig("system.net/settings") as NetConfig;
140 ipv6_supported = config.ipv6Enabled ? -1 : 0;
146 if (ipv6_supported != 0) {
148 Socket tmp = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
159 [MonoTODO ("Currently hardcoded to IPv4. Ideally, support v4/v6 dual-stack.")]
160 public Socket (SocketType socketType, ProtocolType protocolType)
161 : this (AddressFamily.InterNetwork, socketType, protocolType)
165 public Socket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)
167 #if NET_2_1 && !MOBILE
168 switch (addressFamily) {
169 case AddressFamily.InterNetwork: // ok
170 case AddressFamily.InterNetworkV6: // ok
171 case AddressFamily.Unknown: // SocketException will be thrown later (with right error #)
173 // case AddressFamily.Unspecified:
175 throw new ArgumentException ("addressFamily");
178 switch (socketType) {
179 case SocketType.Stream: // ok
180 case SocketType.Unknown: // SocketException will be thrown later (with right error #)
183 throw new ArgumentException ("socketType");
186 switch (protocolType) {
187 case ProtocolType.Tcp: // ok
188 case ProtocolType.Unspecified: // ok
189 case ProtocolType.Unknown: // SocketException will be thrown later (with right error #)
192 throw new ArgumentException ("protocolType");
195 this.address_family = addressFamily;
196 this.socket_type = socketType;
197 this.protocol_type = protocolType;
200 var handle = Socket_internal (addressFamily, socketType, protocolType, out error);
202 this.safe_handle = new SafeSocketHandle (handle, true);
205 throw new SocketException (error);
207 #if !NET_2_1 || MOBILE
213 public Socket (SocketInformation socketInformation)
215 this.is_listening = (socketInformation.Options & SocketInformationOptions.Listening) != 0;
216 this.is_connected = (socketInformation.Options & SocketInformationOptions.Connected) != 0;
217 this.is_blocking = (socketInformation.Options & SocketInformationOptions.NonBlocking) == 0;
218 this.use_overlapped_io = (socketInformation.Options & SocketInformationOptions.UseOnlyOverlappedIO) != 0;
220 var result = Mono.DataConverter.Unpack ("iiiil", socketInformation.ProtocolInformation, 0);
222 this.address_family = (AddressFamily) (int) result [0];
223 this.socket_type = (SocketType) (int) result [1];
224 this.protocol_type = (ProtocolType) (int) result [2];
225 this.is_bound = (ProtocolType) (int) result [3] != 0;
226 this.safe_handle = new SafeSocketHandle ((IntPtr) (long) result [4], true);
232 /* private constructor used by Accept, which already has a socket handle to use */
233 internal Socket(AddressFamily family, SocketType type, ProtocolType proto, SafeSocketHandle safe_handle)
235 this.address_family = family;
236 this.socket_type = type;
237 this.protocol_type = proto;
239 this.safe_handle = safe_handle;
240 this.is_connected = true;
248 void SocketDefaults ()
251 /* Need to test IPv6 further */
252 if (address_family == AddressFamily.InterNetwork
253 // || address_family == AddressFamily.InterNetworkV6
255 /* This is the default, but it probably has nasty side
256 * effects on Linux, as the socket option is kludged by
257 * turning on or off PMTU discovery... */
258 this.DontFragment = false;
261 /* Microsoft sets these to 8192, but we are going to keep them
262 * both to the OS defaults as these have a big performance impact.
263 * on WebClient performance. */
264 // this.ReceiveBufferSize = 8192;
265 // this.SendBufferSize = 8192;
266 } catch (SocketException) {
270 /* Creates a new system socket, returning the handle */
271 [MethodImplAttribute(MethodImplOptions.InternalCall)]
272 extern IntPtr Socket_internal (AddressFamily family, SocketType type, ProtocolType proto, out int error);
278 public static bool SupportsIPv4 {
279 get { return ipv4_supported == 1; }
282 [ObsoleteAttribute ("Use OSSupportsIPv6 instead")]
283 public static bool SupportsIPv6 {
284 get { return ipv6_supported == 1; }
288 public static bool OSSupportsIPv4 {
289 get { return ipv4_supported == 1; }
294 public static bool OSSupportsIPv6 {
295 get { return ipv6_supported == 1; }
298 public static bool OSSupportsIPv6 {
300 NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces ();
302 foreach (NetworkInterface adapter in nics) {
303 if (adapter.Supports (NetworkInterfaceComponent.IPv6))
312 public int Available {
314 ThrowIfDisposedAndClosed ();
317 ret = Available_internal (safe_handle, out error);
320 throw new SocketException (error);
326 static int Available_internal (SafeSocketHandle safeHandle, out int error)
328 bool release = false;
330 safeHandle.DangerousAddRef (ref release);
331 return Available_internal (safeHandle.DangerousGetHandle (), out error);
334 safeHandle.DangerousRelease ();
338 /* Returns the amount of data waiting to be read on socket */
339 [MethodImplAttribute(MethodImplOptions.InternalCall)]
340 extern static int Available_internal (IntPtr socket, out int error);
342 public bool DontFragment {
344 ThrowIfDisposedAndClosed ();
346 switch (address_family) {
347 case AddressFamily.InterNetwork:
348 return ((int) GetSocketOption (SocketOptionLevel.IP, SocketOptionName.DontFragment)) != 0;
349 case AddressFamily.InterNetworkV6:
350 return ((int) GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.DontFragment)) != 0;
352 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
356 ThrowIfDisposedAndClosed ();
358 switch (address_family) {
359 case AddressFamily.InterNetwork:
360 SetSocketOption (SocketOptionLevel.IP, SocketOptionName.DontFragment, value ? 1 : 0);
362 case AddressFamily.InterNetworkV6:
363 SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.DontFragment, value ? 1 : 0);
366 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
371 public bool EnableBroadcast {
373 ThrowIfDisposedAndClosed ();
375 if (protocol_type != ProtocolType.Udp)
376 throw new SocketException ((int) SocketError.ProtocolOption);
378 return ((int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Broadcast)) != 0;
381 ThrowIfDisposedAndClosed ();
383 if (protocol_type != ProtocolType.Udp)
384 throw new SocketException ((int) SocketError.ProtocolOption);
386 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Broadcast, value ? 1 : 0);
390 public bool ExclusiveAddressUse {
392 ThrowIfDisposedAndClosed ();
394 return ((int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse)) != 0;
397 ThrowIfDisposedAndClosed ();
400 throw new InvalidOperationException ("Bind has already been called for this socket");
402 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse, value ? 1 : 0);
406 public bool IsBound {
412 public LingerOption LingerState {
414 ThrowIfDisposedAndClosed ();
416 return (LingerOption) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Linger);
419 ThrowIfDisposedAndClosed ();
420 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Linger, value);
424 public bool MulticastLoopback {
426 ThrowIfDisposedAndClosed ();
428 /* Even though this option can be set for TCP sockets on Linux, throw
429 * this exception anyway to be compatible (the MSDN docs say
430 * "Setting this property on a Transmission Control Protocol (TCP)
431 * socket will have no effect." but the MS runtime throws the
433 if (protocol_type == ProtocolType.Tcp)
434 throw new SocketException ((int)SocketError.ProtocolOption);
436 switch (address_family) {
437 case AddressFamily.InterNetwork:
438 return ((int) GetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastLoopback)) != 0;
439 case AddressFamily.InterNetworkV6:
440 return ((int) GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback)) != 0;
442 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
446 ThrowIfDisposedAndClosed ();
448 /* Even though this option can be set for TCP sockets on Linux, throw
449 * this exception anyway to be compatible (the MSDN docs say
450 * "Setting this property on a Transmission Control Protocol (TCP)
451 * socket will have no effect." but the MS runtime throws the
453 if (protocol_type == ProtocolType.Tcp)
454 throw new SocketException ((int)SocketError.ProtocolOption);
456 switch (address_family) {
457 case AddressFamily.InterNetwork:
458 SetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastLoopback, value ? 1 : 0);
460 case AddressFamily.InterNetworkV6:
461 SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback, value ? 1 : 0);
464 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
469 [MonoTODO ("This doesn't do anything on Mono yet")]
470 public bool UseOnlyOverlappedIO {
471 get { return use_overlapped_io; }
472 set { use_overlapped_io = value; }
475 public IntPtr Handle {
476 get { return safe_handle.DangerousGetHandle (); }
479 // Wish: support non-IP endpoints.
480 public EndPoint LocalEndPoint {
482 ThrowIfDisposedAndClosed ();
484 /* If the seed EndPoint is null, Connect, Bind, etc has not yet
485 * been called. MS returns null in this case. */
486 if (seed_endpoint == null)
490 SocketAddress sa = LocalEndPoint_internal (safe_handle, (int) address_family, out error);
493 throw new SocketException (error);
495 return seed_endpoint.Create (sa);
499 static SocketAddress LocalEndPoint_internal (SafeSocketHandle safeHandle, int family, out int error)
501 bool release = false;
503 safeHandle.DangerousAddRef (ref release);
504 return LocalEndPoint_internal (safeHandle.DangerousGetHandle (), family, out error);
507 safeHandle.DangerousRelease ();
511 /* Returns the local endpoint details in addr and port */
512 [MethodImplAttribute(MethodImplOptions.InternalCall)]
513 extern static SocketAddress LocalEndPoint_internal (IntPtr socket, int family, out int error);
515 public SocketType SocketType {
516 get { return socket_type; }
519 public int SendTimeout {
521 ThrowIfDisposedAndClosed ();
523 return (int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendTimeout);
526 ThrowIfDisposedAndClosed ();
529 throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than -1");
531 /* According to the MSDN docs we should adjust values between 1 and
532 * 499 to 500, but the MS runtime doesn't do this. */
536 SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, value);
540 public int ReceiveTimeout {
542 ThrowIfDisposedAndClosed ();
544 return (int) GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout);
547 ThrowIfDisposedAndClosed ();
550 throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than -1");
555 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, value);
559 public AddressFamily AddressFamily {
560 get { return address_family; }
563 public bool Blocking {
564 get { return is_blocking; }
566 ThrowIfDisposedAndClosed ();
569 Blocking_internal (safe_handle, value, out error);
572 throw new SocketException (error);
578 static void Blocking_internal (SafeSocketHandle safeHandle, bool block, out int error)
580 bool release = false;
582 safeHandle.DangerousAddRef (ref release);
583 Blocking_internal (safeHandle.DangerousGetHandle (), block, out error);
586 safeHandle.DangerousRelease ();
590 [MethodImplAttribute(MethodImplOptions.InternalCall)]
591 internal extern static void Blocking_internal(IntPtr socket, bool block, out int error);
593 public bool Connected {
594 get { return is_connected; }
595 internal set { is_connected = value; }
598 public ProtocolType ProtocolType {
599 get { return protocol_type; }
602 public bool NoDelay {
604 ThrowIfDisposedAndClosed ();
607 return ((int) GetSocketOption (SocketOptionLevel.Tcp, SocketOptionName.NoDelay)) != 0;
611 ThrowIfDisposedAndClosed ();
614 SetSocketOption (SocketOptionLevel.Tcp, SocketOptionName.NoDelay, value ? 1 : 0);
618 public int ReceiveBufferSize {
620 ThrowIfDisposedAndClosed ();
622 return (int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer);
625 ThrowIfDisposedAndClosed ();
628 throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
630 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, value);
634 public int SendBufferSize {
636 ThrowIfDisposedAndClosed ();
638 return (int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendBuffer);
641 ThrowIfDisposedAndClosed ();
644 throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
646 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendBuffer, value);
652 ThrowIfDisposedAndClosed ();
654 switch (address_family) {
655 case AddressFamily.InterNetwork:
656 return (short) (int) GetSocketOption (SocketOptionLevel.IP, SocketOptionName.IpTimeToLive);
657 case AddressFamily.InterNetworkV6:
658 return (short) (int) GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.HopLimit);
660 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
664 ThrowIfDisposedAndClosed ();
667 throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
669 switch (address_family) {
670 case AddressFamily.InterNetwork:
671 SetSocketOption (SocketOptionLevel.IP, SocketOptionName.IpTimeToLive, value);
673 case AddressFamily.InterNetworkV6:
674 SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.HopLimit, value);
677 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
682 public EndPoint RemoteEndPoint {
684 ThrowIfDisposedAndClosed ();
686 /* If the seed EndPoint is null, Connect, Bind, etc has
687 * not yet been called. MS returns null in this case. */
688 if (!is_connected || seed_endpoint == null)
692 SocketAddress sa = RemoteEndPoint_internal (safe_handle, (int) address_family, out error);
695 throw new SocketException (error);
697 return seed_endpoint.Create (sa);
701 static SocketAddress RemoteEndPoint_internal (SafeSocketHandle safeHandle, int family, out int error)
703 bool release = false;
705 safeHandle.DangerousAddRef (ref release);
706 return RemoteEndPoint_internal (safeHandle.DangerousGetHandle (), family, out error);
709 safeHandle.DangerousRelease ();
713 /* Returns the remote endpoint details in addr and port */
714 [MethodImplAttribute(MethodImplOptions.InternalCall)]
715 extern static SocketAddress RemoteEndPoint_internal (IntPtr socket, int family, out int error);
721 public static void Select (IList checkRead, IList checkWrite, IList checkError, int microSeconds)
723 var list = new List<Socket> ();
724 AddSockets (list, checkRead, "checkRead");
725 AddSockets (list, checkWrite, "checkWrite");
726 AddSockets (list, checkError, "checkError");
729 throw new ArgumentNullException ("checkRead, checkWrite, checkError", "All the lists are null or empty.");
731 /* The 'sockets' array contains:
732 * - READ socket 0-n, null,
733 * - WRITE socket 0-n, null,
734 * - ERROR socket 0-n, null */
735 Socket [] sockets = list.ToArray ();
738 Select_internal (ref sockets, microSeconds, out error);
741 throw new SocketException (error);
743 if (sockets == null) {
744 if (checkRead != null)
746 if (checkWrite != null)
748 if (checkError != null)
754 int count = sockets.Length;
755 IList currentList = checkRead;
757 for (int i = 0; i < count; i++) {
758 Socket sock = sockets [i];
759 if (sock == null) { // separator
760 if (currentList != null) {
761 // Remove non-signaled sockets after the current one
762 int to_remove = currentList.Count - currentIdx;
763 for (int k = 0; k < to_remove; k++)
764 currentList.RemoveAt (currentIdx);
766 currentList = (mode == 0) ? checkWrite : checkError;
772 if (mode == 1 && currentList == checkWrite && !sock.is_connected) {
773 if ((int) sock.GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error) == 0)
774 sock.is_connected = true;
777 /* Remove non-signaled sockets before the current one */
778 while (((Socket) currentList [currentIdx]) != sock)
779 currentList.RemoveAt (currentIdx);
785 static void AddSockets (List<Socket> sockets, IList list, string name)
788 foreach (Socket sock in list) {
789 if (sock == null) // MS throws a NullRef
790 throw new ArgumentNullException ("name", "Contains a null element");
798 [MethodImplAttribute(MethodImplOptions.InternalCall)]
799 extern static void Select_internal (ref Socket [] sockets, int microSeconds, out int error);
805 public bool Poll (int time_us, SelectMode mode)
807 ThrowIfDisposedAndClosed ();
809 if (mode != SelectMode.SelectRead && mode != SelectMode.SelectWrite && mode != SelectMode.SelectError)
810 throw new NotSupportedException ("'mode' parameter is not valid.");
813 bool result = Poll_internal (safe_handle, mode, time_us, out error);
816 throw new SocketException (error);
818 if (mode == SelectMode.SelectWrite && result && !is_connected) {
819 /* Update the is_connected state; for non-blocking Connect()
820 * this is when we can find out that the connect succeeded. */
821 if ((int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error) == 0)
828 static bool Poll_internal (SafeSocketHandle safeHandle, SelectMode mode, int timeout, out int error)
830 bool release = false;
832 safeHandle.DangerousAddRef (ref release);
833 return Poll_internal (safeHandle.DangerousGetHandle (), mode, timeout, out error);
836 safeHandle.DangerousRelease ();
840 [MethodImplAttribute(MethodImplOptions.InternalCall)]
841 extern static bool Poll_internal (IntPtr socket, SelectMode mode, int timeout, out int error);
847 public Socket Accept()
849 ThrowIfDisposedAndClosed ();
852 SafeSocketHandle safe_handle = Accept_internal (this.safe_handle, out error, is_blocking);
856 error = SOCKET_CLOSED_CODE;
857 throw new SocketException(error);
860 Socket accepted = new Socket (this.AddressFamily, this.SocketType, this.ProtocolType, safe_handle) {
861 seed_endpoint = this.seed_endpoint,
862 Blocking = this.Blocking,
868 internal void Accept (Socket acceptSocket)
870 ThrowIfDisposedAndClosed ();
873 SafeSocketHandle safe_handle = Accept_internal (this.safe_handle, out error, is_blocking);
877 error = SOCKET_CLOSED_CODE;
878 throw new SocketException (error);
881 acceptSocket.address_family = this.AddressFamily;
882 acceptSocket.socket_type = this.SocketType;
883 acceptSocket.protocol_type = this.ProtocolType;
884 acceptSocket.safe_handle = safe_handle;
885 acceptSocket.is_connected = true;
886 acceptSocket.seed_endpoint = this.seed_endpoint;
887 acceptSocket.Blocking = this.Blocking;
889 // FIXME: figure out what if anything else needs to be reset
892 public bool AcceptAsync (SocketAsyncEventArgs e)
894 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
896 ThrowIfDisposedAndClosed ();
899 throw new InvalidOperationException ("You must call the Bind method before performing this operation.");
901 throw new InvalidOperationException ("You must call the Listen method before performing this operation.");
902 if (e.BufferList != null)
903 throw new ArgumentException ("Multiple buffers cannot be used with this method.");
905 throw new ArgumentOutOfRangeException ("e.Count");
907 Socket acceptSocket = e.AcceptSocket;
908 if (acceptSocket != null) {
909 if (acceptSocket.is_bound || acceptSocket.is_connected)
910 throw new InvalidOperationException ("AcceptSocket: The socket must not be bound or connected.");
914 e.Worker.Init (this, e, SocketOperation.Accept);
916 SocketAsyncResult sockares = e.Worker.result;
918 QueueSocketAsyncResult (readQ, e.Worker, sockares);
923 public IAsyncResult BeginAccept(AsyncCallback callback, object state)
925 ThrowIfDisposedAndClosed ();
927 if (!is_bound || !is_listening)
928 throw new InvalidOperationException ();
930 SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.Accept);
932 QueueSocketAsyncResult (readQ, sockares.Worker, sockares);
937 public IAsyncResult BeginAccept (int receiveSize, AsyncCallback callback, object state)
939 ThrowIfDisposedAndClosed ();
942 throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
944 SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.AcceptReceive) {
945 Buffer = new byte [receiveSize],
948 SockFlags = SocketFlags.None,
951 QueueSocketAsyncResult (readQ, sockares.Worker, sockares);
956 public IAsyncResult BeginAccept (Socket acceptSocket, int receiveSize, AsyncCallback callback, object state)
958 ThrowIfDisposedAndClosed ();
961 throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
963 if (acceptSocket != null) {
964 ThrowIfDisposedAndClosed (acceptSocket);
966 if (acceptSocket.IsBound)
967 throw new InvalidOperationException ();
969 /* For some reason the MS runtime
970 * barfs if the new socket is not TCP,
971 * even though it's just about to blow
972 * away all those parameters
974 if (acceptSocket.ProtocolType != ProtocolType.Tcp)
975 throw new SocketException ((int)SocketError.InvalidArgument);
978 SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.AcceptReceive) {
979 Buffer = new byte [receiveSize],
982 SockFlags = SocketFlags.None,
983 AcceptSocket = acceptSocket,
986 QueueSocketAsyncResult (readQ, sockares.Worker, sockares);
991 public Socket EndAccept (IAsyncResult result)
995 return EndAccept (out buffer, out bytes, result);
998 public Socket EndAccept (out byte[] buffer, IAsyncResult asyncResult)
1001 return EndAccept (out buffer, out bytes, asyncResult);
1004 public Socket EndAccept (out byte[] buffer, out int bytesTransferred, IAsyncResult asyncResult)
1006 ThrowIfDisposedAndClosed ();
1008 SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndAccept", "asyncResult");
1010 if (!sockares.IsCompleted)
1011 sockares.AsyncWaitHandle.WaitOne ();
1013 sockares.CheckIfThrowDelayedException ();
1015 buffer = sockares.Buffer;
1016 bytesTransferred = sockares.Total;
1018 return sockares.Socket;
1021 static SafeSocketHandle Accept_internal (SafeSocketHandle safeHandle, out int error, bool blocking)
1024 safeHandle.RegisterForBlockingSyscall ();
1025 var ret = Accept_internal (safeHandle.DangerousGetHandle (), out error, blocking);
1026 return new SafeSocketHandle (ret, true);
1028 safeHandle.UnRegisterForBlockingSyscall ();
1032 /* Creates a new system socket, returning the handle */
1033 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1034 extern static IntPtr Accept_internal (IntPtr sock, out int error, bool blocking);
1040 public void Bind (EndPoint local_end)
1042 ThrowIfDisposedAndClosed ();
1044 if (local_end == null)
1045 throw new ArgumentNullException("local_end");
1048 Bind_internal (safe_handle, local_end.Serialize(), out error);
1051 throw new SocketException (error);
1055 seed_endpoint = local_end;
1058 private static void Bind_internal (SafeSocketHandle safeHandle, SocketAddress sa, out int error)
1060 bool release = false;
1062 safeHandle.DangerousAddRef (ref release);
1063 Bind_internal (safeHandle.DangerousGetHandle (), sa, out error);
1066 safeHandle.DangerousRelease ();
1070 // Creates a new system socket, returning the handle
1071 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1072 private extern static void Bind_internal(IntPtr sock, SocketAddress sa, out int error);
1078 public void Listen (int backlog)
1080 ThrowIfDisposedAndClosed ();
1083 throw new SocketException ((int) SocketError.InvalidArgument);
1086 Listen_internal(safe_handle, backlog, out error);
1089 throw new SocketException (error);
1091 is_listening = true;
1094 static void Listen_internal (SafeSocketHandle safeHandle, int backlog, out int error)
1096 bool release = false;
1098 safeHandle.DangerousAddRef (ref release);
1099 Listen_internal (safeHandle.DangerousGetHandle (), backlog, out error);
1102 safeHandle.DangerousRelease ();
1106 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1107 extern static void Listen_internal (IntPtr sock, int backlog, out int error);
1113 public void Connect (IPAddress address, int port)
1115 Connect (new IPEndPoint (address, port));
1118 public void Connect (string host, int port)
1120 Connect (Dns.GetHostAddresses (host), port);
1123 public void Connect (IPAddress[] addresses, int port)
1125 ThrowIfDisposedAndClosed ();
1127 if (addresses == null)
1128 throw new ArgumentNullException ("addresses");
1129 if (this.AddressFamily != AddressFamily.InterNetwork && this.AddressFamily != AddressFamily.InterNetworkV6)
1130 throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
1132 throw new InvalidOperationException ();
1134 // FIXME: do non-blocking sockets Poll here?
1136 foreach (IPAddress address in addresses) {
1137 IPEndPoint iep = new IPEndPoint (address, port);
1139 Connect_internal (safe_handle, iep.Serialize (), out error);
1141 is_connected = true;
1143 seed_endpoint = iep;
1146 if (error != (int)SocketError.InProgress && error != (int)SocketError.WouldBlock)
1150 Poll (-1, SelectMode.SelectWrite);
1151 error = (int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
1153 is_connected = true;
1155 seed_endpoint = iep;
1162 throw new SocketException (error);
1166 public void Connect (EndPoint remoteEP)
1168 ThrowIfDisposedAndClosed ();
1170 if (remoteEP == null)
1171 throw new ArgumentNullException ("remoteEP");
1173 IPEndPoint ep = remoteEP as IPEndPoint;
1174 /* Dgram uses Any to 'disconnect' */
1175 if (ep != null && socket_type != SocketType.Dgram) {
1176 if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any))
1177 throw new SocketException ((int) SocketError.AddressNotAvailable);
1181 throw new InvalidOperationException ();
1183 SocketAddress serial = remoteEP.Serialize ();
1186 Connect_internal (safe_handle, serial, out error);
1188 if (error == 0 || error == 10035)
1189 seed_endpoint = remoteEP; // Keep the ep around for non-blocking sockets
1193 error = SOCKET_CLOSED_CODE;
1194 throw new SocketException (error);
1197 is_connected = !(socket_type == SocketType.Dgram && ep != null && (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)));
1201 public bool ConnectAsync (SocketAsyncEventArgs e)
1203 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1205 ThrowIfDisposedAndClosed ();
1208 throw new InvalidOperationException ("You may not perform this operation after calling the Listen method.");
1209 if (e.RemoteEndPoint == null)
1210 throw new ArgumentNullException ("remoteEP");
1213 e.Worker.Init (this, e, SocketOperation.Connect);
1215 SocketAsyncResult result = e.Worker.result;
1218 IPAddress [] addresses;
1221 if (!GetCheckedIPs (e, out addresses)) {
1222 result.EndPoint = e.RemoteEndPoint;
1223 ares = BeginConnect (e.RemoteEndPoint, SocketAsyncEventArgs.Dispatcher, e);
1225 DnsEndPoint dep = (e.RemoteEndPoint as DnsEndPoint);
1226 result.Addresses = addresses;
1227 result.Port = dep.Port;
1228 ares = BeginConnect (addresses, dep.Port, SocketAsyncEventArgs.Dispatcher, e);
1231 if (ares.IsCompleted && ares.CompletedSynchronously) {
1232 ((SocketAsyncResult) ares).CheckIfThrowDelayedException ();
1235 } catch (Exception exc) {
1236 result.Complete (exc, true);
1243 public IAsyncResult BeginConnect (IPAddress address, int port, AsyncCallback callback, object state)
1245 ThrowIfDisposedAndClosed ();
1247 if (address == null)
1248 throw new ArgumentNullException ("address");
1249 if (address.ToString ().Length == 0)
1250 throw new ArgumentException ("The length of the IP address is zero");
1251 if (port <= 0 || port > 65535)
1252 throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
1254 throw new InvalidOperationException ();
1256 return BeginConnect (new IPEndPoint (address, port), callback, state);
1259 public IAsyncResult BeginConnect (string host, int port, AsyncCallback callback, object state)
1261 ThrowIfDisposedAndClosed ();
1264 throw new ArgumentNullException ("host");
1265 if (address_family != AddressFamily.InterNetwork && address_family != AddressFamily.InterNetworkV6)
1266 throw new NotSupportedException ("This method is valid only for sockets in the InterNetwork and InterNetworkV6 families");
1267 if (port <= 0 || port > 65535)
1268 throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
1270 throw new InvalidOperationException ();
1272 return BeginConnect (Dns.GetHostAddresses (host), port, callback, state);
1275 public IAsyncResult BeginConnect (EndPoint end_point, AsyncCallback callback, object state)
1277 ThrowIfDisposedAndClosed ();
1279 if (end_point == null)
1280 throw new ArgumentNullException ("end_point");
1282 SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.Connect) {
1283 EndPoint = end_point,
1286 // Bug #75154: Connect() should not succeed for .Any addresses.
1287 if (end_point is IPEndPoint) {
1288 IPEndPoint ep = (IPEndPoint) end_point;
1289 if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)) {
1290 sockares.Complete (new SocketException ((int) SocketError.AddressNotAvailable), true);
1297 if (connect_in_progress) {
1298 // This could happen when multiple IPs are used
1299 // Calling connect() again will reset the connection attempt and cause
1300 // an error. Better to just close the socket and move on.
1301 connect_in_progress = false;
1302 safe_handle.Dispose ();
1303 var handle = Socket_internal (address_family, socket_type, protocol_type, out error);
1304 safe_handle = new SafeSocketHandle (handle, true);
1306 throw new SocketException (error);
1309 bool blk = is_blocking;
1312 Connect_internal (safe_handle, end_point.Serialize (), out error);
1318 is_connected = true;
1320 sockares.Complete (true);
1324 if (error != (int) SocketError.InProgress && error != (int) SocketError.WouldBlock) {
1326 is_connected = false;
1328 sockares.Complete (new SocketException (error), true);
1333 is_connected = false;
1335 connect_in_progress = true;
1337 socket_pool_queue (SocketAsyncWorker.Dispatcher, sockares);
1342 public IAsyncResult BeginConnect (IPAddress[] addresses, int port, AsyncCallback callback, object state)
1344 ThrowIfDisposedAndClosed ();
1346 if (addresses == null)
1347 throw new ArgumentNullException ("addresses");
1348 if (addresses.Length == 0)
1349 throw new ArgumentException ("Empty addresses list");
1350 if (this.AddressFamily != AddressFamily.InterNetwork && this.AddressFamily != AddressFamily.InterNetworkV6)
1351 throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
1352 if (port <= 0 || port > 65535)
1353 throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
1355 throw new InvalidOperationException ();
1357 SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.Connect) {
1358 Addresses = addresses,
1362 is_connected = false;
1364 return BeginMConnect (sockares);
1367 internal IAsyncResult BeginMConnect (SocketAsyncResult sockares)
1369 IAsyncResult ares = null;
1370 Exception exc = null;
1372 for (int i = sockares.CurrentAddress; i < sockares.Addresses.Length; i++) {
1374 sockares.CurrentAddress++;
1376 ares = BeginConnect (new IPEndPoint (sockares.Addresses [i], sockares.Port), null, sockares);
1377 if (ares.IsCompleted && ares.CompletedSynchronously) {
1378 ((SocketAsyncResult) ares).CheckIfThrowDelayedException ();
1379 sockares.DoMConnectCallback ();
1383 } catch (Exception e) {
1395 public void EndConnect (IAsyncResult result)
1397 ThrowIfDisposedAndClosed ();
1399 SocketAsyncResult sockares = ValidateEndIAsyncResult (result, "EndConnect", "result");
1401 if (!sockares.IsCompleted)
1402 sockares.AsyncWaitHandle.WaitOne();
1404 sockares.CheckIfThrowDelayedException();
1407 static void Connect_internal (SafeSocketHandle safeHandle, SocketAddress sa, out int error)
1410 safeHandle.RegisterForBlockingSyscall ();
1411 Connect_internal (safeHandle.DangerousGetHandle (), sa, out error);
1413 safeHandle.UnRegisterForBlockingSyscall ();
1417 /* Connects to the remote address */
1418 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1419 extern static void Connect_internal(IntPtr sock, SocketAddress sa, out int error);
1422 * - false when it is ok to use RemoteEndPoint
1423 * - true when addresses must be used (and addresses could be null/empty) */
1424 bool GetCheckedIPs (SocketAsyncEventArgs e, out IPAddress [] addresses)
1428 // Connect to the first address that match the host name, like:
1429 // http://blogs.msdn.com/ncl/archive/2009/07/20/new-ncl-features-in-net-4-0-beta-2.aspx
1430 // while skipping entries that do not match the address family
1431 DnsEndPoint dep = e.RemoteEndPoint as DnsEndPoint;
1433 addresses = Dns.GetHostAddresses (dep.Host);
1436 e.ConnectByNameError = null;
1445 /* According to the docs, the MS runtime will throw PlatformNotSupportedException
1446 * if the platform is newer than w2k. We should be able to cope... */
1447 public void Disconnect (bool reuseSocket)
1449 ThrowIfDisposedAndClosed ();
1452 Disconnect_internal (safe_handle, reuseSocket, out error);
1456 /* ERROR_NOT_SUPPORTED */
1457 throw new PlatformNotSupportedException ();
1459 throw new SocketException (error);
1463 is_connected = false;
1465 /* Do managed housekeeping here... */
1469 public bool DisconnectAsync (SocketAsyncEventArgs e)
1471 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1473 ThrowIfDisposedAndClosed ();
1476 e.Worker.Init (this, e, SocketOperation.Disconnect);
1478 SocketAsyncResult sockares = e.Worker.result;
1480 socket_pool_queue (SocketAsyncWorker.Dispatcher, sockares);
1486 public IAsyncResult BeginDisconnect (bool reuseSocket, AsyncCallback callback, object state)
1488 ThrowIfDisposedAndClosed ();
1490 SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.Disconnect) {
1491 ReuseSocket = reuseSocket,
1494 socket_pool_queue (SocketAsyncWorker.Dispatcher, sockares);
1499 public void EndDisconnect (IAsyncResult asyncResult)
1501 ThrowIfDisposedAndClosed ();
1503 SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndDisconnect", "asyncResult");
1505 if (!sockares.IsCompleted)
1506 sockares.AsyncWaitHandle.WaitOne ();
1508 sockares.CheckIfThrowDelayedException ();
1511 static void Disconnect_internal (SafeSocketHandle safeHandle, bool reuse, out int error)
1513 bool release = false;
1515 safeHandle.DangerousAddRef (ref release);
1516 Disconnect_internal (safeHandle.DangerousGetHandle (), reuse, out error);
1519 safeHandle.DangerousRelease ();
1523 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1524 extern static void Disconnect_internal (IntPtr sock, bool reuse, out int error);
1530 public int Receive (byte [] buffer)
1532 return Receive (buffer, SocketFlags.None);
1535 public int Receive (byte [] buffer, SocketFlags flags)
1537 ThrowIfDisposedAndClosed ();
1538 ThrowIfBufferNull (buffer);
1539 ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
1542 int ret = Receive_nochecks (buffer, 0, buffer.Length, flags, out error);
1544 if (error != SocketError.Success) {
1545 if (error == SocketError.WouldBlock && is_blocking) // This might happen when ReceiveTimeout is set
1546 throw new SocketException ((int) error, TIMEOUT_EXCEPTION_MSG);
1547 throw new SocketException ((int) error);
1553 public int Receive (byte [] buffer, int size, SocketFlags flags)
1555 ThrowIfDisposedAndClosed ();
1556 ThrowIfBufferNull (buffer);
1557 ThrowIfBufferOutOfRange (buffer, 0, size);
1560 int ret = Receive_nochecks (buffer, 0, size, flags, out error);
1562 if (error != SocketError.Success) {
1563 if (error == SocketError.WouldBlock && is_blocking) // This might happen when ReceiveTimeout is set
1564 throw new SocketException ((int) error, TIMEOUT_EXCEPTION_MSG);
1565 throw new SocketException ((int) error);
1571 public int Receive (byte [] buffer, int offset, int size, SocketFlags flags)
1573 ThrowIfDisposedAndClosed ();
1574 ThrowIfBufferNull (buffer);
1575 ThrowIfBufferOutOfRange (buffer, offset, size);
1578 int ret = Receive_nochecks (buffer, offset, size, flags, out error);
1580 if (error != SocketError.Success) {
1581 if (error == SocketError.WouldBlock && is_blocking) // This might happen when ReceiveTimeout is set
1582 throw new SocketException ((int) error, TIMEOUT_EXCEPTION_MSG);
1583 throw new SocketException ((int) error);
1589 public int Receive (byte [] buffer, int offset, int size, SocketFlags flags, out SocketError error)
1591 ThrowIfDisposedAndClosed ();
1592 ThrowIfBufferNull (buffer);
1593 ThrowIfBufferOutOfRange (buffer, offset, size);
1595 return Receive_nochecks (buffer, offset, size, flags, out error);
1598 public int Receive (IList<ArraySegment<byte>> buffers)
1601 int ret = Receive (buffers, SocketFlags.None, out error);
1603 if (error != SocketError.Success)
1604 throw new SocketException ((int) error);
1609 [CLSCompliant (false)]
1610 public int Receive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags)
1613 int ret = Receive (buffers, socketFlags, out error);
1615 if (error != SocketError.Success)
1616 throw new SocketException ((int) error);
1621 [CLSCompliant (false)]
1622 public int Receive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode)
1624 ThrowIfDisposedAndClosed ();
1626 if (buffers == null || buffers.Count == 0)
1627 throw new ArgumentNullException ("buffers");
1629 int numsegments = buffers.Count;
1633 /* Only example I can find of sending a byte array reference directly into an internal
1634 * call is in System.Runtime.Remoting/System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeSocket.cs,
1635 * so taking a lead from that... */
1636 WSABUF[] bufarray = new WSABUF[numsegments];
1637 GCHandle[] gch = new GCHandle[numsegments];
1639 for (int i = 0; i < numsegments; i++) {
1640 ArraySegment<byte> segment = buffers[i];
1642 if (segment.Offset < 0 || segment.Count < 0 || segment.Count > segment.Array.Length - segment.Offset)
1643 throw new ArgumentOutOfRangeException ("segment");
1645 gch[i] = GCHandle.Alloc (segment.Array, GCHandleType.Pinned);
1646 bufarray[i].len = segment.Count;
1647 bufarray[i].buf = Marshal.UnsafeAddrOfPinnedArrayElement (segment.Array, segment.Offset);
1651 ret = Receive_internal (safe_handle, bufarray, socketFlags, out nativeError);
1653 for (int i = 0; i < numsegments; i++) {
1654 if (gch[i].IsAllocated)
1659 errorCode = (SocketError) nativeError;
1664 public bool ReceiveAsync (SocketAsyncEventArgs e)
1666 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1668 ThrowIfDisposedAndClosed ();
1670 // LAME SPEC: the ArgumentException is never thrown, instead an NRE is
1671 // thrown when e.Buffer and e.BufferList are null (works fine when one is
1672 // set to a valid object)
1673 if (e.Buffer == null && e.BufferList == null)
1674 throw new NullReferenceException ("Either e.Buffer or e.BufferList must be valid buffers.");
1677 e.Worker.Init (this, e, e.Buffer != null ? SocketOperation.Receive : SocketOperation.ReceiveGeneric);
1679 SocketAsyncResult sockares = e.Worker.result;
1680 sockares.SockFlags = e.SocketFlags;
1682 if (e.Buffer != null) {
1683 sockares.Buffer = e.Buffer;
1684 sockares.Offset = e.Offset;
1685 sockares.Size = e.Count;
1687 sockares.Buffers = e.BufferList;
1690 // Receive takes care of ReceiveGeneric
1691 QueueSocketAsyncResult (readQ, e.Worker, sockares);
1696 public IAsyncResult BeginReceive (byte[] buffer, int offset, int size, SocketFlags socket_flags, AsyncCallback callback, object state)
1698 ThrowIfDisposedAndClosed ();
1699 ThrowIfBufferNull (buffer);
1700 ThrowIfBufferOutOfRange (buffer, offset, size);
1702 SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.Receive) {
1706 SockFlags = socket_flags,
1709 QueueSocketAsyncResult (readQ, sockares.Worker, sockares);
1714 public IAsyncResult BeginReceive (byte[] buffer, int offset, int size, SocketFlags flags, out SocketError error, AsyncCallback callback, object state)
1716 /* As far as I can tell from the docs and from experimentation, a pointer to the
1717 * SocketError parameter is not supposed to be saved for the async parts. And as we don't
1718 * set any socket errors in the setup code, we just have to set it to Success. */
1719 error = SocketError.Success;
1720 return BeginReceive (buffer, offset, size, flags, callback, state);
1723 [CLSCompliant (false)]
1724 public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, AsyncCallback callback, object state)
1726 ThrowIfDisposedAndClosed ();
1728 if (buffers == null)
1729 throw new ArgumentNullException ("buffers");
1731 SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveGeneric) {
1733 SockFlags = socketFlags,
1736 QueueSocketAsyncResult (readQ, sockares.Worker, sockares);
1741 [CLSCompliant (false)]
1742 public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
1744 /* I assume the same SocketError semantics as above */
1745 errorCode = SocketError.Success;
1746 return BeginReceive (buffers, socketFlags, callback, state);
1749 public int EndReceive (IAsyncResult result)
1752 int bytesReceived = EndReceive (result, out error);
1754 if (error != SocketError.Success) {
1755 if (error != SocketError.WouldBlock && error != SocketError.InProgress)
1756 is_connected = false;
1757 throw new SocketException ((int)error);
1760 return bytesReceived;
1763 public int EndReceive (IAsyncResult asyncResult, out SocketError errorCode)
1765 ThrowIfDisposedAndClosed ();
1767 SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndReceive", "asyncResult");
1769 if (!sockares.IsCompleted)
1770 sockares.AsyncWaitHandle.WaitOne ();
1772 // If no socket error occurred, call CheckIfThrowDelayedException in case there are other
1773 // kinds of exceptions that should be thrown.
1774 if ((errorCode = sockares.ErrorCode) == SocketError.Success)
1775 sockares.CheckIfThrowDelayedException();
1777 return sockares.Total;
1780 internal int Receive_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
1783 int ret = Receive_internal (safe_handle, buf, offset, size, flags, out nativeError);
1785 error = (SocketError) nativeError;
1786 if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress) {
1787 is_connected = false;
1790 is_connected = true;
1796 static int Receive_internal (SafeSocketHandle safeHandle, WSABUF[] bufarray, SocketFlags flags, out int error)
1799 safeHandle.RegisterForBlockingSyscall ();
1800 return Receive_internal (safeHandle.DangerousGetHandle (), bufarray, flags, out error);
1802 safeHandle.UnRegisterForBlockingSyscall ();
1806 [MethodImplAttribute (MethodImplOptions.InternalCall)]
1807 extern static int Receive_internal (IntPtr sock, WSABUF[] bufarray, SocketFlags flags, out int error);
1809 static int Receive_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, out int error)
1812 safeHandle.RegisterForBlockingSyscall ();
1813 return Receive_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, out error);
1815 safeHandle.UnRegisterForBlockingSyscall ();
1819 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1820 extern static int Receive_internal(IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags, out int error);
1826 public int ReceiveFrom (byte [] buffer, ref EndPoint remoteEP)
1828 ThrowIfDisposedAndClosed ();
1829 ThrowIfBufferNull (buffer);
1830 ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
1832 if (remoteEP == null)
1833 throw new ArgumentNullException ("remoteEP");
1835 return ReceiveFrom_nochecks (buffer, 0, buffer.Length, SocketFlags.None, ref remoteEP);
1838 public int ReceiveFrom (byte [] buffer, SocketFlags flags, ref EndPoint remoteEP)
1840 ThrowIfDisposedAndClosed ();
1841 ThrowIfBufferNull (buffer);
1842 ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
1844 if (remoteEP == null)
1845 throw new ArgumentNullException ("remoteEP");
1847 return ReceiveFrom_nochecks (buffer, 0, buffer.Length, flags, ref remoteEP);
1850 public int ReceiveFrom (byte [] buffer, int size, SocketFlags flags, ref EndPoint remoteEP)
1852 ThrowIfDisposedAndClosed ();
1853 ThrowIfBufferNull (buffer);
1854 ThrowIfBufferOutOfRange (buffer, 0, size);
1856 if (remoteEP == null)
1857 throw new ArgumentNullException ("remoteEP");
1859 return ReceiveFrom_nochecks (buffer, 0, size, flags, ref remoteEP);
1862 public int ReceiveFrom (byte [] buffer, int offset, int size, SocketFlags flags, ref EndPoint remoteEP)
1864 ThrowIfDisposedAndClosed ();
1865 ThrowIfBufferNull (buffer);
1866 ThrowIfBufferOutOfRange (buffer, offset, size);
1868 if (remoteEP == null)
1869 throw new ArgumentNullException ("remoteEP");
1871 return ReceiveFrom_nochecks (buffer, offset, size, flags, ref remoteEP);
1874 public bool ReceiveFromAsync (SocketAsyncEventArgs e)
1876 ThrowIfDisposedAndClosed ();
1878 // We do not support recv into multiple buffers yet
1879 if (e.BufferList != null)
1880 throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
1881 if (e.RemoteEndPoint == null)
1882 throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
1885 e.Worker.Init (this, e, SocketOperation.ReceiveFrom);
1887 SocketAsyncResult sockares = e.Worker.result;
1888 sockares.Buffer = e.Buffer;
1889 sockares.Offset = e.Offset;
1890 sockares.Size = e.Count;
1891 sockares.EndPoint = e.RemoteEndPoint;
1892 sockares.SockFlags = e.SocketFlags;
1894 QueueSocketAsyncResult (readQ, e.Worker, sockares);
1899 public IAsyncResult BeginReceiveFrom (byte[] buffer, int offset, int size, SocketFlags socket_flags, ref EndPoint remote_end, AsyncCallback callback, object state)
1901 ThrowIfDisposedAndClosed ();
1902 ThrowIfBufferNull (buffer);
1903 ThrowIfBufferOutOfRange (buffer, offset, size);
1905 if (remote_end == null)
1906 throw new ArgumentNullException ("remote_end");
1908 SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveFrom) {
1912 SockFlags = socket_flags,
1913 EndPoint = remote_end,
1916 QueueSocketAsyncResult (readQ, sockares.Worker, sockares);
1921 public int EndReceiveFrom(IAsyncResult result, ref EndPoint end_point)
1923 ThrowIfDisposedAndClosed ();
1925 if (end_point == null)
1926 throw new ArgumentNullException ("remote_end");
1928 SocketAsyncResult sockares = ValidateEndIAsyncResult (result, "EndReceiveFrom", "result");
1930 if (!sockares.IsCompleted)
1931 sockares.AsyncWaitHandle.WaitOne();
1933 sockares.CheckIfThrowDelayedException();
1935 end_point = sockares.EndPoint;
1937 return sockares.Total;
1940 internal int ReceiveFrom_nochecks (byte [] buf, int offset, int size, SocketFlags flags, ref EndPoint remote_end)
1943 return ReceiveFrom_nochecks_exc (buf, offset, size, flags, ref remote_end, true, out error);
1946 internal int ReceiveFrom_nochecks_exc (byte [] buf, int offset, int size, SocketFlags flags, ref EndPoint remote_end, bool throwOnError, out int error)
1948 SocketAddress sockaddr = remote_end.Serialize();
1950 int cnt = ReceiveFrom_internal (safe_handle, buf, offset, size, flags, ref sockaddr, out error);
1952 SocketError err = (SocketError) error;
1954 if (err != SocketError.WouldBlock && err != SocketError.InProgress) {
1955 is_connected = false;
1956 } else if (err == SocketError.WouldBlock && is_blocking) { // This might happen when ReceiveTimeout is set
1958 throw new SocketException ((int) SocketError.TimedOut, TIMEOUT_EXCEPTION_MSG);
1959 error = (int) SocketError.TimedOut;
1964 throw new SocketException (error);
1969 is_connected = true;
1972 /* If sockaddr is null then we're a connection oriented protocol and should ignore the
1973 * remote_end parameter (see MSDN documentation for Socket.ReceiveFrom(...) ) */
1974 if (sockaddr != null) {
1975 /* Stupidly, EndPoint.Create() is an instance method */
1976 remote_end = remote_end.Create (sockaddr);
1979 seed_endpoint = remote_end;
1984 static int ReceiveFrom_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, ref SocketAddress sockaddr, out int error)
1987 safeHandle.RegisterForBlockingSyscall ();
1988 return ReceiveFrom_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, ref sockaddr, out error);
1990 safeHandle.UnRegisterForBlockingSyscall ();
1994 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1995 extern static int ReceiveFrom_internal(IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags, ref SocketAddress sockaddr, out int error);
1999 #region ReceiveMessageFrom
2001 [MonoTODO ("Not implemented")]
2002 public int ReceiveMessageFrom (byte[] buffer, int offset, int size, ref SocketFlags socketFlags, ref EndPoint remoteEP, out IPPacketInformation ipPacketInformation)
2004 ThrowIfDisposedAndClosed ();
2005 ThrowIfBufferNull (buffer);
2006 ThrowIfBufferOutOfRange (buffer, offset, size);
2008 if (remoteEP == null)
2009 throw new ArgumentNullException ("remoteEP");
2011 // FIXME: figure out how we get hold of the IPPacketInformation
2012 throw new NotImplementedException ();
2015 [MonoTODO ("Not implemented")]
2016 public bool ReceiveMessageFromAsync (SocketAsyncEventArgs e)
2018 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
2020 ThrowIfDisposedAndClosed ();
2022 throw new NotImplementedException ();
2026 public IAsyncResult BeginReceiveMessageFrom (byte[] buffer, int offset, int size, SocketFlags socketFlags, ref EndPoint remoteEP, AsyncCallback callback, object state)
2028 ThrowIfDisposedAndClosed ();
2029 ThrowIfBufferNull (buffer);
2030 ThrowIfBufferOutOfRange (buffer, offset, size);
2032 if (remoteEP == null)
2033 throw new ArgumentNullException ("remoteEP");
2035 throw new NotImplementedException ();
2039 public int EndReceiveMessageFrom (IAsyncResult asyncResult, ref SocketFlags socketFlags, ref EndPoint endPoint, out IPPacketInformation ipPacketInformation)
2041 ThrowIfDisposedAndClosed ();
2043 if (endPoint == null)
2044 throw new ArgumentNullException ("endPoint");
2046 SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndReceiveMessageFrom", "asyncResult");
2048 throw new NotImplementedException ();
2055 public int Send (byte [] buffer)
2057 ThrowIfDisposedAndClosed ();
2058 ThrowIfBufferNull (buffer);
2059 ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
2062 int ret = Send_nochecks (buffer, 0, buffer.Length, SocketFlags.None, out error);
2064 if (error != SocketError.Success)
2065 throw new SocketException ((int) error);
2070 public int Send (byte [] buffer, SocketFlags flags)
2072 ThrowIfDisposedAndClosed ();
2073 ThrowIfBufferNull (buffer);
2074 ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
2077 int ret = Send_nochecks (buffer, 0, buffer.Length, flags, out error);
2079 if (error != SocketError.Success)
2080 throw new SocketException ((int) error);
2085 public int Send (byte [] buffer, int size, SocketFlags flags)
2087 ThrowIfDisposedAndClosed ();
2088 ThrowIfBufferNull (buffer);
2089 ThrowIfBufferOutOfRange (buffer, 0, size);
2092 int ret = Send_nochecks (buffer, 0, size, flags, out error);
2094 if (error != SocketError.Success)
2095 throw new SocketException ((int) error);
2100 public int Send (byte [] buffer, int offset, int size, SocketFlags flags)
2102 ThrowIfDisposedAndClosed ();
2103 ThrowIfBufferNull (buffer);
2104 ThrowIfBufferOutOfRange (buffer, offset, size);
2107 int ret = Send_nochecks (buffer, offset, size, flags, out error);
2109 if (error != SocketError.Success)
2110 throw new SocketException ((int) error);
2115 public int Send (byte [] buffer, int offset, int size, SocketFlags flags, out SocketError error)
2117 ThrowIfDisposedAndClosed ();
2118 ThrowIfBufferNull (buffer);
2119 ThrowIfBufferOutOfRange (buffer, offset, size);
2121 return Send_nochecks (buffer, offset, size, flags, out error);
2125 int Send (IList<ArraySegment<byte>> buffers)
2128 int ret = Send (buffers, SocketFlags.None, out error);
2130 if (error != SocketError.Success)
2131 throw new SocketException ((int) error);
2137 int Send (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags)
2140 int ret = Send (buffers, socketFlags, out error);
2142 if (error != SocketError.Success)
2143 throw new SocketException ((int) error);
2148 [CLSCompliant (false)]
2149 public int Send (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode)
2151 ThrowIfDisposedAndClosed ();
2153 if (buffers == null)
2154 throw new ArgumentNullException ("buffers");
2155 if (buffers.Count == 0)
2156 throw new ArgumentException ("Buffer is empty", "buffers");
2158 int numsegments = buffers.Count;
2162 WSABUF[] bufarray = new WSABUF[numsegments];
2163 GCHandle[] gch = new GCHandle[numsegments];
2165 for(int i = 0; i < numsegments; i++) {
2166 ArraySegment<byte> segment = buffers[i];
2168 if (segment.Offset < 0 || segment.Count < 0 || segment.Count > segment.Array.Length - segment.Offset)
2169 throw new ArgumentOutOfRangeException ("segment");
2171 gch[i] = GCHandle.Alloc (segment.Array, GCHandleType.Pinned);
2172 bufarray[i].len = segment.Count;
2173 bufarray[i].buf = Marshal.UnsafeAddrOfPinnedArrayElement (segment.Array, segment.Offset);
2177 ret = Send_internal (safe_handle, bufarray, socketFlags, out nativeError);
2179 for(int i = 0; i < numsegments; i++) {
2180 if (gch[i].IsAllocated) {
2186 errorCode = (SocketError)nativeError;
2191 internal int Send_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
2194 error = SocketError.Success;
2199 int ret = Send_internal (safe_handle, buf, offset, size, flags, out nativeError);
2201 error = (SocketError)nativeError;
2203 if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress) {
2204 is_connected = false;
2207 is_connected = true;
2213 public bool SendAsync (SocketAsyncEventArgs e)
2215 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
2217 ThrowIfDisposedAndClosed ();
2219 if (e.Buffer == null && e.BufferList == null)
2220 throw new NullReferenceException ("Either e.Buffer or e.BufferList must be valid buffers.");
2223 e.Worker.Init (this, e, e.Buffer != null ? SocketOperation.Send : SocketOperation.SendGeneric);
2225 SocketAsyncResult sockares = e.Worker.result;
2226 sockares.SockFlags = e.SocketFlags;
2228 if (e.Buffer != null) {
2229 sockares.Buffer = e.Buffer;
2230 sockares.Offset = e.Offset;
2231 sockares.Size = e.Count;
2233 sockares.Buffers = e.BufferList;
2236 // Send takes care of SendGeneric
2237 QueueSocketAsyncResult (writeQ, e.Worker, sockares);
2242 public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
2244 if (!is_connected) {
2245 errorCode = SocketError.NotConnected;
2246 throw new SocketException ((int) errorCode);
2249 errorCode = SocketError.Success;
2250 return BeginSend (buffer, offset, size, socketFlags, callback, state);
2253 public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socket_flags, AsyncCallback callback, object state)
2255 ThrowIfDisposedAndClosed ();
2256 ThrowIfBufferNull (buffer);
2257 ThrowIfBufferOutOfRange (buffer, offset, size);
2260 throw new SocketException ((int)SocketError.NotConnected);
2262 SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.Send) {
2266 SockFlags = socket_flags,
2269 QueueSocketAsyncResult (writeQ, sockares.Worker, sockares);
2274 public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, AsyncCallback callback, object state)
2276 ThrowIfDisposedAndClosed ();
2278 if (buffers == null)
2279 throw new ArgumentNullException ("buffers");
2281 throw new SocketException ((int)SocketError.NotConnected);
2283 SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.SendGeneric) {
2285 SockFlags = socketFlags,
2288 QueueSocketAsyncResult (writeQ, sockares.Worker, sockares);
2293 [CLSCompliant (false)]
2294 public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
2296 if (!is_connected) {
2297 errorCode = SocketError.NotConnected;
2298 throw new SocketException ((int)errorCode);
2301 errorCode = SocketError.Success;
2302 return BeginSend (buffers, socketFlags, callback, state);
2305 public int EndSend (IAsyncResult result)
2308 int bytesSent = EndSend (result, out error);
2310 if (error != SocketError.Success) {
2311 if (error != SocketError.WouldBlock && error != SocketError.InProgress)
2312 is_connected = false;
2313 throw new SocketException ((int)error);
2319 public int EndSend (IAsyncResult asyncResult, out SocketError errorCode)
2321 ThrowIfDisposedAndClosed ();
2323 SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndSend", "asyncResult");
2325 if (!sockares.IsCompleted)
2326 sockares.AsyncWaitHandle.WaitOne ();
2328 /* If no socket error occurred, call CheckIfThrowDelayedException in
2329 * case there are other kinds of exceptions that should be thrown.*/
2330 if ((errorCode = sockares.ErrorCode) == SocketError.Success)
2331 sockares.CheckIfThrowDelayedException ();
2333 return sockares.Total;
2336 static int Send_internal (SafeSocketHandle safeHandle, WSABUF[] bufarray, SocketFlags flags, out int error)
2338 bool release = false;
2340 safeHandle.DangerousAddRef (ref release);
2341 return Send_internal (safeHandle.DangerousGetHandle (), bufarray, flags, out error);
2344 safeHandle.DangerousRelease ();
2348 [MethodImplAttribute (MethodImplOptions.InternalCall)]
2349 extern static int Send_internal (IntPtr sock, WSABUF[] bufarray, SocketFlags flags, out int error);
2351 static int Send_internal (SafeSocketHandle safeHandle, byte[] buf, int offset, int count, SocketFlags flags, out int error)
2354 safeHandle.RegisterForBlockingSyscall ();
2355 return Send_internal (safeHandle.DangerousGetHandle (), buf, offset, count, flags, out error);
2357 safeHandle.UnRegisterForBlockingSyscall ();
2361 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2362 extern static int Send_internal(IntPtr sock, byte[] buf, int offset, int count, SocketFlags flags, out int error);
2368 public int SendTo (byte [] buffer, EndPoint remote_end)
2370 ThrowIfDisposedAndClosed ();
2371 ThrowIfBufferNull (buffer);
2372 ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
2374 if (remote_end == null)
2375 throw new ArgumentNullException ("remote_end");
2377 return SendTo_nochecks (buffer, 0, buffer.Length, SocketFlags.None, remote_end);
2380 public int SendTo (byte [] buffer, SocketFlags flags, EndPoint remote_end)
2382 ThrowIfDisposedAndClosed ();
2383 ThrowIfBufferNull (buffer);
2384 ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
2386 if (remote_end == null)
2387 throw new ArgumentNullException ("remote_end");
2389 return SendTo_nochecks (buffer, 0, buffer.Length, flags, remote_end);
2392 public int SendTo (byte [] buffer, int size, SocketFlags flags, EndPoint remote_end)
2394 ThrowIfDisposedAndClosed ();
2395 ThrowIfBufferNull (buffer);
2396 ThrowIfBufferOutOfRange (buffer, 0, size);
2398 if (remote_end == null)
2399 throw new ArgumentNullException ("remote_end");
2401 return SendTo_nochecks (buffer, 0, size, flags, remote_end);
2404 public int SendTo (byte [] buffer, int offset, int size, SocketFlags flags, EndPoint remote_end)
2406 ThrowIfDisposedAndClosed ();
2407 ThrowIfBufferNull (buffer);
2408 ThrowIfBufferOutOfRange (buffer, offset, size);
2410 if (remote_end == null)
2411 throw new ArgumentNullException("remote_end");
2413 return SendTo_nochecks (buffer, offset, size, flags, remote_end);
2416 internal int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags, EndPoint remote_end)
2419 int ret = SendTo_internal (safe_handle, buffer, offset, size, flags, remote_end.Serialize (), out error);
2421 SocketError err = (SocketError) error;
2423 if (err != SocketError.WouldBlock && err != SocketError.InProgress)
2424 is_connected = false;
2425 throw new SocketException (error);
2428 is_connected = true;
2430 seed_endpoint = remote_end;
2435 public bool SendToAsync (SocketAsyncEventArgs e)
2437 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
2439 ThrowIfDisposedAndClosed ();
2441 if (e.BufferList != null)
2442 throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
2443 if (e.RemoteEndPoint == null)
2444 throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
2447 e.Worker.Init (this, e, SocketOperation.SendTo);
2449 SocketAsyncResult sockares = e.Worker.result;
2450 sockares.Buffer = e.Buffer;
2451 sockares.Offset = e.Offset;
2452 sockares.Size = e.Count;
2453 sockares.SockFlags = e.SocketFlags;
2454 sockares.EndPoint = e.RemoteEndPoint;
2456 QueueSocketAsyncResult (writeQ, e.Worker, sockares);
2462 public IAsyncResult BeginSendTo(byte[] buffer, int offset, int size, SocketFlags socket_flags, EndPoint remote_end, AsyncCallback callback, object state)
2464 ThrowIfDisposedAndClosed ();
2465 ThrowIfBufferNull (buffer);
2466 ThrowIfBufferOutOfRange (buffer, offset, size);
2468 SocketAsyncResult sockares = new SocketAsyncResult (this, state, callback, SocketOperation.SendTo) {
2472 SockFlags = socket_flags,
2473 EndPoint = remote_end,
2476 QueueSocketAsyncResult (writeQ, sockares.Worker, sockares);
2481 public int EndSendTo (IAsyncResult result)
2483 ThrowIfDisposedAndClosed ();
2485 SocketAsyncResult sockares = ValidateEndIAsyncResult (result, "EndSendTo", "result");
2487 if (!sockares.IsCompleted)
2488 sockares.AsyncWaitHandle.WaitOne();
2490 sockares.CheckIfThrowDelayedException();
2492 return sockares.Total;
2495 static int SendTo_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, SocketAddress sa, out int error)
2498 safeHandle.RegisterForBlockingSyscall ();
2499 return SendTo_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, sa, out error);
2501 safeHandle.UnRegisterForBlockingSyscall ();
2505 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2506 extern static int SendTo_internal (IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags, SocketAddress sa, out int error);
2512 public void SendFile (string fileName)
2514 ThrowIfDisposedAndClosed ();
2517 throw new NotSupportedException ();
2519 throw new InvalidOperationException ();
2521 SendFile (fileName, null, null, 0);
2524 public void SendFile (string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags)
2526 ThrowIfDisposedAndClosed ();
2529 throw new NotSupportedException ();
2531 throw new InvalidOperationException ();
2533 if (!SendFile_internal (safe_handle, fileName, preBuffer, postBuffer, flags)) {
2534 SocketException exc = new SocketException ();
2535 if (exc.ErrorCode == 2 || exc.ErrorCode == 3)
2536 throw new FileNotFoundException ();
2541 public IAsyncResult BeginSendFile (string fileName, AsyncCallback callback, object state)
2543 ThrowIfDisposedAndClosed ();
2546 throw new NotSupportedException ();
2547 if (!File.Exists (fileName))
2548 throw new FileNotFoundException ();
2550 return BeginSendFile (fileName, null, null, 0, callback, state);
2553 public IAsyncResult BeginSendFile (string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags, AsyncCallback callback, object state)
2555 ThrowIfDisposedAndClosed ();
2558 throw new NotSupportedException ();
2559 if (!File.Exists (fileName))
2560 throw new FileNotFoundException ();
2562 SendFileHandler handler = new SendFileHandler (SendFile);
2564 return new SendFileAsyncResult (handler, handler.BeginInvoke (fileName, preBuffer, postBuffer, flags, ar => callback (new SendFileAsyncResult (handler, ar)), state));
2567 public void EndSendFile (IAsyncResult asyncResult)
2569 ThrowIfDisposedAndClosed ();
2571 if (asyncResult == null)
2572 throw new ArgumentNullException ("asyncResult");
2574 SendFileAsyncResult ares = asyncResult as SendFileAsyncResult;
2576 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
2578 ares.Delegate.EndInvoke (ares.Original);
2581 static bool SendFile_internal (SafeSocketHandle safeHandle, string filename, byte [] pre_buffer, byte [] post_buffer, TransmitFileOptions flags)
2584 safeHandle.RegisterForBlockingSyscall ();
2585 return SendFile_internal (safeHandle.DangerousGetHandle (), filename, pre_buffer, post_buffer, flags);
2587 safeHandle.UnRegisterForBlockingSyscall ();
2591 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2592 extern static bool SendFile_internal (IntPtr sock, string filename, byte [] pre_buffer, byte [] post_buffer, TransmitFileOptions flags);
2594 delegate void SendFileHandler (string fileName, byte [] preBuffer, byte [] postBuffer, TransmitFileOptions flags);
2596 sealed class SendFileAsyncResult : IAsyncResult {
2600 public SendFileAsyncResult (SendFileHandler d, IAsyncResult ares)
2606 public object AsyncState {
2607 get { return ares.AsyncState; }
2610 public WaitHandle AsyncWaitHandle {
2611 get { return ares.AsyncWaitHandle; }
2614 public bool CompletedSynchronously {
2615 get { return ares.CompletedSynchronously; }
2618 public bool IsCompleted {
2619 get { return ares.IsCompleted; }
2622 public SendFileHandler Delegate {
2626 public IAsyncResult Original {
2627 get { return ares; }
2635 [MonoTODO ("Not implemented")]
2636 public bool SendPacketsAsync (SocketAsyncEventArgs e)
2638 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
2640 ThrowIfDisposedAndClosed ();
2642 throw new NotImplementedException ();
2647 #region DuplicateAndClose
2650 [MonoLimitation ("We do not support passing sockets across processes, we merely allow this API to pass the socket across AppDomains")]
2651 public SocketInformation DuplicateAndClose (int targetProcessId)
2653 var si = new SocketInformation ();
2655 (is_listening ? SocketInformationOptions.Listening : 0) |
2656 (is_connected ? SocketInformationOptions.Connected : 0) |
2657 (is_blocking ? 0 : SocketInformationOptions.NonBlocking) |
2658 (use_overlapped_io ? SocketInformationOptions.UseOnlyOverlappedIO : 0);
2660 si.ProtocolInformation = Mono.DataConverter.Pack ("iiiil", (int)address_family, (int)socket_type, (int)protocol_type, is_bound ? 1 : 0, (long)Handle);
2669 #region GetSocketOption
2671 public void GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, byte [] optionValue)
2673 ThrowIfDisposedAndClosed ();
2675 if (optionValue == null)
2676 throw new SocketException ((int) SocketError.Fault, "Error trying to dereference an invalid pointer");
2679 GetSocketOption_arr_internal (safe_handle, optionLevel, optionName, ref optionValue, out error);
2682 throw new SocketException (error);
2685 public byte [] GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int length)
2687 ThrowIfDisposedAndClosed ();
2690 byte[] byte_val = new byte [length];
2691 GetSocketOption_arr_internal (safe_handle, optionLevel, optionName, ref byte_val, out error);
2694 throw new SocketException (error);
2699 public object GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName)
2701 ThrowIfDisposedAndClosed ();
2705 GetSocketOption_obj_internal (safe_handle, optionLevel, optionName, out obj_val, out error);
2708 throw new SocketException (error);
2710 if (optionName == SocketOptionName.Linger)
2711 return (LingerOption) obj_val;
2712 else if (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)
2713 return (MulticastOption) obj_val;
2714 else if (obj_val is int)
2715 return (int) obj_val;
2720 static void GetSocketOption_arr_internal (SafeSocketHandle safeHandle, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val, out int error)
2722 bool release = false;
2724 safeHandle.DangerousAddRef (ref release);
2725 GetSocketOption_arr_internal (safeHandle.DangerousGetHandle (), level, name, ref byte_val, out error);
2728 safeHandle.DangerousRelease ();
2732 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2733 extern static void GetSocketOption_arr_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val, out int error);
2735 static void GetSocketOption_obj_internal (SafeSocketHandle safeHandle, SocketOptionLevel level, SocketOptionName name, out object obj_val, out int error)
2737 bool release = false;
2739 safeHandle.DangerousAddRef (ref release);
2740 GetSocketOption_obj_internal (safeHandle.DangerousGetHandle (), level, name, out obj_val, out error);
2743 safeHandle.DangerousRelease ();
2747 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2748 extern static void GetSocketOption_obj_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, out object obj_val, out int error);
2752 #region SetSocketOption
2754 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, byte [] optionValue)
2756 ThrowIfDisposedAndClosed ();
2758 // I'd throw an ArgumentNullException, but this is what MS does.
2759 if (optionValue == null)
2760 throw new SocketException ((int) SocketError.Fault, "Error trying to dereference an invalid pointer");
2763 SetSocketOption_internal (safe_handle, optionLevel, optionName, null, optionValue, 0, out error);
2766 if (error == (int) SocketError.InvalidArgument)
2767 throw new ArgumentException ();
2768 throw new SocketException (error);
2772 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, object optionValue)
2774 ThrowIfDisposedAndClosed ();
2776 // NOTE: if a null is passed, the byte[] overload is used instead...
2777 if (optionValue == null)
2778 throw new ArgumentNullException("optionValue");
2782 if (optionLevel == SocketOptionLevel.Socket && optionName == SocketOptionName.Linger) {
2783 LingerOption linger = optionValue as LingerOption;
2785 throw new ArgumentException ("A 'LingerOption' value must be specified.", "optionValue");
2786 SetSocketOption_internal (safe_handle, optionLevel, optionName, linger, null, 0, out error);
2787 } else if (optionLevel == SocketOptionLevel.IP && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
2788 MulticastOption multicast = optionValue as MulticastOption;
2789 if (multicast == null)
2790 throw new ArgumentException ("A 'MulticastOption' value must be specified.", "optionValue");
2791 SetSocketOption_internal (safe_handle, optionLevel, optionName, multicast, null, 0, out error);
2792 } else if (optionLevel == SocketOptionLevel.IPv6 && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
2793 IPv6MulticastOption multicast = optionValue as IPv6MulticastOption;
2794 if (multicast == null)
2795 throw new ArgumentException ("A 'IPv6MulticastOption' value must be specified.", "optionValue");
2796 SetSocketOption_internal (safe_handle, optionLevel, optionName, multicast, null, 0, out error);
2798 throw new ArgumentException ("Invalid value specified.", "optionValue");
2802 if (error == (int) SocketError.InvalidArgument)
2803 throw new ArgumentException ();
2804 throw new SocketException (error);
2808 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, bool optionValue)
2810 ThrowIfDisposedAndClosed ();
2813 int int_val = optionValue ? 1 : 0;
2814 SetSocketOption_internal (safe_handle, optionLevel, optionName, null, null, int_val, out error);
2817 if (error == (int) SocketError.InvalidArgument)
2818 throw new ArgumentException ();
2819 throw new SocketException (error);
2823 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int optionValue)
2825 ThrowIfDisposedAndClosed ();
2828 SetSocketOption_internal (safe_handle, optionLevel, optionName, null, null, optionValue, out error);
2831 if (error == (int) SocketError.InvalidArgument)
2832 throw new ArgumentException ();
2833 throw new SocketException (error);
2837 static void SetSocketOption_internal (SafeSocketHandle safeHandle, SocketOptionLevel level, SocketOptionName name, object obj_val, byte [] byte_val, int int_val, out int error)
2839 bool release = false;
2841 safeHandle.DangerousAddRef (ref release);
2842 SetSocketOption_internal (safeHandle.DangerousGetHandle (), level, name, obj_val, byte_val, int_val, out error);
2845 safeHandle.DangerousRelease ();
2849 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2850 extern static void SetSocketOption_internal (IntPtr socket, SocketOptionLevel level, SocketOptionName name, object obj_val, byte [] byte_val, int int_val, out int error);
2856 public int IOControl (int ioctl_code, byte [] in_value, byte [] out_value)
2859 throw new ObjectDisposedException (GetType ().ToString ());
2862 int result = IOControl_internal (safe_handle, ioctl_code, in_value, out_value, out error);
2865 throw new SocketException (error);
2867 throw new InvalidOperationException ("Must use Blocking property instead.");
2872 public int IOControl (IOControlCode ioControlCode, byte[] optionInValue, byte[] optionOutValue)
2874 return IOControl ((int) ioControlCode, optionInValue, optionOutValue);
2877 static int IOControl_internal (SafeSocketHandle safeHandle, int ioctl_code, byte [] input, byte [] output, out int error)
2879 bool release = false;
2881 safeHandle.DangerousAddRef (ref release);
2882 return IOControl_internal (safeHandle.DangerousGetHandle (), ioctl_code, input, output, out error);
2885 safeHandle.DangerousRelease ();
2889 /* See Socket.IOControl, WSAIoctl documentation in MSDN. The common options between UNIX
2890 * and Winsock are FIONREAD, FIONBIO and SIOCATMARK. Anything else will depend on the system
2891 * except SIO_KEEPALIVE_VALS which is properly handled on both windows and linux. */
2892 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2893 extern static int IOControl_internal (IntPtr sock, int ioctl_code, byte [] input, byte [] output, out int error);
2899 public void Close ()
2905 public void Close (int timeout)
2907 linger_timeout = timeout;
2911 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2912 internal extern static void Close_internal (IntPtr socket, out int error);
2918 public void Shutdown (SocketShutdown how)
2920 ThrowIfDisposedAndClosed ();
2923 throw new SocketException (10057); // Not connected
2926 Shutdown_internal (safe_handle, how, out error);
2929 throw new SocketException (error);
2932 static void Shutdown_internal (SafeSocketHandle safeHandle, SocketShutdown how, out int error)
2934 bool release = false;
2936 safeHandle.DangerousAddRef (ref release);
2937 Shutdown_internal (safeHandle.DangerousGetHandle (), how, out error);
2940 safeHandle.DangerousRelease ();
2944 [MethodImplAttribute (MethodImplOptions.InternalCall)]
2945 extern static void Shutdown_internal (IntPtr socket, SocketShutdown how, out int error);
2951 protected virtual void Dispose (bool disposing)
2957 bool was_connected = is_connected;
2958 is_connected = false;
2960 if (safe_handle != null) {
2967 safe_handle.Dispose ();
2971 public void Dispose ()
2974 GC.SuppressFinalize (this);
2977 void Linger (IntPtr handle)
2979 if (!is_connected || linger_timeout <= 0)
2982 /* We don't want to receive any more data */
2984 Shutdown_internal (handle, SocketShutdown.Receive, out error);
2989 int seconds = linger_timeout / 1000;
2990 int ms = linger_timeout % 1000;
2992 /* If the other end closes, this will return 'true' with 'Available' == 0 */
2993 Poll_internal (handle, SelectMode.SelectRead, ms * 1000, out error);
2999 LingerOption linger = new LingerOption (true, seconds);
3000 SetSocketOption_internal (handle, SocketOptionLevel.Socket, SocketOptionName.Linger, linger, null, 0, out error);
3001 /* Not needed, we're closing upon return */
3009 void ThrowIfDisposedAndClosed (Socket socket)
3011 if (socket.is_disposed && socket.is_closed)
3012 throw new ObjectDisposedException (socket.GetType ().ToString ());
3015 void ThrowIfDisposedAndClosed ()
3017 if (is_disposed && is_closed)
3018 throw new ObjectDisposedException (GetType ().ToString ());
3021 void ThrowIfBufferNull (byte[] buffer)
3024 throw new ArgumentNullException ("buffer");
3027 void ThrowIfBufferOutOfRange (byte[] buffer, int offset, int size)
3030 throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
3031 if (offset > buffer.Length)
3032 throw new ArgumentOutOfRangeException ("offset", "offset must be <= buffer.Length");
3034 throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
3035 if (size > buffer.Length - offset)
3036 throw new ArgumentOutOfRangeException ("size", "size must be <= buffer.Length - offset");
3041 #if !NET_2_1 || MOBILE
3042 if (protocol_type == ProtocolType.Udp)
3043 throw new SocketException ((int)SocketError.ProtocolOption);
3047 SocketAsyncResult ValidateEndIAsyncResult (IAsyncResult ares, string methodName, string argName)
3050 throw new ArgumentNullException (argName);
3052 SocketAsyncResult sockares = ares as SocketAsyncResult;
3053 if (sockares == null)
3054 throw new ArgumentException ("Invalid IAsyncResult", argName);
3055 if (Interlocked.CompareExchange (ref sockares.EndCalled, 1, 0) == 1)
3056 throw new InvalidOperationException (methodName + " can only be called once per asynchronous operation");
3061 void QueueSocketAsyncResult (Queue<SocketAsyncWorker> queue, SocketAsyncWorker worker, SocketAsyncResult sockares)
3065 queue.Enqueue (worker);
3066 count = queue.Count;
3070 socket_pool_queue (SocketAsyncWorker.Dispatcher, sockares);
3073 [StructLayout (LayoutKind.Sequential)]
3079 [MethodImplAttribute(MethodImplOptions.InternalCall)]
3080 internal static extern void cancel_blocking_socket_operation (Thread thread);
3082 [MethodImplAttribute(MethodImplOptions.InternalCall)]
3083 internal static extern void socket_pool_queue (SocketAsyncCallback d, SocketAsyncResult r);