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)
8 // Copyright (C) 2001, 2002 Phillip Pearson and Ximian, Inc.
9 // http://www.myelin.co.nz
10 // (c) 2004 Novell, Inc. (http://www.novell.com)
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 using System
.Collections
;
37 using System
.Runtime
.CompilerServices
;
38 using System
.Runtime
.InteropServices
;
39 using System
.Threading
;
40 using System
.Reflection
;
43 namespace System
.Net
.Sockets
45 public class Socket
: IDisposable
47 [StructLayout (LayoutKind
.Sequential
)]
48 private sealed class SocketAsyncResult
: IAsyncResult
50 /* Same structure in the runtime */
54 AsyncCallback callback
;
55 WaitHandle waithandle
;
57 Exception delayedException
;
59 public EndPoint EndPoint
; // Connect,ReceiveFrom,SendTo
60 public byte [] Buffer
; // Receive,ReceiveFrom,Send,SendTo
61 public int Offset
; // Receive,ReceiveFrom,Send,SendTo
62 public int Size
; // Receive,ReceiveFrom,Send,SendTo
63 public SocketFlags SockFlags
; // Receive,ReceiveFrom,Send,SendTo
71 AsyncCallback real_callback
;
74 public SocketAsyncResult (Socket sock
, object state
, AsyncCallback callback
)
77 this.handle
= sock
.socket
;
79 this.real_callback
= callback
;
80 SockFlags
= SocketFlags
.None
;
83 public void CreateAsyncDelegate ()
85 if (real_callback
!= null)
86 this.callback
= new AsyncCallback (FakeCB
);
89 static void FakeCB (IAsyncResult result
)
91 SocketAsyncResult ares
= (SocketAsyncResult
) result
;
92 ares
.real_callback
.BeginInvoke (ares
, null, null);
95 public void CheckIfThrowDelayedException ()
97 if (delayedException
!= null)
98 throw delayedException
;
101 throw new SocketException (error
);
104 public void Complete ()
107 if (real_callback
!= null)
108 real_callback (this);
111 public void Complete (int total
)
117 public void Complete (Exception e
)
119 delayedException
= e
;
123 public void Complete (Socket s
)
129 public object AsyncState
{
135 public WaitHandle AsyncWaitHandle
{
138 if (waithandle
== null)
139 waithandle
= new ManualResetEvent (completed
);
149 public bool CompletedSynchronously
{
151 return(completed_sync
);
155 public bool IsCompleted
{
162 if (waithandle
!= null && value) {
163 ((ManualResetEvent
) waithandle
).Set ();
169 public Socket Socket
{
182 private sealed class Worker
184 SocketAsyncResult result
;
186 public Worker (SocketAsyncResult ares
)
191 public void Accept ()
194 Socket acc_socket
= null;
196 if (!result
.Sock
.blocking
)
197 result
.Sock
.Poll (-1, SelectMode
.SelectRead
);
199 acc_socket
= result
.Sock
.Accept ();
200 } catch (Exception e
) {
205 result
.Complete (acc_socket
);
209 public void Connect ()
213 result
.Sock
.Connect (result
.EndPoint
);
214 } catch (SocketException se
) {
215 if (result
.Sock
.blocking
|| se
.ErrorCode
!= 10036) {
216 result
.Complete (se
);
221 result
.Sock
.Poll (-1, SelectMode
.SelectWrite
);
222 result
.Sock
.Connect (result
.EndPoint
);
223 } catch (Exception k
) {
227 } catch (Exception e
) {
236 public void Receive ()
241 if (!result
.Sock
.blocking
)
242 result
.Sock
.Poll (-1, SelectMode
.SelectRead
);
244 total
= result
.Sock
.Receive_nochecks (result
.Buffer
,
248 } catch (Exception e
) {
253 result
.Complete (total
);
257 public void ReceiveFrom ()
262 if (!result
.Sock
.blocking
)
263 result
.Sock
.Poll (-1, SelectMode
.SelectRead
);
265 total
= result
.Sock
.ReceiveFrom_nochecks (result
.Buffer
,
269 ref result
.EndPoint
);
270 } catch (Exception e
) {
275 result
.Complete (total
);
284 if (!result
.Sock
.blocking
)
285 result
.Sock
.Poll (-1, SelectMode
.SelectWrite
);
287 total
= result
.Sock
.Send_nochecks (result
.Buffer
,
291 } catch (Exception e
) {
296 result
.Complete (total
);
300 public void SendTo() {
304 if (!result
.Sock
.blocking
)
305 result
.Sock
.Poll (-1, SelectMode
.SelectWrite
);
307 total
= result
.Sock
.SendTo_nochecks (result
.Buffer
,
312 } catch (Exception e
) {
317 result
.Complete (total
);
322 /* the field "socket" is looked up by name by the runtime */
323 private IntPtr socket
;
324 private AddressFamily address_family
;
325 private SocketType socket_type
;
326 private ProtocolType protocol_type
;
327 internal bool blocking
=true;
328 private int pendingEnds
;
329 private int closeDelayed
;
330 static readonly bool supportsAsync
= FakeGetSupportsAsync ();
332 delegate void SocketAsyncCall ();
334 * These two fields are looked up by name by the runtime, don't change
335 * their name without also updating the runtime code.
337 private static int ipv4Supported
= -1, ipv6Supported
= -1;
339 /* When true, the socket was connected at the time of
340 * the last IO operation
342 private bool connected
=false;
343 /* true if we called Close_internal */
346 /* Used in LocalEndPoint and RemoteEndPoint if the
347 * Mono.Posix assembly is available
349 private static object unixendpoint
=null;
350 private static Type unixendpointtype
=null;
352 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
353 private extern static void Select_internal(ref Socket
[] read
,
359 public static void Select(IList read_list
, IList write_list
,
360 IList err_list
, int time_us
) {
361 int read_count
= 0, write_count
= 0, err_count
= 0;
362 Socket
[] read_arr
= null;
363 Socket
[] write_arr
= null;
364 Socket
[] err_arr
= null;
367 read_count
=read_list
.Count
;
370 read_arr
=new Socket
[read_count
];
372 if (write_list
!=null)
373 write_count
=write_list
.Count
;
375 if (write_count
!= 0)
376 write_arr
=new Socket
[write_count
];
379 err_count
=err_list
.Count
;
382 err_arr
=new Socket
[err_count
];
384 if(read_count
== 0 && write_count
== 0 && err_count
== 0) {
385 throw new ArgumentNullException ("read_list, write_list, err_list",
386 "All the lists are null or empty.");
391 if (read_count
!= 0) {
394 foreach (Socket s
in read_list
) {
400 if (write_count
!= 0) {
402 foreach (Socket s
in write_list
) {
408 if (err_count
!= 0) {
410 foreach (Socket s
in err_list
) {
418 Select_internal(ref read_arr
, ref write_arr
,
419 ref err_arr
, time_us
, out error
);
422 throw new SocketException (error
);
425 /* Make sure the connected state is updated
426 * for each socket returned from the select;
427 * for non blocking Connect()s, this is when
428 * we find out that the connect succeeded.
431 if(read_list
!=null) {
433 if (read_arr
!= null) {
434 for(i
=0; i
<read_arr
.Length
; i
++) {
435 read_list
.Add(read_arr
[i
]);
436 read_arr
[i
].connected
= true;
441 if(write_list
!=null) {
443 if (write_arr
!= null) {
444 for(i
=0; i
<write_arr
.Length
; i
++) {
445 write_list
.Add(write_arr
[i
]);
446 write_arr
[i
].connected
= true;
453 if (err_arr
!= null) {
454 for(i
=0; i
<err_arr
.Length
; i
++) {
455 err_list
.Add(err_arr
[i
]);
456 err_arr
[i
].connected
= true;
466 ass
= Assembly
.Load (Consts
.AssemblyMono_Posix
);
467 } catch (FileNotFoundException
) {
471 unixendpointtype
=ass
.GetType("Mono.Posix.UnixEndPoint");
473 /* The endpoint Create() method is an instance
476 Type
[] arg_types
=new Type
[1];
477 arg_types
[0]=typeof(string);
478 ConstructorInfo cons
=unixendpointtype
.GetConstructor(arg_types
);
480 object[] args
=new object[1];
483 unixendpoint
=cons
.Invoke(args
);
486 // private constructor used by Accept, which already
487 // has a socket handle to use
488 private Socket(AddressFamily family
, SocketType type
,
489 ProtocolType proto
, IntPtr sock
) {
490 address_family
=family
;
498 // Creates a new system socket, returning the handle
499 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
500 private extern IntPtr
Socket_internal(AddressFamily family
,
505 public Socket(AddressFamily family
, SocketType type
,
506 ProtocolType proto
) {
507 address_family
=family
;
513 socket
=Socket_internal(family
, type
, proto
, out error
);
515 throw new SocketException (error
);
519 public AddressFamily AddressFamily
{
521 return(address_family
);
525 // Returns the amount of data waiting to be read on socket
526 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
527 private extern static int Available_internal(IntPtr socket
,
530 public int Available
{
532 if (disposed
&& closed
)
533 throw new ObjectDisposedException (GetType ().ToString ());
537 ret
= Available_internal(socket
, out error
);
540 throw new SocketException (error
);
547 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
548 private extern static void Blocking_internal(IntPtr socket
,
552 public bool Blocking
{
559 Blocking_internal(socket
, value, out error
);
562 throw new SocketException (error
);
569 public bool Connected
{
575 public IntPtr Handle
{
581 // Returns the local endpoint details in addr and port
582 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
583 private extern static SocketAddress
LocalEndPoint_internal(IntPtr socket
, out int error
);
585 [MonoTODO("Support non-IP endpoints")]
586 public EndPoint LocalEndPoint
{
588 if (disposed
&& closed
)
589 throw new ObjectDisposedException (GetType ().ToString ());
594 sa
=LocalEndPoint_internal(socket
, out error
);
597 throw new SocketException (error
);
600 if(sa
.Family
==AddressFamily
.InterNetwork
|| sa
.Family
==AddressFamily
.InterNetworkV6
) {
601 // Stupidly, EndPoint.Create() is an
603 return new IPEndPoint(0, 0).Create(sa
);
604 } else if (sa
.Family
==AddressFamily
.Unix
&&
605 unixendpoint
!=null) {
606 return((EndPoint
)unixendpointtype
.InvokeMember("Create", BindingFlags
.InvokeMethod
|BindingFlags
.Instance
|BindingFlags
.Public
, null, unixendpoint
, new object[] {sa}
));
608 throw new NotImplementedException();
613 public ProtocolType ProtocolType
{
615 return(protocol_type
);
619 // Returns the remote endpoint details in addr and port
620 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
621 private extern static SocketAddress
RemoteEndPoint_internal(IntPtr socket
, out int error
);
623 [MonoTODO("Support non-IP endpoints")]
624 public EndPoint RemoteEndPoint
{
626 if (disposed
&& closed
)
627 throw new ObjectDisposedException (GetType ().ToString ());
632 sa
=RemoteEndPoint_internal(socket
, out error
);
635 throw new SocketException (error
);
638 if(sa
.Family
==AddressFamily
.InterNetwork
|| sa
.Family
==AddressFamily
.InterNetworkV6
) {
639 // Stupidly, EndPoint.Create() is an
641 return new IPEndPoint(0, 0).Create(sa
);
642 } else if (sa
.Family
==AddressFamily
.Unix
&&
643 unixendpoint
!=null) {
644 return((EndPoint
)unixendpointtype
.InvokeMember("Create", BindingFlags
.InvokeMethod
|BindingFlags
.Instance
|BindingFlags
.Public
, null, unixendpoint
, new object[] {sa}
));
646 throw new NotImplementedException();
651 public SocketType SocketType
{
658 public static bool SupportsIPv4
{
660 CheckProtocolSupport();
661 return ipv4Supported
== 1;
665 public static bool SupportsIPv6
{
667 CheckProtocolSupport();
668 return ipv6Supported
== 1;
672 internal static bool SupportsIPv4
680 internal static bool SupportsIPv6
689 internal static void CheckProtocolSupport()
691 if(ipv4Supported
== -1) {
693 Socket tmp
= new Socket(AddressFamily
.InterNetwork
, SocketType
.Stream
, ProtocolType
.Tcp
);
703 if(ipv6Supported
== -1) {
704 NetConfig config
= (NetConfig
)System
.Configuration
.ConfigurationSettings
.GetConfig("system.net/settings");
707 ipv6Supported
= config
.ipv6Enabled
?-1:0;
709 if(ipv6Supported
!= 0) {
711 Socket tmp
= new Socket(AddressFamily
.InterNetworkV6
, SocketType
.Stream
, ProtocolType
.Tcp
);
721 // Creates a new system socket, returning the handle
722 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
723 private extern static IntPtr
Accept_internal(IntPtr sock
,
726 public Socket
Accept() {
727 if (disposed
&& closed
)
728 throw new ObjectDisposedException (GetType ().ToString ());
731 IntPtr sock
=Accept_internal(socket
, out error
);
733 if (!blocking
&& error
== 10035) {
734 Poll (-1, SelectMode
.SelectRead
);
735 sock
= Accept_internal (socket
, out error
);
739 throw new SocketException (error
);
742 Socket accepted
= new Socket(this.AddressFamily
,
744 this.ProtocolType
, sock
);
746 // The MS runtime (really the OS, we suspect)
747 // sets newly accepted sockets to have the
748 // same Blocking status as the listening
750 accepted
.Blocking
= this.Blocking
;
754 public IAsyncResult
BeginAccept(AsyncCallback callback
,
757 if (disposed
&& closed
)
758 throw new ObjectDisposedException (GetType ().ToString ());
760 Interlocked
.Increment (ref pendingEnds
);
761 SocketAsyncResult req
= new SocketAsyncResult (this, state
, callback
);
762 Worker worker
= new Worker (req
);
763 SocketAsyncCall sac
= new SocketAsyncCall (worker
.Accept
);
764 sac
.BeginInvoke (null, null);
768 public IAsyncResult
BeginConnect(EndPoint end_point
,
769 AsyncCallback callback
,
772 if (disposed
&& closed
)
773 throw new ObjectDisposedException (GetType ().ToString ());
775 if (end_point
== null)
776 throw new ArgumentNullException ("end_point");
778 Interlocked
.Increment (ref pendingEnds
);
779 SocketAsyncResult req
= new SocketAsyncResult (this, state
, callback
);
780 req
.EndPoint
= end_point
;
781 Worker worker
= new Worker (req
);
782 SocketAsyncCall sac
= new SocketAsyncCall (worker
.Connect
);
783 sac
.BeginInvoke (null, null);
787 public IAsyncResult
BeginReceive(byte[] buffer
, int offset
,
789 SocketFlags socket_flags
,
790 AsyncCallback callback
,
793 if (disposed
&& closed
)
794 throw new ObjectDisposedException (GetType ().ToString ());
797 throw new ArgumentNullException ("buffer");
799 if (offset
< 0 || offset
> buffer
.Length
)
800 throw new ArgumentOutOfRangeException ("offset");
802 if (size
< 0 || offset
+ size
> buffer
.Length
)
803 throw new ArgumentOutOfRangeException ("size");
805 Interlocked
.Increment (ref pendingEnds
);
806 SocketAsyncResult req
= new SocketAsyncResult (this, state
, callback
);
810 req
.SockFlags
= socket_flags
;
811 if (supportsAsync
&& socket_type
== SocketType
.Stream
) {
813 req
.CreateAsyncDelegate ();
815 AsyncReceiveInternal (req
, out error
);
816 if (error
!= 0 && error
!= 10036) // WSAEINPROGRESS
817 throw new SocketException (error
);
819 Worker worker
= new Worker (req
);
820 SocketAsyncCall sac
= new SocketAsyncCall (worker
.Receive
);
821 sac
.BeginInvoke (null, null);
827 public IAsyncResult
BeginReceiveFrom(byte[] buffer
, int offset
,
829 SocketFlags socket_flags
,
830 ref EndPoint remote_end
,
831 AsyncCallback callback
,
833 if (disposed
&& closed
)
834 throw new ObjectDisposedException (GetType ().ToString ());
837 throw new ArgumentNullException ("buffer");
840 throw new ArgumentOutOfRangeException ("offset must be >= 0");
843 throw new ArgumentOutOfRangeException ("size must be >= 0");
845 if (offset
+ size
> buffer
.Length
)
846 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
848 Interlocked
.Increment (ref pendingEnds
);
849 SocketAsyncResult req
= new SocketAsyncResult (this, state
, callback
);
853 req
.SockFlags
= socket_flags
;
854 req
.EndPoint
= remote_end
;
855 Worker worker
= new Worker (req
);
856 SocketAsyncCall sac
= new SocketAsyncCall (worker
.ReceiveFrom
);
857 sac
.BeginInvoke (null, null);
861 public IAsyncResult
BeginSend (byte[] buffer
, int offset
, int size
, SocketFlags socket_flags
,
862 AsyncCallback callback
, object state
)
864 if (disposed
&& closed
)
865 throw new ObjectDisposedException (GetType ().ToString ());
868 throw new ArgumentNullException ("buffer");
871 throw new ArgumentOutOfRangeException ("offset must be >= 0");
874 throw new ArgumentOutOfRangeException ("size must be >= 0");
876 if (offset
+ size
> buffer
.Length
)
877 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
879 Interlocked
.Increment (ref pendingEnds
);
880 SocketAsyncResult req
= new SocketAsyncResult (this, state
, callback
);
884 req
.SockFlags
= socket_flags
;
885 if (supportsAsync
&& socket_type
== SocketType
.Stream
) {
887 req
.CreateAsyncDelegate ();
889 AsyncSendInternal (req
, out error
);
890 if (error
!= 0 && error
!= 10036) // WSAEINPROGRESS
891 throw new SocketException (error
);
893 Worker worker
= new Worker (req
);
894 SocketAsyncCall sac
= new SocketAsyncCall (worker
.Send
);
895 sac
.BeginInvoke (null, null);
900 public IAsyncResult
BeginSendTo(byte[] buffer
, int offset
,
902 SocketFlags socket_flags
,
904 AsyncCallback callback
,
906 if (disposed
&& closed
)
907 throw new ObjectDisposedException (GetType ().ToString ());
910 throw new ArgumentNullException ("buffer");
913 throw new ArgumentOutOfRangeException ("offset must be >= 0");
916 throw new ArgumentOutOfRangeException ("size must be >= 0");
918 if (offset
+ size
> buffer
.Length
)
919 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
921 Interlocked
.Increment (ref pendingEnds
);
922 SocketAsyncResult req
= new SocketAsyncResult (this, state
, callback
);
926 req
.SockFlags
= socket_flags
;
927 req
.EndPoint
= remote_end
;
928 Worker worker
= new Worker(req
);
929 SocketAsyncCall sac
= new SocketAsyncCall (worker
.SendTo
);
930 sac
.BeginInvoke (null, null);
934 // Creates a new system socket, returning the handle
935 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
936 private extern static void Bind_internal(IntPtr sock
,
940 public void Bind(EndPoint local_end
) {
941 if (disposed
&& closed
)
942 throw new ObjectDisposedException (GetType ().ToString ());
944 if(local_end
==null) {
945 throw new ArgumentNullException("local_end");
950 Bind_internal(socket
, local_end
.Serialize(),
954 throw new SocketException (error
);
959 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
960 private extern static void Close_internal(IntPtr socket
,
963 public void Close() {
964 ((IDisposable
) this).Dispose ();
967 // Connects to the remote address
968 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
969 private extern static void Connect_internal(IntPtr sock
,
973 public void Connect(EndPoint remote_end
) {
974 if (disposed
&& closed
)
975 throw new ObjectDisposedException (GetType ().ToString ());
977 if(remote_end
==null) {
978 throw new ArgumentNullException("remote_end");
983 SocketAddress serial
= remote_end
.Serialize ();
984 Connect_internal(socket
, serial
, out error
);
985 if (!blocking
&& error
== 10035) {
986 Poll (-1, SelectMode
.SelectWrite
);
987 Connect_internal (socket
, serial
, out error
);
991 throw new SocketException (error
);
996 public Socket
EndAccept(IAsyncResult result
) {
997 if (disposed
&& closed
)
998 throw new ObjectDisposedException (GetType ().ToString ());
1001 throw new ArgumentNullException ("result");
1003 SocketAsyncResult req
= result
as SocketAsyncResult
;
1005 throw new ArgumentException ("Invalid IAsyncResult", "result");
1007 if (!result
.IsCompleted
)
1008 result
.AsyncWaitHandle
.WaitOne();
1010 Interlocked
.Decrement (ref pendingEnds
);
1012 req
.CheckIfThrowDelayedException();
1016 public void EndConnect(IAsyncResult result
) {
1017 if (disposed
&& closed
)
1018 throw new ObjectDisposedException (GetType ().ToString ());
1021 throw new ArgumentNullException ("result");
1023 SocketAsyncResult req
= result
as SocketAsyncResult
;
1025 throw new ArgumentException ("Invalid IAsyncResult", "result");
1027 if (!result
.IsCompleted
)
1028 result
.AsyncWaitHandle
.WaitOne();
1030 Interlocked
.Decrement (ref pendingEnds
);
1032 req
.CheckIfThrowDelayedException();
1035 public int EndReceive(IAsyncResult result
) {
1036 if (disposed
&& closed
)
1037 throw new ObjectDisposedException (GetType ().ToString ());
1040 throw new ArgumentNullException ("result");
1042 SocketAsyncResult req
= result
as SocketAsyncResult
;
1044 throw new ArgumentException ("Invalid IAsyncResult", "result");
1046 if (supportsAsync
&& socket_type
== SocketType
.Stream
)
1047 RemoveReference (req
);
1049 if (!result
.IsCompleted
)
1050 result
.AsyncWaitHandle
.WaitOne();
1052 Interlocked
.Decrement (ref pendingEnds
);
1054 req
.CheckIfThrowDelayedException();
1058 public int EndReceiveFrom(IAsyncResult result
,
1059 ref EndPoint end_point
) {
1060 if (disposed
&& closed
)
1061 throw new ObjectDisposedException (GetType ().ToString ());
1064 throw new ArgumentNullException ("result");
1066 SocketAsyncResult req
= result
as SocketAsyncResult
;
1068 throw new ArgumentException ("Invalid IAsyncResult", "result");
1070 if (!result
.IsCompleted
)
1071 result
.AsyncWaitHandle
.WaitOne();
1073 Interlocked
.Decrement (ref pendingEnds
);
1075 req
.CheckIfThrowDelayedException();
1076 end_point
= req
.EndPoint
;
1080 public int EndSend(IAsyncResult result
) {
1081 if (disposed
&& closed
)
1082 throw new ObjectDisposedException (GetType ().ToString ());
1085 throw new ArgumentNullException ("result");
1087 SocketAsyncResult req
= result
as SocketAsyncResult
;
1089 throw new ArgumentException ("Invalid IAsyncResult", "result");
1091 if (supportsAsync
&& socket_type
== SocketType
.Stream
)
1092 RemoveReference (req
);
1094 if (!result
.IsCompleted
)
1095 result
.AsyncWaitHandle
.WaitOne();
1097 Interlocked
.Decrement (ref pendingEnds
);
1099 req
.CheckIfThrowDelayedException();
1103 public int EndSendTo(IAsyncResult result
) {
1104 if (disposed
&& closed
)
1105 throw new ObjectDisposedException (GetType ().ToString ());
1108 throw new ArgumentNullException ("result");
1110 SocketAsyncResult req
= result
as SocketAsyncResult
;
1112 throw new ArgumentException ("Invalid IAsyncResult", "result");
1114 if (!result
.IsCompleted
)
1115 result
.AsyncWaitHandle
.WaitOne();
1117 Interlocked
.Decrement (ref pendingEnds
);
1119 req
.CheckIfThrowDelayedException();
1123 void CheckIfClose ()
1125 if (Interlocked
.CompareExchange (ref closeDelayed
, 0, 1) == 1 &&
1126 Interlocked
.CompareExchange (ref pendingEnds
, 0, 0) == 0) {
1131 Close_internal(socket
, out error
);
1134 throw new SocketException (error
);
1139 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
1140 private extern static void GetSocketOption_obj_internal(IntPtr socket
, SocketOptionLevel level
, SocketOptionName name
, out object obj_val
, out int error
);
1141 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
1142 private extern static void GetSocketOption_arr_internal(IntPtr socket
, SocketOptionLevel level
, SocketOptionName name
, ref byte[] byte_val
, out int error
);
1144 public object GetSocketOption(SocketOptionLevel level
,
1145 SocketOptionName name
) {
1149 GetSocketOption_obj_internal(socket
, level
, name
,
1150 out obj_val
, out error
);
1153 throw new SocketException (error
);
1156 if(name
==SocketOptionName
.Linger
) {
1157 return((LingerOption
)obj_val
);
1158 } else if (name
==SocketOptionName
.AddMembership
||
1159 name
==SocketOptionName
.DropMembership
) {
1160 return((MulticastOption
)obj_val
);
1161 } else if (obj_val
is int) {
1162 return((int)obj_val
);
1168 public void GetSocketOption(SocketOptionLevel level
,
1169 SocketOptionName name
,
1171 int opt_value_len
=opt_value
.Length
;
1174 GetSocketOption_arr_internal(socket
, level
, name
,
1175 ref opt_value
, out error
);
1178 throw new SocketException (error
);
1182 public byte[] GetSocketOption(SocketOptionLevel level
,
1183 SocketOptionName name
,
1185 byte[] byte_val
=new byte[length
];
1188 GetSocketOption_arr_internal(socket
, level
, name
,
1189 ref byte_val
, out error
);
1192 throw new SocketException (error
);
1198 // See Socket.IOControl, WSAIoctl documentation in MSDN. The
1199 // common options between UNIX and Winsock are FIONREAD,
1200 // FIONBIO and SIOCATMARK. Anything else will depend on the
1202 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
1203 extern static int WSAIoctl (IntPtr sock
, int ioctl_code
,
1204 byte [] input
, byte [] output
,
1207 public int IOControl (int ioctl_code
, byte [] in_value
, byte [] out_value
)
1210 throw new ObjectDisposedException (GetType ().ToString ());
1213 int result
= WSAIoctl (socket
, ioctl_code
, in_value
,
1214 out_value
, out error
);
1217 throw new SocketException (error
);
1221 throw new InvalidOperationException ("Must use Blocking property instead.");
1226 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
1227 private extern static void Listen_internal(IntPtr sock
,
1231 public void Listen(int backlog
) {
1234 Listen_internal(socket
, backlog
, out error
);
1237 throw new SocketException (error
);
1241 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
1242 extern static bool Poll_internal (IntPtr socket
, SelectMode mode
, int timeout
, out int error
);
1244 public bool Poll (int time_us
, SelectMode mode
)
1246 if (mode
!= SelectMode
.SelectRead
&&
1247 mode
!= SelectMode
.SelectWrite
&&
1248 mode
!= SelectMode
.SelectError
)
1249 throw new NotSupportedException ("'mode' parameter is not valid.");
1252 bool result
= Poll_internal (socket
, mode
, time_us
, out error
);
1254 throw new SocketException (error
);
1256 if (result
== true) {
1257 /* Update the connected state; for
1258 * non-blocking Connect()s this is
1259 * when we can find out that the
1260 * connect succeeded.
1268 public int Receive (byte [] buf
)
1271 throw new ArgumentNullException ("buf");
1273 return Receive_nochecks (buf
, 0, buf
.Length
, SocketFlags
.None
);
1276 public int Receive (byte [] buf
, SocketFlags flags
)
1279 throw new ArgumentNullException ("buf");
1281 return Receive_nochecks (buf
, 0, buf
.Length
, flags
);
1284 public int Receive (byte [] buf
, int size
, SocketFlags flags
)
1287 throw new ArgumentNullException ("buf");
1289 if (size
< 0 || size
> buf
.Length
)
1290 throw new ArgumentOutOfRangeException ("size");
1292 return Receive_nochecks (buf
, 0, size
, flags
);
1295 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
1296 private extern static int Receive_internal(IntPtr sock
,
1303 public int Receive (byte [] buf
, int offset
, int size
, SocketFlags flags
)
1306 throw new ArgumentNullException ("buf");
1308 if (offset
< 0 || offset
> buf
.Length
)
1309 throw new ArgumentOutOfRangeException ("offset");
1311 if (size
< 0 || offset
+ size
> buf
.Length
)
1312 throw new ArgumentOutOfRangeException ("size");
1314 return Receive_nochecks (buf
, offset
, size
, flags
);
1317 int Receive_nochecks (byte [] buf
, int offset
, int size
, SocketFlags flags
)
1321 ret
= Receive_internal (socket
, buf
, offset
, size
, flags
, out error
);
1325 throw new SocketException (error
);
1333 public int ReceiveFrom (byte [] buf
, ref EndPoint remote_end
)
1336 throw new ArgumentNullException ("buf");
1338 if (remote_end
== null)
1339 throw new ArgumentNullException ("remote_end");
1341 return ReceiveFrom_nochecks (buf
, 0, buf
.Length
, SocketFlags
.None
, ref remote_end
);
1344 public int ReceiveFrom (byte [] buf
, SocketFlags flags
, ref EndPoint remote_end
)
1347 throw new ArgumentNullException ("buf");
1349 if (remote_end
== null)
1350 throw new ArgumentNullException ("remote_end");
1353 return ReceiveFrom_nochecks (buf
, 0, buf
.Length
, flags
, ref remote_end
);
1356 public int ReceiveFrom (byte [] buf
, int size
, SocketFlags flags
,
1357 ref EndPoint remote_end
)
1360 throw new ArgumentNullException ("buf");
1362 if (remote_end
== null)
1363 throw new ArgumentNullException ("remote_end");
1365 if (size
< 0 || size
> buf
.Length
)
1366 throw new ArgumentOutOfRangeException ("size");
1368 return ReceiveFrom_nochecks (buf
, 0, size
, flags
, ref remote_end
);
1372 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
1373 private extern static int RecvFrom_internal(IntPtr sock
,
1378 ref SocketAddress sockaddr
,
1381 public int ReceiveFrom (byte [] buf
, int offset
, int size
, SocketFlags flags
,
1382 ref EndPoint remote_end
)
1385 throw new ArgumentNullException ("buf");
1387 if (remote_end
== null)
1388 throw new ArgumentNullException ("remote_end");
1390 if (offset
< 0 || offset
> buf
.Length
)
1391 throw new ArgumentOutOfRangeException ("offset");
1393 if (size
< 0 || offset
+ size
> buf
.Length
)
1394 throw new ArgumentOutOfRangeException ("size");
1396 return ReceiveFrom_nochecks (buf
, offset
, size
, flags
, ref remote_end
);
1399 int ReceiveFrom_nochecks (byte [] buf
, int offset
, int size
, SocketFlags flags
,
1400 ref EndPoint remote_end
)
1402 SocketAddress sockaddr
= remote_end
.Serialize();
1405 cnt
= RecvFrom_internal (socket
, buf
, offset
, size
, flags
, ref sockaddr
, out error
);
1409 throw new SocketException (error
);
1414 // If sockaddr is null then we're a connection
1415 // oriented protocol and should ignore the
1416 // remote_end parameter (see MSDN
1417 // documentation for Socket.ReceiveFrom(...) )
1419 if ( sockaddr
!= null ) {
1420 // Stupidly, EndPoint.Create() is an
1422 remote_end
= remote_end
.Create (sockaddr
);
1428 public int Send (byte [] buf
)
1431 throw new ArgumentNullException ("buf");
1433 return Send_nochecks (buf
, 0, buf
.Length
, SocketFlags
.None
);
1436 public int Send (byte [] buf
, SocketFlags flags
)
1439 throw new ArgumentNullException ("buf");
1441 return Send_nochecks (buf
, 0, buf
.Length
, flags
);
1444 public int Send (byte [] buf
, int size
, SocketFlags flags
)
1447 throw new ArgumentNullException ("buf");
1449 if (size
< 0 || size
> buf
.Length
)
1450 throw new ArgumentOutOfRangeException ("size");
1452 return Send_nochecks (buf
, 0, size
, flags
);
1455 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
1456 private extern static int Send_internal(IntPtr sock
,
1457 byte[] buf
, int offset
,
1462 public int Send (byte [] buf
, int offset
, int size
, SocketFlags flags
)
1465 throw new ArgumentNullException ("buffer");
1467 if (offset
< 0 || offset
> buf
.Length
)
1468 throw new ArgumentOutOfRangeException ("offset");
1470 if (size
< 0 || offset
+ size
> buf
.Length
)
1471 throw new ArgumentOutOfRangeException ("size");
1473 return Send_nochecks (buf
, offset
, size
, flags
);
1476 int Send_nochecks (byte [] buf
, int offset
, int size
, SocketFlags flags
)
1483 ret
= Send_internal (socket
, buf
, offset
, size
, flags
, out error
);
1487 throw new SocketException (error
);
1495 public int SendTo (byte [] buffer
, EndPoint remote_end
)
1498 throw new ArgumentNullException ("buffer");
1500 if (remote_end
== null)
1501 throw new ArgumentNullException ("remote_end");
1503 return SendTo_nochecks (buffer
, 0, buffer
.Length
, SocketFlags
.None
, remote_end
);
1506 public int SendTo (byte [] buffer
, SocketFlags flags
, EndPoint remote_end
)
1509 throw new ArgumentNullException ("buffer");
1511 if (remote_end
== null)
1512 throw new ArgumentNullException ("remote_end");
1514 return SendTo_nochecks (buffer
, 0, buffer
.Length
, flags
, remote_end
);
1517 public int SendTo (byte [] buffer
, int size
, SocketFlags flags
, EndPoint remote_end
)
1520 throw new ArgumentNullException ("buffer");
1522 if (remote_end
== null)
1523 throw new ArgumentNullException ("remote_end");
1525 if (size
< 0 || size
> buffer
.Length
)
1526 throw new ArgumentOutOfRangeException ("size");
1528 return SendTo_nochecks (buffer
, 0, size
, flags
, remote_end
);
1532 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
1533 private extern static int SendTo_internal(IntPtr sock
,
1541 public int SendTo (byte [] buffer
, int offset
, int size
, SocketFlags flags
,
1542 EndPoint remote_end
)
1545 throw new ArgumentNullException ("buffer");
1547 if (remote_end
== null)
1548 throw new ArgumentNullException("remote_end");
1550 if (offset
< 0 || offset
> buffer
.Length
)
1551 throw new ArgumentOutOfRangeException ("offset");
1553 if (size
< 0 || offset
+ size
> buffer
.Length
)
1554 throw new ArgumentOutOfRangeException ("size");
1556 return SendTo_nochecks (buffer
, offset
, size
, flags
, remote_end
);
1559 int SendTo_nochecks (byte [] buffer
, int offset
, int size
, SocketFlags flags
,
1560 EndPoint remote_end
)
1562 SocketAddress sockaddr
= remote_end
.Serialize ();
1566 ret
= SendTo_internal (socket
, buffer
, offset
, size
, flags
, sockaddr
, out error
);
1570 throw new SocketException (error
);
1578 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
1579 private extern static void SetSocketOption_internal (IntPtr socket
, SocketOptionLevel level
,
1580 SocketOptionName name
, object obj_val
,
1581 byte [] byte_val
, int int_val
,
1584 public void SetSocketOption(SocketOptionLevel level
,
1585 SocketOptionName name
,
1589 SetSocketOption_internal(socket
, level
, name
, null,
1590 opt_value
, 0, out error
);
1593 throw new SocketException (error
);
1597 public void SetSocketOption(SocketOptionLevel level
,
1598 SocketOptionName name
,
1602 SetSocketOption_internal(socket
, level
, name
, null,
1603 null, opt_value
, out error
);
1606 throw new SocketException (error
);
1610 public void SetSocketOption(SocketOptionLevel level
,
1611 SocketOptionName name
,
1613 if(opt_value
==null) {
1614 throw new ArgumentNullException();
1619 /* Passing a bool as the third parameter to
1620 * SetSocketOption causes this overload to be
1621 * used when in fact we want to pass the value
1622 * to the runtime as an int.
1624 if (opt_value
is System
.Boolean
) {
1625 bool bool_val
= (bool) opt_value
;
1626 int int_val
= (bool_val
) ? 1 : 0;
1628 SetSocketOption_internal (socket
, level
, name
, null, null, int_val
, out error
);
1630 SetSocketOption_internal (socket
, level
, name
, opt_value
, null, 0, out error
);
1634 throw new SocketException (error
);
1638 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
1639 private extern static void Shutdown_internal(IntPtr socket
, SocketShutdown how
, out int error
);
1641 public void Shutdown(SocketShutdown how
) {
1644 Shutdown_internal(socket
, how
, out error
);
1647 throw new SocketException (error
);
1651 public override int GetHashCode ()
1653 return (int) socket
;
1656 private bool disposed
;
1658 protected virtual void Dispose(bool explicitDisposing
) {
1664 if (!explicitDisposing
) {
1666 Close_internal (socket
, out error
);
1669 throw new SocketException (error
);
1675 if (Interlocked
.CompareExchange (ref pendingEnds
, 0, 0) == 0) {
1677 Close_internal (socket
, out error
);
1680 throw new SocketException (error
);
1683 Interlocked
.CompareExchange (ref closeDelayed
, 1, 0);
1688 void IDisposable
.Dispose ()
1691 GC
.SuppressFinalize (this);
1698 static Hashtable asyncObjects
;
1700 static void KeepReference (object o
)
1702 lock (typeof (Socket
)) {
1703 if (asyncObjects
== null)
1704 asyncObjects
= new Hashtable ();
1706 asyncObjects
[o
] = o
;
1710 static void RemoveReference (object o
)
1712 lock (typeof (Socket
)) {
1713 if (asyncObjects
== null)
1716 asyncObjects
.Remove (o
);
1720 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
1721 extern static bool GetSupportsAsync ();
1723 static bool FakeGetSupportsAsync ()
1725 if (Environment
.GetEnvironmentVariable ("MONO_ENABLE_SOCKET_AIO") != null)
1726 return GetSupportsAsync ();
1731 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
1732 extern static void AsyncReceiveInternal (SocketAsyncResult ares
, out int error
);
1734 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
1735 extern static void AsyncSendInternal (SocketAsyncResult ares
, out int error
);