1 // System.Net.Sockets.Socket.cs
4 // Phillip Pearson (pp@myelin.co.nz)
5 // Dick Porter <dick@ximian.com>
6 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 // Sridhar Kulkarni (sridharkulkarni@gmail.com)
8 // Brian Nickel (brian.nickel@gmail.com)
10 // Copyright (C) 2001, 2002 Phillip Pearson and Ximian, Inc.
11 // http://www.myelin.co.nz
12 // (c) 2004-2011 Novell, Inc. (http://www.novell.com)
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 using System
.Collections
;
38 using System
.Collections
.Generic
;
39 using System
.Runtime
.CompilerServices
;
40 using System
.Runtime
.InteropServices
;
41 using System
.Threading
;
42 using System
.Reflection
;
44 using System
.Net
.Configuration
;
47 using System
.Net
.NetworkInformation
;
49 namespace System
.Net
.Sockets
51 public partial class Socket
: IDisposable
53 private bool islistening
;
54 private bool useoverlappedIO
;
55 private const int SOCKET_CLOSED
= 10004;
57 private static readonly string timeout_exc_msg
= "A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond";
59 static void AddSockets (List
<Socket
> sockets
, IList list
, string name
)
62 foreach (Socket sock
in list
) {
63 if (sock
== null) // MS throws a NullRef
64 throw new ArgumentNullException ("name", "Contains a null element");
71 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
72 private extern static void Select_internal (ref Socket
[] sockets
,
75 public static void Select (IList checkRead
, IList checkWrite
, IList checkError
, int microSeconds
)
77 var list
= new List
<Socket
> ();
78 AddSockets (list
, checkRead
, "checkRead");
79 AddSockets (list
, checkWrite
, "checkWrite");
80 AddSockets (list
, checkError
, "checkError");
82 if (list
.Count
== 3) {
83 throw new ArgumentNullException ("checkRead, checkWrite, checkError",
84 "All the lists are null or empty.");
89 * The 'sockets' array contains: READ socket 0-n, null,
90 * WRITE socket 0-n, null,
91 * ERROR socket 0-n, null
93 Socket
[] sockets
= list
.ToArray ();
94 Select_internal (ref sockets
, microSeconds
, out error
);
97 throw new SocketException (error
);
99 if (sockets
== null) {
100 if (checkRead
!= null)
102 if (checkWrite
!= null)
104 if (checkError
!= null)
110 int count
= sockets
.Length
;
111 IList currentList
= checkRead
;
113 for (int i
= 0; i
< count
; i
++) {
114 Socket sock
= sockets
[i
];
115 if (sock
== null) { // separator
116 if (currentList
!= null) {
117 // Remove non-signaled sockets after the current one
118 int to_remove
= currentList
.Count
- currentIdx
;
119 for (int k
= 0; k
< to_remove
; k
++)
120 currentList
.RemoveAt (currentIdx
);
122 currentList
= (mode
== 0) ? checkWrite
: checkError
;
128 if (mode
== 1 && currentList
== checkWrite
&& !sock
.connected
) {
129 if ((int) sock
.GetSocketOption (SocketOptionLevel
.Socket
, SocketOptionName
.Error
) == 0)
130 sock
.connected
= true;
133 // Remove non-signaled sockets before the current one
134 //int max = currentList.Count;
135 while (((Socket
) currentList
[currentIdx
]) != sock
) {
136 currentList
.RemoveAt (currentIdx
);
142 // private constructor used by Accept, which already
143 // has a socket handle to use
144 internal Socket(AddressFamily family
, SocketType type
,
145 ProtocolType proto
, IntPtr sock
)
147 address_family
=family
;
155 private void SocketDefaults ()
158 if (address_family
== AddressFamily
.InterNetwork
/* Need to test IPv6 further ||
159 address_family == AddressFamily.InterNetworkV6 */) {
160 /* This is the default, but it
161 * probably has nasty side
162 * effects on Linux, as the
163 * socket option is kludged by
164 * turning on or off PMTU
167 this.DontFragment
= false;
171 // Microsoft sets these to 8192, but we are going to keep them
172 // both to the OS defaults as these have a big performance impact.
173 // on WebClient performance.
175 //this.ReceiveBufferSize = 8192;
176 //this.SendBufferSize = 8192;
177 } catch (SocketException
) {
182 public Socket (SocketInformation socketInformation
)
184 var options
= socketInformation
.Options
;
185 islistening
= (options
& SocketInformationOptions
.Listening
) != 0;
186 connected
= (options
& SocketInformationOptions
.Connected
) != 0;
187 blocking
= (options
& SocketInformationOptions
.NonBlocking
) == 0;
188 useoverlappedIO
= (options
& SocketInformationOptions
.UseOnlyOverlappedIO
) != 0;
190 var result
= Mono
.DataConverter
.Unpack ("iiiil", socketInformation
.ProtocolInformation
, 0);
192 address_family
= (AddressFamily
) (int) result
[0];
193 socket_type
= (SocketType
) (int) result
[1];
194 protocol_type
= (ProtocolType
) (int) result
[2];
195 isbound
= (ProtocolType
) (int) result
[3] != 0;
196 socket
= (IntPtr
) (long) result
[4];
201 // Returns the amount of data waiting to be read on socket
202 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
203 private extern static int Available_internal(IntPtr socket
, out int error
);
205 public int Available
{
207 if (disposed
&& closed
)
208 throw new ObjectDisposedException (GetType ().ToString ());
212 ret
= Available_internal(socket
, out error
);
215 throw new SocketException (error
);
222 public bool DontFragment
{
224 if (disposed
&& closed
) {
225 throw new ObjectDisposedException (GetType ().ToString ());
230 if (address_family
== AddressFamily
.InterNetwork
) {
231 dontfragment
= (int)(GetSocketOption (SocketOptionLevel
.IP
, SocketOptionName
.DontFragment
)) != 0;
232 } else if (address_family
== AddressFamily
.InterNetworkV6
) {
233 dontfragment
= (int)(GetSocketOption (SocketOptionLevel
.IPv6
, SocketOptionName
.DontFragment
)) != 0;
235 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
238 return(dontfragment
);
241 if (disposed
&& closed
) {
242 throw new ObjectDisposedException (GetType ().ToString ());
245 if (address_family
== AddressFamily
.InterNetwork
) {
246 SetSocketOption (SocketOptionLevel
.IP
, SocketOptionName
.DontFragment
, value?1:0);
247 } else if (address_family
== AddressFamily
.InterNetworkV6
) {
248 SetSocketOption (SocketOptionLevel
.IPv6
, SocketOptionName
.DontFragment
, value?1:0);
250 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
255 public bool EnableBroadcast
{
257 if (disposed
&& closed
) {
258 throw new ObjectDisposedException (GetType ().ToString ());
261 if (protocol_type
!= ProtocolType
.Udp
) {
262 throw new SocketException ((int)SocketError
.ProtocolOption
);
265 return((int)(GetSocketOption (SocketOptionLevel
.Socket
, SocketOptionName
.Broadcast
)) != 0);
268 if (disposed
&& closed
) {
269 throw new ObjectDisposedException (GetType ().ToString ());
272 if (protocol_type
!= ProtocolType
.Udp
) {
273 throw new SocketException ((int)SocketError
.ProtocolOption
);
276 SetSocketOption (SocketOptionLevel
.Socket
, SocketOptionName
.Broadcast
, value?1:0);
280 public bool ExclusiveAddressUse
{
282 if (disposed
&& closed
) {
283 throw new ObjectDisposedException (GetType ().ToString ());
286 return((int)(GetSocketOption (SocketOptionLevel
.Socket
, SocketOptionName
.ExclusiveAddressUse
)) != 0);
289 if (disposed
&& closed
) {
290 throw new ObjectDisposedException (GetType ().ToString ());
293 throw new InvalidOperationException ("Bind has already been called for this socket");
296 SetSocketOption (SocketOptionLevel
.Socket
, SocketOptionName
.ExclusiveAddressUse
, value?1:0);
300 public bool IsBound
{
306 public LingerOption LingerState
{
308 if (disposed
&& closed
) {
309 throw new ObjectDisposedException (GetType ().ToString ());
312 return((LingerOption
)GetSocketOption (SocketOptionLevel
.Socket
, SocketOptionName
.Linger
));
315 if (disposed
&& closed
) {
316 throw new ObjectDisposedException (GetType ().ToString ());
319 SetSocketOption (SocketOptionLevel
.Socket
,
320 SocketOptionName
.Linger
,
325 public bool MulticastLoopback
{
327 if (disposed
&& closed
) {
328 throw new ObjectDisposedException (GetType ().ToString ());
331 /* Even though this option can be set
332 * for TCP sockets on Linux, throw
333 * this exception anyway to be
334 * compatible (the MSDN docs say
335 * "Setting this property on a
336 * Transmission Control Protocol (TCP)
337 * socket will have no effect." but
338 * the MS runtime throws the
341 if (protocol_type
== ProtocolType
.Tcp
) {
342 throw new SocketException ((int)SocketError
.ProtocolOption
);
345 bool multicastloopback
;
347 if (address_family
== AddressFamily
.InterNetwork
) {
348 multicastloopback
= (int)(GetSocketOption (SocketOptionLevel
.IP
, SocketOptionName
.MulticastLoopback
)) != 0;
349 } else if (address_family
== AddressFamily
.InterNetworkV6
) {
350 multicastloopback
= (int)(GetSocketOption (SocketOptionLevel
.IPv6
, SocketOptionName
.MulticastLoopback
)) != 0;
352 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
355 return(multicastloopback
);
358 if (disposed
&& closed
) {
359 throw new ObjectDisposedException (GetType ().ToString ());
362 /* Even though this option can be set
363 * for TCP sockets on Linux, throw
364 * this exception anyway to be
365 * compatible (the MSDN docs say
366 * "Setting this property on a
367 * Transmission Control Protocol (TCP)
368 * socket will have no effect." but
369 * the MS runtime throws the
372 if (protocol_type
== ProtocolType
.Tcp
) {
373 throw new SocketException ((int)SocketError
.ProtocolOption
);
376 if (address_family
== AddressFamily
.InterNetwork
) {
377 SetSocketOption (SocketOptionLevel
.IP
, SocketOptionName
.MulticastLoopback
, value?1:0);
378 } else if (address_family
== AddressFamily
.InterNetworkV6
) {
379 SetSocketOption (SocketOptionLevel
.IPv6
, SocketOptionName
.MulticastLoopback
, value?1:0);
381 throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
387 [MonoTODO ("This doesn't do anything on Mono yet")]
388 public bool UseOnlyOverlappedIO
{
390 return(useoverlappedIO
);
393 useoverlappedIO
= value;
397 public IntPtr Handle
{
403 // Returns the local endpoint details in addr and port
404 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
405 private extern static SocketAddress
LocalEndPoint_internal(IntPtr socket
, int family
, out int error
);
407 // Wish: support non-IP endpoints.
408 public EndPoint LocalEndPoint
{
410 if (disposed
&& closed
)
411 throw new ObjectDisposedException (GetType ().ToString ());
414 * If the seed EndPoint is null, Connect, Bind,
415 * etc has not yet been called. MS returns null
418 if (seed_endpoint
== null)
424 sa
=LocalEndPoint_internal(socket
, (int) address_family
, out error
);
427 throw new SocketException (error
);
429 return seed_endpoint
.Create (sa
);
433 public SocketType SocketType
{
439 public int SendTimeout
{
441 if (disposed
&& closed
)
442 throw new ObjectDisposedException (GetType ().ToString ());
444 return (int)GetSocketOption(
445 SocketOptionLevel
.Socket
,
446 SocketOptionName
.SendTimeout
);
449 if (disposed
&& closed
)
450 throw new ObjectDisposedException (GetType ().ToString ());
453 throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than -1");
455 /* According to the MSDN docs we
456 * should adjust values between 1 and
457 * 499 to 500, but the MS runtime
464 SocketOptionLevel
.Socket
,
465 SocketOptionName
.SendTimeout
, value);
469 public int ReceiveTimeout
{
471 if (disposed
&& closed
)
472 throw new ObjectDisposedException (GetType ().ToString ());
474 return (int)GetSocketOption(
475 SocketOptionLevel
.Socket
,
476 SocketOptionName
.ReceiveTimeout
);
479 if (disposed
&& closed
)
480 throw new ObjectDisposedException (GetType ().ToString ());
483 throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than -1");
490 SocketOptionLevel
.Socket
,
491 SocketOptionName
.ReceiveTimeout
, value);
495 public bool AcceptAsync (SocketAsyncEventArgs e
)
497 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
499 if (disposed
&& closed
)
500 throw new ObjectDisposedException (GetType ().ToString ());
502 throw new InvalidOperationException ("You must call the Bind method before performing this operation.");
504 throw new InvalidOperationException ("You must call the Listen method before performing this operation.");
505 if (e
.BufferList
!= null)
506 throw new ArgumentException ("Multiple buffers cannot be used with this method.");
508 throw new ArgumentOutOfRangeException ("e.Count");
510 Socket acceptSocket
= e
.AcceptSocket
;
511 if (acceptSocket
!= null) {
512 if (acceptSocket
.IsBound
|| acceptSocket
.Connected
)
513 throw new InvalidOperationException ("AcceptSocket: The socket must not be bound or connected.");
518 w
.Init (this, e
, SocketOperation
.Accept
);
521 readQ
.Enqueue (e
.Worker
);
525 socket_pool_queue (Worker
.Dispatcher
, w
.result
);
528 // Creates a new system socket, returning the handle
529 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
530 private extern static IntPtr
Accept_internal(IntPtr sock
, out int error
, bool blocking
);
532 public Socket
Accept() {
533 if (disposed
&& closed
)
534 throw new ObjectDisposedException (GetType ().ToString ());
537 IntPtr sock
= (IntPtr
) (-1);
539 RegisterForBlockingSyscall ();
540 sock
= Accept_internal(socket
, out error
, blocking
);
542 UnRegisterForBlockingSyscall ();
547 error
= SOCKET_CLOSED
;
548 throw new SocketException(error
);
551 Socket accepted
= new Socket(this.AddressFamily
, this.SocketType
,
552 this.ProtocolType
, sock
);
554 accepted
.seed_endpoint
= this.seed_endpoint
;
555 accepted
.Blocking
= this.Blocking
;
559 internal void Accept (Socket acceptSocket
)
561 if (disposed
&& closed
)
562 throw new ObjectDisposedException (GetType ().ToString ());
565 IntPtr sock
= (IntPtr
)(-1);
568 RegisterForBlockingSyscall ();
569 sock
= Accept_internal (socket
, out error
, blocking
);
571 UnRegisterForBlockingSyscall ();
576 error
= SOCKET_CLOSED
;
577 throw new SocketException (error
);
580 acceptSocket
.address_family
= this.AddressFamily
;
581 acceptSocket
.socket_type
= this.SocketType
;
582 acceptSocket
.protocol_type
= this.ProtocolType
;
583 acceptSocket
.socket
= sock
;
584 acceptSocket
.connected
= true;
585 acceptSocket
.seed_endpoint
= this.seed_endpoint
;
586 acceptSocket
.Blocking
= this.Blocking
;
588 /* FIXME: figure out what if anything else
593 public IAsyncResult
BeginAccept(AsyncCallback callback
, object state
)
595 if (disposed
&& closed
)
596 throw new ObjectDisposedException (GetType ().ToString ());
598 if (!isbound
|| !islistening
)
599 throw new InvalidOperationException ();
601 SocketAsyncResult req
= new SocketAsyncResult (this, state
, callback
, SocketOperation
.Accept
);
604 readQ
.Enqueue (req
.Worker
);
608 socket_pool_queue (Worker
.Dispatcher
, req
);
612 public IAsyncResult
BeginAccept (int receiveSize
,
613 AsyncCallback callback
,
616 if (disposed
&& closed
)
617 throw new ObjectDisposedException (GetType ().ToString ());
620 throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
622 SocketAsyncResult req
= new SocketAsyncResult (this, state
, callback
, SocketOperation
.AcceptReceive
);
623 req
.Buffer
= new byte[receiveSize
];
625 req
.Size
= receiveSize
;
626 req
.SockFlags
= SocketFlags
.None
;
629 readQ
.Enqueue (req
.Worker
);
633 socket_pool_queue (Worker
.Dispatcher
, req
);
637 public IAsyncResult
BeginAccept (Socket acceptSocket
,
639 AsyncCallback callback
,
642 if (disposed
&& closed
)
643 throw new ObjectDisposedException (GetType ().ToString ());
646 throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
648 if (acceptSocket
!= null) {
649 if (acceptSocket
.disposed
&& acceptSocket
.closed
)
650 throw new ObjectDisposedException (acceptSocket
.GetType ().ToString ());
652 if (acceptSocket
.IsBound
)
653 throw new InvalidOperationException ();
655 /* For some reason the MS runtime
656 * barfs if the new socket is not TCP,
657 * even though it's just about to blow
658 * away all those parameters
660 if (acceptSocket
.ProtocolType
!= ProtocolType
.Tcp
)
661 throw new SocketException ((int)SocketError
.InvalidArgument
);
664 SocketAsyncResult req
= new SocketAsyncResult (this, state
, callback
, SocketOperation
.AcceptReceive
);
665 req
.Buffer
= new byte[receiveSize
];
667 req
.Size
= receiveSize
;
668 req
.SockFlags
= SocketFlags
.None
;
669 req
.AcceptSocket
= acceptSocket
;
672 readQ
.Enqueue (req
.Worker
);
676 socket_pool_queue (Worker
.Dispatcher
, req
);
680 public IAsyncResult
BeginConnect (IPAddress address
, int port
,
681 AsyncCallback callback
,
684 if (disposed
&& closed
)
685 throw new ObjectDisposedException (GetType ().ToString ());
688 throw new ArgumentNullException ("address");
690 if (address
.ToString ().Length
== 0)
691 throw new ArgumentException ("The length of the IP address is zero");
693 if (port
<= 0 || port
> 65535)
694 throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
697 throw new InvalidOperationException ();
699 IPEndPoint iep
= new IPEndPoint (address
, port
);
700 return(BeginConnect (iep
, callback
, state
));
703 public IAsyncResult
BeginConnect (string host
, int port
,
704 AsyncCallback callback
,
707 if (disposed
&& closed
)
708 throw new ObjectDisposedException (GetType ().ToString ());
711 throw new ArgumentNullException ("host");
713 if (address_family
!= AddressFamily
.InterNetwork
&&
714 address_family
!= AddressFamily
.InterNetworkV6
)
715 throw new NotSupportedException ("This method is valid only for sockets in the InterNetwork and InterNetworkV6 families");
717 if (port
<= 0 || port
> 65535)
718 throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
721 throw new InvalidOperationException ();
723 return BeginConnect (Dns
.GetHostAddresses (host
), port
, callback
, state
);
726 public IAsyncResult
BeginDisconnect (bool reuseSocket
,
727 AsyncCallback callback
,
730 if (disposed
&& closed
)
731 throw new ObjectDisposedException (GetType ().ToString ());
733 SocketAsyncResult req
= new SocketAsyncResult (this, state
, callback
, SocketOperation
.Disconnect
);
734 req
.ReuseSocket
= reuseSocket
;
735 socket_pool_queue (Worker
.Dispatcher
, req
);
739 void CheckRange (byte[] buffer
, int offset
, int size
)
742 throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
744 if (offset
> buffer
.Length
)
745 throw new ArgumentOutOfRangeException ("offset", "offset must be <= buffer.Length");
748 throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
750 if (size
> buffer
.Length
- offset
)
751 throw new ArgumentOutOfRangeException ("size", "size must be <= buffer.Length - offset");
754 public IAsyncResult
BeginReceive(byte[] buffer
, int offset
,
756 SocketFlags socket_flags
,
757 AsyncCallback callback
,
760 if (disposed
&& closed
)
761 throw new ObjectDisposedException (GetType ().ToString ());
764 throw new ArgumentNullException ("buffer");
766 CheckRange (buffer
, offset
, size
);
768 SocketAsyncResult req
= new SocketAsyncResult (this, state
, callback
, SocketOperation
.Receive
);
772 req
.SockFlags
= socket_flags
;
775 readQ
.Enqueue (req
.Worker
);
779 socket_pool_queue (Worker
.Dispatcher
, req
);
783 public IAsyncResult
BeginReceive (byte[] buffer
, int offset
,
784 int size
, SocketFlags flags
,
785 out SocketError error
,
786 AsyncCallback callback
,
789 /* As far as I can tell from the docs and from
790 * experimentation, a pointer to the
791 * SocketError parameter is not supposed to be
792 * saved for the async parts. And as we don't
793 * set any socket errors in the setup code, we
794 * just have to set it to Success.
796 error
= SocketError
.Success
;
797 return (BeginReceive (buffer
, offset
, size
, flags
, callback
, state
));
800 [CLSCompliant (false)]
801 public IAsyncResult
BeginReceive (IList
<ArraySegment
<byte>> buffers
,
802 SocketFlags socketFlags
,
803 AsyncCallback callback
,
806 if (disposed
&& closed
)
807 throw new ObjectDisposedException (GetType ().ToString ());
810 throw new ArgumentNullException ("buffers");
812 SocketAsyncResult req
= new SocketAsyncResult (this, state
, callback
, SocketOperation
.ReceiveGeneric
);
813 req
.Buffers
= buffers
;
814 req
.SockFlags
= socketFlags
;
817 readQ
.Enqueue (req
.Worker
);
821 socket_pool_queue (Worker
.Dispatcher
, req
);
825 [CLSCompliant (false)]
826 public IAsyncResult
BeginReceive (IList
<ArraySegment
<byte>> buffers
,
827 SocketFlags socketFlags
,
828 out SocketError errorCode
,
829 AsyncCallback callback
,
832 /* I assume the same SocketError semantics as
835 errorCode
= SocketError
.Success
;
836 return (BeginReceive (buffers
, socketFlags
, callback
, state
));
839 public IAsyncResult
BeginReceiveFrom(byte[] buffer
, int offset
,
841 SocketFlags socket_flags
,
842 ref EndPoint remote_end
,
843 AsyncCallback callback
,
845 if (disposed
&& closed
)
846 throw new ObjectDisposedException (GetType ().ToString ());
849 throw new ArgumentNullException ("buffer");
851 if (remote_end
== null)
852 throw new ArgumentNullException ("remote_end");
854 CheckRange (buffer
, offset
, size
);
856 SocketAsyncResult req
= new SocketAsyncResult (this, state
, callback
, SocketOperation
.ReceiveFrom
);
860 req
.SockFlags
= socket_flags
;
861 req
.EndPoint
= remote_end
;
864 readQ
.Enqueue (req
.Worker
);
868 socket_pool_queue (Worker
.Dispatcher
, req
);
873 public IAsyncResult
BeginReceiveMessageFrom (
874 byte[] buffer
, int offset
, int size
,
875 SocketFlags socketFlags
, ref EndPoint remoteEP
,
876 AsyncCallback callback
, object state
)
878 if (disposed
&& closed
)
879 throw new ObjectDisposedException (GetType ().ToString ());
882 throw new ArgumentNullException ("buffer");
884 if (remoteEP
== null)
885 throw new ArgumentNullException ("remoteEP");
887 CheckRange (buffer
, offset
, size
);
889 throw new NotImplementedException ();
892 public IAsyncResult
BeginSend (byte[] buffer
, int offset
, int size
, SocketFlags socket_flags
,
893 AsyncCallback callback
, object state
)
895 if (disposed
&& closed
)
896 throw new ObjectDisposedException (GetType ().ToString ());
899 throw new ArgumentNullException ("buffer");
901 CheckRange (buffer
, offset
, size
);
904 throw new SocketException ((int)SocketError
.NotConnected
);
906 SocketAsyncResult req
= new SocketAsyncResult (this, state
, callback
, SocketOperation
.Send
);
910 req
.SockFlags
= socket_flags
;
913 writeQ
.Enqueue (req
.Worker
);
914 count
= writeQ
.Count
;
917 socket_pool_queue (Worker
.Dispatcher
, req
);
921 public IAsyncResult
BeginSend (byte[] buffer
, int offset
,
923 SocketFlags socketFlags
,
924 out SocketError errorCode
,
925 AsyncCallback callback
,
929 errorCode
= SocketError
.NotConnected
;
930 throw new SocketException ((int)errorCode
);
933 errorCode
= SocketError
.Success
;
935 return (BeginSend (buffer
, offset
, size
, socketFlags
, callback
,
939 public IAsyncResult
BeginSend (IList
<ArraySegment
<byte>> buffers
,
940 SocketFlags socketFlags
,
941 AsyncCallback callback
,
944 if (disposed
&& closed
)
945 throw new ObjectDisposedException (GetType ().ToString ());
948 throw new ArgumentNullException ("buffers");
951 throw new SocketException ((int)SocketError
.NotConnected
);
953 SocketAsyncResult req
= new SocketAsyncResult (this, state
, callback
, SocketOperation
.SendGeneric
);
954 req
.Buffers
= buffers
;
955 req
.SockFlags
= socketFlags
;
958 writeQ
.Enqueue (req
.Worker
);
959 count
= writeQ
.Count
;
962 socket_pool_queue (Worker
.Dispatcher
, req
);
966 [CLSCompliant (false)]
967 public IAsyncResult
BeginSend (IList
<ArraySegment
<byte>> buffers
,
968 SocketFlags socketFlags
,
969 out SocketError errorCode
,
970 AsyncCallback callback
,
974 errorCode
= SocketError
.NotConnected
;
975 throw new SocketException ((int)errorCode
);
978 errorCode
= SocketError
.Success
;
979 return (BeginSend (buffers
, socketFlags
, callback
, state
));
982 delegate void SendFileHandler (string fileName
, byte [] preBuffer
, byte [] postBuffer
, TransmitFileOptions flags
);
984 sealed class SendFileAsyncResult
: IAsyncResult
{
988 public SendFileAsyncResult (SendFileHandler d
, IAsyncResult ares
)
994 public object AsyncState
{
995 get { return ares.AsyncState; }
998 public WaitHandle AsyncWaitHandle
{
999 get { return ares.AsyncWaitHandle; }
1002 public bool CompletedSynchronously
{
1003 get { return ares.CompletedSynchronously; }
1006 public bool IsCompleted
{
1007 get { return ares.IsCompleted; }
1010 public SendFileHandler Delegate
{
1014 public IAsyncResult Original
{
1015 get { return ares; }
1019 public IAsyncResult
BeginSendFile (string fileName
,
1020 AsyncCallback callback
,
1023 if (disposed
&& closed
)
1024 throw new ObjectDisposedException (GetType ().ToString ());
1027 throw new NotSupportedException ();
1029 if (!File
.Exists (fileName
))
1030 throw new FileNotFoundException ();
1032 return BeginSendFile (fileName
, null, null, 0, callback
, state
);
1035 public IAsyncResult
BeginSendFile (string fileName
,
1038 TransmitFileOptions flags
,
1039 AsyncCallback callback
,
1042 if (disposed
&& closed
)
1043 throw new ObjectDisposedException (GetType ().ToString ());
1046 throw new NotSupportedException ();
1048 if (!File
.Exists (fileName
))
1049 throw new FileNotFoundException ();
1051 SendFileHandler d
= new SendFileHandler (SendFile
);
1052 return new SendFileAsyncResult (d
, d
.BeginInvoke (fileName
, preBuffer
, postBuffer
, flags
, ar
=> {
1053 SendFileAsyncResult sfar
= new SendFileAsyncResult (d
, ar
);
1058 public IAsyncResult
BeginSendTo(byte[] buffer
, int offset
,
1060 SocketFlags socket_flags
,
1061 EndPoint remote_end
,
1062 AsyncCallback callback
,
1064 if (disposed
&& closed
)
1065 throw new ObjectDisposedException (GetType ().ToString ());
1068 throw new ArgumentNullException ("buffer");
1070 CheckRange (buffer
, offset
, size
);
1072 SocketAsyncResult req
= new SocketAsyncResult (this, state
, callback
, SocketOperation
.SendTo
);
1073 req
.Buffer
= buffer
;
1074 req
.Offset
= offset
;
1076 req
.SockFlags
= socket_flags
;
1077 req
.EndPoint
= remote_end
;
1080 writeQ
.Enqueue (req
.Worker
);
1081 count
= writeQ
.Count
;
1084 socket_pool_queue (Worker
.Dispatcher
, req
);
1088 // Creates a new system socket, returning the handle
1089 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
1090 private extern static void Bind_internal(IntPtr sock
,
1094 public void Bind(EndPoint local_end
) {
1095 if (disposed
&& closed
)
1096 throw new ObjectDisposedException (GetType ().ToString ());
1098 if (local_end
== null)
1099 throw new ArgumentNullException("local_end");
1103 Bind_internal(socket
, local_end
.Serialize(), out error
);
1105 throw new SocketException (error
);
1109 seed_endpoint
= local_end
;
1112 public void Connect (IPAddress address
, int port
)
1114 Connect (new IPEndPoint (address
, port
));
1117 public void Connect (IPAddress
[] addresses
, int port
)
1119 if (disposed
&& closed
)
1120 throw new ObjectDisposedException (GetType ().ToString ());
1122 if (addresses
== null)
1123 throw new ArgumentNullException ("addresses");
1125 if (this.AddressFamily
!= AddressFamily
.InterNetwork
&&
1126 this.AddressFamily
!= AddressFamily
.InterNetworkV6
)
1127 throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
1130 throw new InvalidOperationException ();
1132 /* FIXME: do non-blocking sockets Poll here? */
1134 foreach (IPAddress address
in addresses
) {
1135 IPEndPoint iep
= new IPEndPoint (address
, port
);
1136 SocketAddress serial
= iep
.Serialize ();
1138 Connect_internal (socket
, serial
, out error
);
1142 seed_endpoint
= iep
;
1144 } else if (error
!= (int)SocketError
.InProgress
&&
1145 error
!= (int)SocketError
.WouldBlock
) {
1150 Poll (-1, SelectMode
.SelectWrite
);
1151 error
= (int)GetSocketOption (SocketOptionLevel
.Socket
, SocketOptionName
.Error
);
1155 seed_endpoint
= iep
;
1161 throw new SocketException (error
);
1164 public void Connect (string host
, int port
)
1166 IPAddress
[] addresses
= Dns
.GetHostAddresses (host
);
1167 Connect (addresses
, port
);
1170 public bool DisconnectAsync (SocketAsyncEventArgs e
)
1172 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1173 if (disposed
&& closed
)
1174 throw new ObjectDisposedException (GetType ().ToString ());
1177 e
.Worker
.Init (this, e
, SocketOperation
.Disconnect
);
1178 socket_pool_queue (Worker
.Dispatcher
, e
.Worker
.result
);
1182 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
1183 extern static void Disconnect_internal(IntPtr sock
, bool reuse
, out int error
);
1185 /* According to the docs, the MS runtime will throw
1186 * PlatformNotSupportedException if the platform is
1187 * newer than w2k. We should be able to cope...
1189 public void Disconnect (bool reuseSocket
)
1191 if (disposed
&& closed
)
1192 throw new ObjectDisposedException (GetType ().ToString ());
1196 Disconnect_internal (socket
, reuseSocket
, out error
);
1200 /* ERROR_NOT_SUPPORTED */
1201 throw new PlatformNotSupportedException ();
1203 throw new SocketException (error
);
1210 /* Do managed housekeeping here... */
1215 [MonoLimitation ("We do not support passing sockets across processes, we merely allow this API to pass the socket across AppDomains")]
1216 public SocketInformation
DuplicateAndClose (int targetProcessId
)
1218 var si
= new SocketInformation ();
1220 (islistening
? SocketInformationOptions
.Listening
: 0) |
1221 (connected
? SocketInformationOptions
.Connected
: 0) |
1222 (blocking
? 0 : SocketInformationOptions
.NonBlocking
) |
1223 (useoverlappedIO
? SocketInformationOptions
.UseOnlyOverlappedIO
: 0);
1225 si
.ProtocolInformation
= Mono
.DataConverter
.Pack ("iiiil", (int)address_family
, (int)socket_type
, (int)protocol_type
, isbound
? 1 : 0, (long)socket
);
1226 socket
= (IntPtr
) (-1);
1232 public Socket
EndAccept (IAsyncResult result
)
1237 return(EndAccept (out buffer
, out bytes
, result
));
1240 public Socket
EndAccept (out byte[] buffer
, IAsyncResult asyncResult
)
1243 return(EndAccept (out buffer
, out bytes
, asyncResult
));
1246 public Socket
EndAccept (out byte[] buffer
, out int bytesTransferred
, IAsyncResult asyncResult
)
1248 if (disposed
&& closed
)
1249 throw new ObjectDisposedException (GetType ().ToString ());
1251 if (asyncResult
== null)
1252 throw new ArgumentNullException ("asyncResult");
1254 SocketAsyncResult req
= asyncResult
as SocketAsyncResult
;
1256 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
1258 if (Interlocked
.CompareExchange (ref req
.EndCalled
, 1, 0) == 1)
1259 throw InvalidAsyncOp ("EndAccept");
1260 if (!asyncResult
.IsCompleted
)
1261 asyncResult
.AsyncWaitHandle
.WaitOne ();
1263 req
.CheckIfThrowDelayedException ();
1265 buffer
= req
.Buffer
;
1266 bytesTransferred
= req
.Total
;
1271 public void EndConnect (IAsyncResult result
)
1273 if (disposed
&& closed
)
1274 throw new ObjectDisposedException (GetType ().ToString ());
1277 throw new ArgumentNullException ("result");
1279 SocketAsyncResult req
= result
as SocketAsyncResult
;
1281 throw new ArgumentException ("Invalid IAsyncResult", "result");
1283 if (Interlocked
.CompareExchange (ref req
.EndCalled
, 1, 0) == 1)
1284 throw InvalidAsyncOp ("EndConnect");
1285 if (!result
.IsCompleted
)
1286 result
.AsyncWaitHandle
.WaitOne();
1288 req
.CheckIfThrowDelayedException();
1291 public void EndDisconnect (IAsyncResult asyncResult
)
1293 if (disposed
&& closed
)
1294 throw new ObjectDisposedException (GetType ().ToString ());
1296 if (asyncResult
== null)
1297 throw new ArgumentNullException ("asyncResult");
1299 SocketAsyncResult req
= asyncResult
as SocketAsyncResult
;
1301 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
1303 if (Interlocked
.CompareExchange (ref req
.EndCalled
, 1, 0) == 1)
1304 throw InvalidAsyncOp ("EndDisconnect");
1305 if (!asyncResult
.IsCompleted
)
1306 asyncResult
.AsyncWaitHandle
.WaitOne ();
1308 req
.CheckIfThrowDelayedException ();
1312 public int EndReceiveMessageFrom (IAsyncResult asyncResult
,
1313 ref SocketFlags socketFlags
,
1314 ref EndPoint endPoint
,
1315 out IPPacketInformation ipPacketInformation
)
1317 if (disposed
&& closed
)
1318 throw new ObjectDisposedException (GetType ().ToString ());
1320 if (asyncResult
== null)
1321 throw new ArgumentNullException ("asyncResult");
1323 if (endPoint
== null)
1324 throw new ArgumentNullException ("endPoint");
1326 SocketAsyncResult req
= asyncResult
as SocketAsyncResult
;
1328 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
1330 if (Interlocked
.CompareExchange (ref req
.EndCalled
, 1, 0) == 1)
1331 throw InvalidAsyncOp ("EndReceiveMessageFrom");
1332 throw new NotImplementedException ();
1335 public void EndSendFile (IAsyncResult asyncResult
)
1337 if (disposed
&& closed
)
1338 throw new ObjectDisposedException (GetType ().ToString ());
1340 if (asyncResult
== null)
1341 throw new ArgumentNullException ("asyncResult");
1343 SendFileAsyncResult ares
= asyncResult
as SendFileAsyncResult
;
1345 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
1347 ares
.Delegate
.EndInvoke (ares
.Original
);
1350 public int EndSendTo (IAsyncResult result
)
1352 if (disposed
&& closed
)
1353 throw new ObjectDisposedException (GetType ().ToString ());
1356 throw new ArgumentNullException ("result");
1358 SocketAsyncResult req
= result
as SocketAsyncResult
;
1360 throw new ArgumentException ("Invalid IAsyncResult", "result");
1362 if (Interlocked
.CompareExchange (ref req
.EndCalled
, 1, 0) == 1)
1363 throw InvalidAsyncOp ("EndSendTo");
1364 if (!result
.IsCompleted
)
1365 result
.AsyncWaitHandle
.WaitOne();
1367 req
.CheckIfThrowDelayedException();
1371 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
1372 private extern static void GetSocketOption_arr_internal(IntPtr socket
,
1373 SocketOptionLevel level
, SocketOptionName name
, ref byte[] byte_val
,
1376 public void GetSocketOption (SocketOptionLevel optionLevel
, SocketOptionName optionName
, byte [] optionValue
)
1378 if (disposed
&& closed
)
1379 throw new ObjectDisposedException (GetType ().ToString ());
1381 if (optionValue
== null)
1382 throw new SocketException ((int) SocketError
.Fault
,
1383 "Error trying to dereference an invalid pointer");
1387 GetSocketOption_arr_internal (socket
, optionLevel
, optionName
, ref optionValue
,
1390 throw new SocketException (error
);
1393 public byte [] GetSocketOption (SocketOptionLevel optionLevel
, SocketOptionName optionName
, int length
)
1395 if (disposed
&& closed
)
1396 throw new ObjectDisposedException (GetType ().ToString ());
1398 byte[] byte_val
=new byte[length
];
1401 GetSocketOption_arr_internal (socket
, optionLevel
, optionName
, ref byte_val
,
1404 throw new SocketException (error
);
1409 // See Socket.IOControl, WSAIoctl documentation in MSDN. The
1410 // common options between UNIX and Winsock are FIONREAD,
1411 // FIONBIO and SIOCATMARK. Anything else will depend on the
1412 // system except SIO_KEEPALIVE_VALS which is properly handled
1413 // on both windows and linux.
1414 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
1415 extern static int WSAIoctl (IntPtr sock
, int ioctl_code
, byte [] input
,
1416 byte [] output
, out int error
);
1418 public int IOControl (int ioctl_code
, byte [] in_value
, byte [] out_value
)
1421 throw new ObjectDisposedException (GetType ().ToString ());
1424 int result
= WSAIoctl (socket
, ioctl_code
, in_value
, out_value
,
1428 throw new SocketException (error
);
1431 throw new InvalidOperationException ("Must use Blocking property instead.");
1436 public int IOControl (IOControlCode ioControlCode
, byte[] optionInValue
, byte[] optionOutValue
)
1438 return IOControl ((int) ioControlCode
, optionInValue
, optionOutValue
);
1441 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
1442 private extern static void Listen_internal(IntPtr sock
, int backlog
, out int error
);
1444 public void Listen (int backlog
)
1446 if (disposed
&& closed
)
1447 throw new ObjectDisposedException (GetType ().ToString ());
1450 throw new SocketException ((int)SocketError
.InvalidArgument
);
1453 Listen_internal(socket
, backlog
, out error
);
1456 throw new SocketException (error
);
1461 public bool Poll (int time_us
, SelectMode mode
)
1463 if (disposed
&& closed
)
1464 throw new ObjectDisposedException (GetType ().ToString ());
1466 if (mode
!= SelectMode
.SelectRead
&&
1467 mode
!= SelectMode
.SelectWrite
&&
1468 mode
!= SelectMode
.SelectError
)
1469 throw new NotSupportedException ("'mode' parameter is not valid.");
1472 bool result
= Poll_internal (socket
, mode
, time_us
, out error
);
1474 throw new SocketException (error
);
1476 if (mode
== SelectMode
.SelectWrite
&& result
&& !connected
) {
1477 /* Update the connected state; for
1478 * non-blocking Connect()s this is
1479 * when we can find out that the
1480 * connect succeeded.
1482 if ((int)GetSocketOption (SocketOptionLevel
.Socket
, SocketOptionName
.Error
) == 0) {
1490 public int Receive (byte [] buffer
)
1492 return Receive (buffer
, SocketFlags
.None
);
1495 public int Receive (byte [] buffer
, SocketFlags flags
)
1497 if (disposed
&& closed
)
1498 throw new ObjectDisposedException (GetType ().ToString ());
1501 throw new ArgumentNullException ("buffer");
1505 int ret
= Receive_nochecks (buffer
, 0, buffer
.Length
, flags
, out error
);
1507 if (error
!= SocketError
.Success
) {
1508 if (error
== SocketError
.WouldBlock
&& blocking
) // This might happen when ReceiveTimeout is set
1509 throw new SocketException ((int) error
, timeout_exc_msg
);
1510 throw new SocketException ((int) error
);
1516 public int Receive (byte [] buffer
, int size
, SocketFlags flags
)
1518 if (disposed
&& closed
)
1519 throw new ObjectDisposedException (GetType ().ToString ());
1522 throw new ArgumentNullException ("buffer");
1524 CheckRange (buffer
, 0, size
);
1528 int ret
= Receive_nochecks (buffer
, 0, size
, flags
, out error
);
1530 if (error
!= SocketError
.Success
) {
1531 if (error
== SocketError
.WouldBlock
&& blocking
) // This might happen when ReceiveTimeout is set
1532 throw new SocketException ((int) error
, timeout_exc_msg
);
1533 throw new SocketException ((int) error
);
1539 public int Receive (byte [] buffer
, int offset
, int size
, SocketFlags flags
)
1541 if (disposed
&& closed
)
1542 throw new ObjectDisposedException (GetType ().ToString ());
1545 throw new ArgumentNullException ("buffer");
1547 CheckRange (buffer
, offset
, size
);
1551 int ret
= Receive_nochecks (buffer
, offset
, size
, flags
, out error
);
1553 if (error
!= SocketError
.Success
) {
1554 if (error
== SocketError
.WouldBlock
&& blocking
) // This might happen when ReceiveTimeout is set
1555 throw new SocketException ((int) error
, timeout_exc_msg
);
1556 throw new SocketException ((int) error
);
1562 public int Receive (byte [] buffer
, int offset
, int size
, SocketFlags flags
, out SocketError error
)
1564 if (disposed
&& closed
)
1565 throw new ObjectDisposedException (GetType ().ToString ());
1568 throw new ArgumentNullException ("buffer");
1570 CheckRange (buffer
, offset
, size
);
1572 return Receive_nochecks (buffer
, offset
, size
, flags
, out error
);
1575 public bool ReceiveFromAsync (SocketAsyncEventArgs e
)
1577 if (disposed
&& closed
)
1578 throw new ObjectDisposedException (GetType ().ToString ());
1580 // We do not support recv into multiple buffers yet
1581 if (e
.BufferList
!= null)
1582 throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
1583 if (e
.RemoteEndPoint
== null)
1584 throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
1587 e
.Worker
.Init (this, e
, SocketOperation
.ReceiveFrom
);
1588 SocketAsyncResult res
= e
.Worker
.result
;
1589 res
.Buffer
= e
.Buffer
;
1590 res
.Offset
= e
.Offset
;
1592 res
.EndPoint
= e
.RemoteEndPoint
;
1593 res
.SockFlags
= e
.SocketFlags
;
1596 readQ
.Enqueue (e
.Worker
);
1597 count
= readQ
.Count
;
1600 socket_pool_queue (Worker
.Dispatcher
, res
);
1604 public int ReceiveFrom (byte [] buffer
, ref EndPoint remoteEP
)
1606 if (disposed
&& closed
)
1607 throw new ObjectDisposedException (GetType ().ToString ());
1610 throw new ArgumentNullException ("buffer");
1612 if (remoteEP
== null)
1613 throw new ArgumentNullException ("remoteEP");
1615 return ReceiveFrom_nochecks (buffer
, 0, buffer
.Length
, SocketFlags
.None
, ref remoteEP
);
1618 public int ReceiveFrom (byte [] buffer
, SocketFlags flags
, ref EndPoint remoteEP
)
1620 if (disposed
&& closed
)
1621 throw new ObjectDisposedException (GetType ().ToString ());
1624 throw new ArgumentNullException ("buffer");
1626 if (remoteEP
== null)
1627 throw new ArgumentNullException ("remoteEP");
1629 return ReceiveFrom_nochecks (buffer
, 0, buffer
.Length
, flags
, ref remoteEP
);
1632 public int ReceiveFrom (byte [] buffer
, int size
, SocketFlags flags
,
1633 ref EndPoint remoteEP
)
1635 if (disposed
&& closed
)
1636 throw new ObjectDisposedException (GetType ().ToString ());
1639 throw new ArgumentNullException ("buffer");
1641 if (remoteEP
== null)
1642 throw new ArgumentNullException ("remoteEP");
1644 if (size
< 0 || size
> buffer
.Length
)
1645 throw new ArgumentOutOfRangeException ("size");
1647 return ReceiveFrom_nochecks (buffer
, 0, size
, flags
, ref remoteEP
);
1650 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
1651 private extern static int RecvFrom_internal(IntPtr sock
,
1656 ref SocketAddress sockaddr
,
1659 public int ReceiveFrom (byte [] buffer
, int offset
, int size
, SocketFlags flags
,
1660 ref EndPoint remoteEP
)
1662 if (disposed
&& closed
)
1663 throw new ObjectDisposedException (GetType ().ToString ());
1666 throw new ArgumentNullException ("buffer");
1668 if (remoteEP
== null)
1669 throw new ArgumentNullException ("remoteEP");
1671 CheckRange (buffer
, offset
, size
);
1673 return ReceiveFrom_nochecks (buffer
, offset
, size
, flags
, ref remoteEP
);
1676 internal int ReceiveFrom_nochecks (byte [] buf
, int offset
, int size
, SocketFlags flags
,
1677 ref EndPoint remote_end
)
1680 return ReceiveFrom_nochecks_exc (buf
, offset
, size
, flags
, ref remote_end
, true, out error
);
1683 internal int ReceiveFrom_nochecks_exc (byte [] buf
, int offset
, int size
, SocketFlags flags
,
1684 ref EndPoint remote_end
, bool throwOnError
, out int error
)
1686 SocketAddress sockaddr
= remote_end
.Serialize();
1687 int cnt
= RecvFrom_internal (socket
, buf
, offset
, size
, flags
, ref sockaddr
, out error
);
1688 SocketError err
= (SocketError
) error
;
1690 if (err
!= SocketError
.WouldBlock
&& err
!= SocketError
.InProgress
)
1692 else if (err
== SocketError
.WouldBlock
&& blocking
) { // This might happen when ReceiveTimeout is set
1694 throw new SocketException ((int) SocketError
.TimedOut
, timeout_exc_msg
);
1695 error
= (int) SocketError
.TimedOut
;
1700 throw new SocketException (error
);
1707 // If sockaddr is null then we're a connection
1708 // oriented protocol and should ignore the
1709 // remote_end parameter (see MSDN
1710 // documentation for Socket.ReceiveFrom(...) )
1712 if ( sockaddr
!= null ) {
1713 // Stupidly, EndPoint.Create() is an
1715 remote_end
= remote_end
.Create (sockaddr
);
1718 seed_endpoint
= remote_end
;
1723 [MonoTODO ("Not implemented")]
1724 public bool ReceiveMessageFromAsync (SocketAsyncEventArgs e
)
1726 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1727 if (disposed
&& closed
)
1728 throw new ObjectDisposedException (GetType ().ToString ());
1730 throw new NotImplementedException ();
1733 [MonoTODO ("Not implemented")]
1734 public int ReceiveMessageFrom (byte[] buffer
, int offset
,
1736 ref SocketFlags socketFlags
,
1737 ref EndPoint remoteEP
,
1738 out IPPacketInformation ipPacketInformation
)
1740 if (disposed
&& closed
)
1741 throw new ObjectDisposedException (GetType ().ToString ());
1744 throw new ArgumentNullException ("buffer");
1746 if (remoteEP
== null)
1747 throw new ArgumentNullException ("remoteEP");
1749 CheckRange (buffer
, offset
, size
);
1751 /* FIXME: figure out how we get hold of the
1752 * IPPacketInformation
1754 throw new NotImplementedException ();
1757 [MonoTODO ("Not implemented")]
1758 public bool SendPacketsAsync (SocketAsyncEventArgs e
)
1760 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1762 if (disposed
&& closed
)
1763 throw new ObjectDisposedException (GetType ().ToString ());
1765 throw new NotImplementedException ();
1768 public int Send (byte [] buf
)
1770 if (disposed
&& closed
)
1771 throw new ObjectDisposedException (GetType ().ToString ());
1774 throw new ArgumentNullException ("buf");
1778 int ret
= Send_nochecks (buf
, 0, buf
.Length
, SocketFlags
.None
, out error
);
1780 if (error
!= SocketError
.Success
)
1781 throw new SocketException ((int) error
);
1786 public int Send (byte [] buf
, SocketFlags flags
)
1788 if (disposed
&& closed
)
1789 throw new ObjectDisposedException (GetType ().ToString ());
1792 throw new ArgumentNullException ("buf");
1796 int ret
= Send_nochecks (buf
, 0, buf
.Length
, flags
, out error
);
1798 if (error
!= SocketError
.Success
)
1799 throw new SocketException ((int) error
);
1804 public int Send (byte [] buf
, int size
, SocketFlags flags
)
1806 if (disposed
&& closed
)
1807 throw new ObjectDisposedException (GetType ().ToString ());
1810 throw new ArgumentNullException ("buf");
1812 CheckRange (buf
, 0, size
);
1816 int ret
= Send_nochecks (buf
, 0, size
, flags
, out error
);
1818 if (error
!= SocketError
.Success
)
1819 throw new SocketException ((int) error
);
1824 public int Send (byte [] buf
, int offset
, int size
, SocketFlags flags
)
1826 if (disposed
&& closed
)
1827 throw new ObjectDisposedException (GetType ().ToString ());
1830 throw new ArgumentNullException ("buffer");
1832 CheckRange (buf
, offset
, size
);
1836 int ret
= Send_nochecks (buf
, offset
, size
, flags
, out error
);
1838 if (error
!= SocketError
.Success
)
1839 throw new SocketException ((int) error
);
1844 public int Send (byte [] buf
, int offset
, int size
, SocketFlags flags
, out SocketError error
)
1846 if (disposed
&& closed
)
1847 throw new ObjectDisposedException (GetType ().ToString ());
1850 throw new ArgumentNullException ("buffer");
1852 CheckRange (buf
, offset
, size
);
1854 return Send_nochecks (buf
, offset
, size
, flags
, out error
);
1857 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
1858 private extern static bool SendFile (IntPtr sock
, string filename
, byte [] pre_buffer
, byte [] post_buffer
, TransmitFileOptions flags
);
1860 public void SendFile (string fileName
)
1862 if (disposed
&& closed
)
1863 throw new ObjectDisposedException (GetType ().ToString ());
1866 throw new NotSupportedException ();
1869 throw new InvalidOperationException ();
1871 SendFile (fileName
, null, null, 0);
1874 public void SendFile (string fileName
, byte[] preBuffer
, byte[] postBuffer
, TransmitFileOptions flags
)
1876 if (disposed
&& closed
)
1877 throw new ObjectDisposedException (GetType ().ToString ());
1880 throw new NotSupportedException ();
1883 throw new InvalidOperationException ();
1885 if (!SendFile (socket
, fileName
, preBuffer
, postBuffer
, flags
)) {
1886 SocketException exc
= new SocketException ();
1887 if (exc
.ErrorCode
== 2 || exc
.ErrorCode
== 3)
1888 throw new FileNotFoundException ();
1893 public bool SendToAsync (SocketAsyncEventArgs e
)
1895 // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1897 if (disposed
&& closed
)
1898 throw new ObjectDisposedException (GetType ().ToString ());
1899 if (e
.BufferList
!= null)
1900 throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
1901 if (e
.RemoteEndPoint
== null)
1902 throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
1905 e
.Worker
.Init (this, e
, SocketOperation
.SendTo
);
1906 SocketAsyncResult res
= e
.Worker
.result
;
1907 res
.Buffer
= e
.Buffer
;
1908 res
.Offset
= e
.Offset
;
1910 res
.SockFlags
= e
.SocketFlags
;
1911 res
.EndPoint
= e
.RemoteEndPoint
;
1914 writeQ
.Enqueue (e
.Worker
);
1915 count
= writeQ
.Count
;
1918 socket_pool_queue (Worker
.Dispatcher
, res
);
1922 public int SendTo (byte [] buffer
, EndPoint remote_end
)
1924 if (disposed
&& closed
)
1925 throw new ObjectDisposedException (GetType ().ToString ());
1928 throw new ArgumentNullException ("buffer");
1930 if (remote_end
== null)
1931 throw new ArgumentNullException ("remote_end");
1933 return SendTo_nochecks (buffer
, 0, buffer
.Length
, SocketFlags
.None
, remote_end
);
1936 public int SendTo (byte [] buffer
, SocketFlags flags
, EndPoint remote_end
)
1938 if (disposed
&& closed
)
1939 throw new ObjectDisposedException (GetType ().ToString ());
1942 throw new ArgumentNullException ("buffer");
1944 if (remote_end
== null)
1945 throw new ArgumentNullException ("remote_end");
1947 return SendTo_nochecks (buffer
, 0, buffer
.Length
, flags
, remote_end
);
1950 public int SendTo (byte [] buffer
, int size
, SocketFlags flags
, EndPoint remote_end
)
1952 if (disposed
&& closed
)
1953 throw new ObjectDisposedException (GetType ().ToString ());
1956 throw new ArgumentNullException ("buffer");
1958 if (remote_end
== null)
1959 throw new ArgumentNullException ("remote_end");
1961 CheckRange (buffer
, 0, size
);
1963 return SendTo_nochecks (buffer
, 0, size
, flags
, remote_end
);
1966 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
1967 private extern static int SendTo_internal(IntPtr sock
,
1975 public int SendTo (byte [] buffer
, int offset
, int size
, SocketFlags flags
,
1976 EndPoint remote_end
)
1978 if (disposed
&& closed
)
1979 throw new ObjectDisposedException (GetType ().ToString ());
1982 throw new ArgumentNullException ("buffer");
1984 if (remote_end
== null)
1985 throw new ArgumentNullException("remote_end");
1987 CheckRange (buffer
, offset
, size
);
1989 return SendTo_nochecks (buffer
, offset
, size
, flags
, remote_end
);
1992 internal int SendTo_nochecks (byte [] buffer
, int offset
, int size
, SocketFlags flags
,
1993 EndPoint remote_end
)
1995 SocketAddress sockaddr
= remote_end
.Serialize ();
1999 ret
= SendTo_internal (socket
, buffer
, offset
, size
, flags
, sockaddr
, out error
);
2001 SocketError err
= (SocketError
) error
;
2003 if (err
!= SocketError
.WouldBlock
&& err
!= SocketError
.InProgress
)
2006 throw new SocketException (error
);
2011 seed_endpoint
= remote_end
;
2016 public void SetSocketOption (SocketOptionLevel optionLevel
, SocketOptionName optionName
, byte [] optionValue
)
2018 if (disposed
&& closed
)
2019 throw new ObjectDisposedException (GetType ().ToString ());
2021 // I'd throw an ArgumentNullException, but this is what MS does.
2022 if (optionValue
== null)
2023 throw new SocketException ((int) SocketError
.Fault
,
2024 "Error trying to dereference an invalid pointer");
2028 SetSocketOption_internal (socket
, optionLevel
, optionName
, null,
2029 optionValue
, 0, out error
);
2032 if (error
== (int) SocketError
.InvalidArgument
)
2033 throw new ArgumentException ();
2034 throw new SocketException (error
);
2038 public void SetSocketOption (SocketOptionLevel optionLevel
, SocketOptionName optionName
, object optionValue
)
2040 if (disposed
&& closed
)
2041 throw new ObjectDisposedException (GetType ().ToString ());
2043 // NOTE: if a null is passed, the byte[] overload is used instead...
2044 if (optionValue
== null)
2045 throw new ArgumentNullException("optionValue");
2049 if (optionLevel
== SocketOptionLevel
.Socket
&& optionName
== SocketOptionName
.Linger
) {
2050 LingerOption linger
= optionValue
as LingerOption
;
2052 throw new ArgumentException ("A 'LingerOption' value must be specified.", "optionValue");
2053 SetSocketOption_internal (socket
, optionLevel
, optionName
, linger
, null, 0, out error
);
2054 } else if (optionLevel
== SocketOptionLevel
.IP
&& (optionName
== SocketOptionName
.AddMembership
|| optionName
== SocketOptionName
.DropMembership
)) {
2055 MulticastOption multicast
= optionValue
as MulticastOption
;
2056 if (multicast
== null)
2057 throw new ArgumentException ("A 'MulticastOption' value must be specified.", "optionValue");
2058 SetSocketOption_internal (socket
, optionLevel
, optionName
, multicast
, null, 0, out error
);
2059 } else if (optionLevel
== SocketOptionLevel
.IPv6
&& (optionName
== SocketOptionName
.AddMembership
|| optionName
== SocketOptionName
.DropMembership
)) {
2060 IPv6MulticastOption multicast
= optionValue
as IPv6MulticastOption
;
2061 if (multicast
== null)
2062 throw new ArgumentException ("A 'IPv6MulticastOption' value must be specified.", "optionValue");
2063 SetSocketOption_internal (socket
, optionLevel
, optionName
, multicast
, null, 0, out error
);
2065 throw new ArgumentException ("Invalid value specified.", "optionValue");
2069 if (error
== (int) SocketError
.InvalidArgument
)
2070 throw new ArgumentException ();
2071 throw new SocketException (error
);
2075 public void SetSocketOption (SocketOptionLevel optionLevel
, SocketOptionName optionName
, bool optionValue
)
2077 if (disposed
&& closed
)
2078 throw new ObjectDisposedException (GetType ().ToString ());
2081 int int_val
= (optionValue
) ? 1 : 0;
2082 SetSocketOption_internal (socket
, optionLevel
, optionName
, null, null, int_val
, out error
);
2084 if (error
== (int) SocketError
.InvalidArgument
)
2085 throw new ArgumentException ();
2086 throw new SocketException (error
);