2009-05-18 Miguel de Icaza <miguel@novell.com>
[mono.git] / mcs / class / System / System.Net.Sockets / Socket_2_1.cs
1 // System.Net.Sockets.Socket.cs
2 //
3 // Authors:
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 //
10 // Copyright (C) 2001, 2002 Phillip Pearson and Ximian, Inc.
11 //    http://www.myelin.co.nz
12 // (c) 2004-2006 Novell, Inc. (http://www.novell.com)
13 //
14
15 //
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:
23 // 
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
26 // 
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.
34 //
35
36 using System;
37 using System.Net;
38 using System.Collections;
39 using System.Runtime.CompilerServices;
40 using System.Runtime.InteropServices;
41 using System.Threading;
42 using System.Reflection;
43 using System.IO;
44 using System.Net.Configuration;
45 using System.Security;
46 using System.Text;
47
48 #if NET_2_0
49 using System.Collections.Generic;
50 using System.Net.NetworkInformation;
51 #if !NET_2_1
52 using System.Timers;
53 #endif
54 #endif
55
56 namespace System.Net.Sockets {
57
58         public partial class Socket : IDisposable {
59
60                 /*
61                  *      These two fields are looked up by name by the runtime, don't change
62                  *  their name without also updating the runtime code.
63                  */
64                 private static int ipv4Supported = -1, ipv6Supported = -1;
65
66                 static Socket ()
67                 {
68                         // initialize ipv4Supported and ipv6Supported
69                         CheckProtocolSupport ();
70                 }
71
72                 internal static void CheckProtocolSupport ()
73                 {
74                         if(ipv4Supported == -1) {
75                                 try {
76                                         Socket tmp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
77                                         tmp.Close();
78
79                                         ipv4Supported = 1;
80                                 } catch {
81                                         ipv4Supported = 0;
82                                 }
83                         }
84
85                         if (ipv6Supported == -1) {
86 #if !NET_2_1
87 #if NET_2_0 && CONFIGURATION_DEP
88                                 SettingsSection config;
89                                 config = (SettingsSection) System.Configuration.ConfigurationManager.GetSection ("system.net/settings");
90                                 if (config != null)
91                                         ipv6Supported = config.Ipv6.Enabled ? -1 : 0;
92 #else
93                                 NetConfig config = System.Configuration.ConfigurationSettings.GetConfig("system.net/settings") as NetConfig;
94                                 if (config != null)
95                                         ipv6Supported = config.ipv6Enabled ? -1 : 0;
96 #endif
97 #endif
98                                 if (ipv6Supported != 0) {
99                                         try {
100                                                 Socket tmp = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
101                                                 tmp.Close();
102
103                                                 ipv6Supported = 1;
104                                         } catch {
105                                                 ipv6Supported = 0;
106                                         }
107                                 }
108                         }
109                 }
110
111                 public static bool SupportsIPv4 {
112                         get {
113                                 CheckProtocolSupport();
114                                 return ipv4Supported == 1;
115                         }
116                 }
117
118 #if NET_2_0
119                 [ObsoleteAttribute ("Use OSSupportsIPv6 instead")]
120 #endif
121                 public static bool SupportsIPv6 {
122                         get {
123                                 CheckProtocolSupport();
124                                 return ipv6Supported == 1;
125                         }
126                 }
127 #if NET_2_1
128                 public static bool OSSupportsIPv4 {
129                         get {
130                                 CheckProtocolSupport();
131                                 return ipv4Supported == 1;
132                         }
133                 }
134 #endif
135 #if NET_2_1
136                 public static bool OSSupportsIPv6 {
137                         get {
138                                 CheckProtocolSupport();
139                                 return ipv6Supported == 1;
140                         }
141                 }
142 #elif NET_2_0
143                 public static bool OSSupportsIPv6 {
144                         get {
145                                 NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces ();
146                                 
147                                 foreach (NetworkInterface adapter in nics) {
148                                         if (adapter.Supports (NetworkInterfaceComponent.IPv6))
149                                                 return true;
150                                 }
151                                 return false;
152                         }
153                 }
154 #endif
155
156                 /* the field "socket" is looked up by name by the runtime */
157                 private IntPtr socket;
158                 private AddressFamily address_family;
159                 private SocketType socket_type;
160                 private ProtocolType protocol_type;
161                 internal bool blocking=true;
162                 Thread blocking_thread;
163 #if NET_2_0
164                 private bool isbound;
165 #endif
166                 /* When true, the socket was connected at the time of
167                  * the last IO operation
168                  */
169                 private bool connected;
170                 /* true if we called Close_internal */
171                 private bool closed;
172                 internal bool disposed;
173
174                 /*
175                  * This EndPoint is used when creating new endpoints. Because
176                  * there are many types of EndPoints possible,
177                  * seed_endpoint.Create(addr) is used for creating new ones.
178                  * As such, this value is set on Bind, SentTo, ReceiveFrom,
179                  * Connect, etc.
180                  */
181                 internal EndPoint seed_endpoint = null;
182
183 #if !TARGET_JVM
184                 // Creates a new system socket, returning the handle
185                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
186                 private extern IntPtr Socket_internal(AddressFamily family,
187                                                       SocketType type,
188                                                       ProtocolType proto,
189                                                       out int error);
190 #endif          
191                 
192                 public Socket(AddressFamily family, SocketType type, ProtocolType proto)
193                 {
194                         address_family=family;
195                         socket_type=type;
196                         protocol_type=proto;
197                         
198                         int error;
199                         
200                         socket = Socket_internal (family, type, proto, out error);
201                         if (error != 0)
202                                 throw new SocketException (error);
203 #if !NET_2_1
204                         SocketDefaults ();
205 #endif
206                 }
207
208                 ~Socket ()
209                 {
210                         Dispose (false);
211                 }
212
213
214                 public AddressFamily AddressFamily {
215                         get { return address_family; }
216                 }
217
218 #if !TARGET_JVM
219                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
220                 private extern static void Blocking_internal(IntPtr socket,
221                                                              bool block,
222                                                              out int error);
223 #endif
224                 public bool Blocking {
225                         get {
226                                 return(blocking);
227                         }
228                         set {
229                                 if (disposed && closed)
230                                         throw new ObjectDisposedException (GetType ().ToString ());
231
232                                 int error;
233                                 
234                                 Blocking_internal (socket, value, out error);
235
236                                 if (error != 0)
237                                         throw new SocketException (error);
238                                 
239                                 blocking=value;
240                         }
241                 }
242
243                 public bool Connected {
244                         get { return connected; }
245                         internal set { connected = value; }
246                 }
247
248                 public ProtocolType ProtocolType {
249                         get { return protocol_type; }
250                 }
251 #if NET_2_0
252                 public bool NoDelay {
253                         get {
254                                 if (disposed && closed)
255                                         throw new ObjectDisposedException (GetType ().ToString ());
256
257                                 ThrowIfUpd ();
258
259                                 return (int)(GetSocketOption (
260                                         SocketOptionLevel.Tcp,
261                                         SocketOptionName.NoDelay)) != 0;
262                         }
263
264                         set {
265                                 if (disposed && closed)
266                                         throw new ObjectDisposedException (GetType ().ToString ());
267
268                                 ThrowIfUpd ();
269
270                                 SetSocketOption (
271                                         SocketOptionLevel.Tcp,
272                                         SocketOptionName.NoDelay, value ? 1 : 0);
273                         }
274                 }
275
276                 public int ReceiveBufferSize {
277                         get {
278                                 if (disposed && closed) {
279                                         throw new ObjectDisposedException (GetType ().ToString ());
280                                 }
281                                 return((int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer));
282                         }
283                         set {
284                                 if (disposed && closed) {
285                                         throw new ObjectDisposedException (GetType ().ToString ());
286                                 }
287                                 if (value < 0) {
288                                         throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
289                                 }
290                                 
291                                 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, value);
292                         }
293                 }
294
295                 public int SendBufferSize {
296                         get {
297                                 if (disposed && closed) {
298                                         throw new ObjectDisposedException (GetType ().ToString ());
299                                 }
300                                 return((int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendBuffer));
301                         }
302                         set {
303                                 if (disposed && closed) {
304                                         throw new ObjectDisposedException (GetType ().ToString ());
305                                 }
306                                 if (value < 0) {
307                                         throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
308                                 }
309                                 
310                                 SetSocketOption (SocketOptionLevel.Socket,
311                                                  SocketOptionName.SendBuffer,
312                                                  value);
313                         }
314                 }
315
316                 public short Ttl {
317                         get {
318                                 if (disposed && closed) {
319                                         throw new ObjectDisposedException (GetType ().ToString ());
320                                 }
321                                 
322                                 short ttl_val;
323                                 
324                                 if (address_family == AddressFamily.InterNetwork) {
325                                         ttl_val = (short)((int)GetSocketOption (SocketOptionLevel.IP, SocketOptionName.IpTimeToLive));
326                                 } else if (address_family == AddressFamily.InterNetworkV6) {
327                                         ttl_val = (short)((int)GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.HopLimit));
328                                 } else {
329                                         throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
330                                 }
331                                 
332                                 return(ttl_val);
333                         }
334                         set {
335                                 if (disposed && closed) {
336                                         throw new ObjectDisposedException (GetType ().ToString ());
337                                 }
338                                 
339                                 if (address_family == AddressFamily.InterNetwork) {
340                                         SetSocketOption (SocketOptionLevel.IP, SocketOptionName.IpTimeToLive, value);
341                                 } else if (address_family == AddressFamily.InterNetworkV6) {
342                                         SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.HopLimit, value);
343                                 } else {
344                                         throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
345                                 }
346                         }
347                 }
348 #endif
349                 // Returns the remote endpoint details in addr and port
350                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
351                 private extern static SocketAddress RemoteEndPoint_internal(IntPtr socket, out int error);
352
353                 public EndPoint RemoteEndPoint {
354                         get {
355                                 if (disposed && closed)
356                                         throw new ObjectDisposedException (GetType ().ToString ());
357                                 
358                                 /*
359                                  * If the seed EndPoint is null, Connect, Bind,
360                                  * etc has not yet been called. MS returns null
361                                  * in this case.
362                                  */
363                                 if (seed_endpoint == null)
364                                         return null;
365                                 
366                                 SocketAddress sa;
367                                 int error;
368                                 
369                                 sa=RemoteEndPoint_internal(socket, out error);
370
371                                 if (error != 0)
372                                         throw new SocketException (error);
373
374                                 return seed_endpoint.Create (sa);
375                         }
376                 }
377
378                 protected virtual void Dispose (bool explicitDisposing)
379                 {
380                         if (disposed)
381                                 return;
382
383                         disposed = true;
384                         connected = false;
385                         if ((int) socket != -1) {
386                                 int error;
387                                 closed = true;
388                                 IntPtr x = socket;
389                                 socket = (IntPtr) (-1);
390                                 Close_internal (x, out error);
391                                 if (blocking_thread != null) {
392                                         blocking_thread.Abort ();
393                                         blocking_thread = null;
394                                 }
395                                 if (error != 0)
396                                         throw new SocketException (error);
397                         }
398                 }
399
400 #if NET_2_1
401                 public void Dispose ()
402 #else
403                 void IDisposable.Dispose ()
404 #endif
405                 {
406                         Dispose (true);
407                         GC.SuppressFinalize (this);
408                 }
409
410                 // Closes the socket
411                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
412                 private extern static void Close_internal(IntPtr socket, out int error);
413
414                 public void Close ()
415                 {
416                         ((IDisposable) this).Dispose ();
417                 }
418
419                 // Connects to the remote address
420                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
421                 private extern static void Connect_internal(IntPtr sock,
422                                                             SocketAddress sa,
423                                                             out int error);
424
425                 public void Connect (EndPoint remote_end)
426                 {
427                         SocketAddress serial = null;
428
429                         if (disposed && closed)
430                                 throw new ObjectDisposedException (GetType ().ToString ());
431
432                         if (remote_end == null)
433                                 throw new ArgumentNullException("remote_end");
434
435                         if (remote_end is IPEndPoint) {
436                                 IPEndPoint ep = (IPEndPoint) remote_end;
437                                 if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any))
438                                         throw new SocketException ((int) SocketError.AddressNotAvailable);
439                         }
440 #if NET_2_1
441                         if (protocol_type != ProtocolType.Tcp)
442                                 throw new SocketException ((int) SocketError.AccessDenied);
443
444                         DnsEndPoint dep = (remote_end as DnsEndPoint);
445                         if (dep != null)
446                                 serial = dep.AsIPEndPoint ().Serialize ();
447                         else
448                                 serial = remote_end.Serialize ();
449 #elif NET_2_0
450                         /* TODO: check this for the 1.1 profile too */
451                         if (islistening)
452                                 throw new InvalidOperationException ();
453
454                         serial = remote_end.Serialize ();
455 #else
456                         serial = remote_end.Serialize ();
457 #endif
458
459                         int error = 0;
460
461                         blocking_thread = Thread.CurrentThread;
462                         try {
463                                 Connect_internal (socket, serial, out error);
464                         } catch (ThreadAbortException) {
465                                 if (disposed) {
466                                         Thread.ResetAbort ();
467                                         error = (int) SocketError.Interrupted;
468                                 }
469                         } finally {
470                                 blocking_thread = null;
471                         }
472
473                         if (error != 0)
474                                 throw new SocketException (error);
475
476                         connected=true;
477
478 #if NET_2_0
479                         isbound = true;
480 #endif
481                         
482                         seed_endpoint = remote_end;
483                 }
484
485 #if NET_2_0
486                 public bool ReceiveAsync (SocketAsyncEventArgs e)
487                 {
488                         // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
489                         //
490                         // LAME SPEC: the ArgumentException is never thrown, instead an NRE is
491                         // thrown when e.Buffer and e.BufferList are null (works fine when one is
492                         // set to a valid object)
493                         if (disposed && closed)
494                                 throw new ObjectDisposedException (GetType ().ToString ());
495
496                         // We do not support recv into multiple buffers yet
497                         if (e.BufferList != null)
498                                 throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
499                         
500                         e.DoOperation (SocketAsyncOperation.Receive, this);
501
502                         // We always return true for now
503                         return true;
504                 }
505
506                 public bool SendAsync (SocketAsyncEventArgs e)
507                 {
508                         // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
509                         
510                         if (disposed && closed)
511                                 throw new ObjectDisposedException (GetType ().ToString ());
512                         if (e.Buffer == null && e.BufferList == null)
513                                 throw new ArgumentException ("Either e.Buffer or e.BufferList must be valid buffers.");
514
515                         e.DoOperation (SocketAsyncOperation.Send, this);
516
517                         // We always return true for now
518                         return true;
519                 }
520 #endif
521
522                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
523                 extern static bool Poll_internal (IntPtr socket, SelectMode mode, int timeout, out int error);
524
525                 /* This overload is needed as the async Connect method
526                  * also needs to check the socket error status, but
527                  * getsockopt(..., SO_ERROR) clears the error.
528                  */
529                 internal bool Poll (int time_us, SelectMode mode, out int socket_error)
530                 {
531                         if (disposed && closed)
532                                 throw new ObjectDisposedException (GetType ().ToString ());
533
534                         if (mode != SelectMode.SelectRead &&
535                             mode != SelectMode.SelectWrite &&
536                             mode != SelectMode.SelectError)
537                                 throw new NotSupportedException ("'mode' parameter is not valid.");
538
539                         int error;
540                         bool result = Poll_internal (socket, mode, time_us, out error);
541                         if (error != 0)
542                                 throw new SocketException (error);
543
544                         socket_error = (int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
545                         
546                         if (mode == SelectMode.SelectWrite && result) {
547                                 /* Update the connected state; for
548                                  * non-blocking Connect()s this is
549                                  * when we can find out that the
550                                  * connect succeeded.
551                                  */
552                                 if (socket_error == 0) {
553                                         connected = true;
554                                 }
555                         }
556                         
557                         return result;
558                 }
559
560                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
561                 private extern static int Receive_internal(IntPtr sock,
562                                                            byte[] buffer,
563                                                            int offset,
564                                                            int count,
565                                                            SocketFlags flags,
566                                                            out int error);
567
568                 internal int Receive_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
569                 {
570                         int nativeError;
571                         int ret = Receive_internal (socket, buf, offset, size, flags, out nativeError);
572                         error = (SocketError) nativeError;
573                         if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress)
574                                 connected = false;
575                         else
576                                 connected = true;
577                         
578                         return ret;
579                 }
580
581                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
582                 private extern static void GetSocketOption_obj_internal(IntPtr socket,
583                         SocketOptionLevel level, SocketOptionName name, out object obj_val,
584                         out int error);
585
586                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
587                 private extern static int Send_internal(IntPtr sock,
588                                                         byte[] buf, int offset,
589                                                         int count,
590                                                         SocketFlags flags,
591                                                         out int error);
592
593                 internal int Send_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
594                 {
595                         if (size == 0) {
596                                 error = SocketError.Success;
597                                 return 0;
598                         }
599
600                         int nativeError;
601
602                         int ret = Send_internal (socket, buf, offset, size, flags, out nativeError);
603
604                         error = (SocketError)nativeError;
605
606                         if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress)
607                                 connected = false;
608                         else
609                                 connected = true;
610
611                         return ret;
612                 }
613
614                 public object GetSocketOption (SocketOptionLevel level, SocketOptionName name)
615                 {
616                         if (disposed && closed)
617                                 throw new ObjectDisposedException (GetType ().ToString ());
618
619                         object obj_val;
620                         int error;
621                         
622                         GetSocketOption_obj_internal(socket, level, name, out obj_val,
623                                 out error);
624                         if (error != 0)
625                                 throw new SocketException (error);
626                         
627                         if (name == SocketOptionName.Linger) {
628                                 return((LingerOption)obj_val);
629                         } else if (name==SocketOptionName.AddMembership ||
630                                    name==SocketOptionName.DropMembership) {
631                                 return((MulticastOption)obj_val);
632                         } else if (obj_val is int) {
633                                 return((int)obj_val);
634                         } else {
635                                 return(obj_val);
636                         }
637                 }
638
639                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
640                 private extern static void Shutdown_internal (IntPtr socket, SocketShutdown how, out int error);
641                 
642                 public void Shutdown (SocketShutdown how)
643                 {
644                         if (disposed && closed)
645                                 throw new ObjectDisposedException (GetType ().ToString ());
646
647                         int error;
648                         
649                         Shutdown_internal (socket, how, out error);
650
651                         if (error != 0)
652                                 throw new SocketException (error);
653                 }
654
655                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
656                 private extern static void SetSocketOption_internal (IntPtr socket, SocketOptionLevel level,
657                                                                      SocketOptionName name, object obj_val,
658                                                                      byte [] byte_val, int int_val,
659                                                                      out int error);
660
661                 public void SetSocketOption (SocketOptionLevel level, SocketOptionName name, int opt_value)
662                 {
663                         if (disposed && closed)
664                                 throw new ObjectDisposedException (GetType ().ToString ());
665
666                         int error;
667                         
668                         SetSocketOption_internal(socket, level, name, null,
669                                                  null, opt_value, out error);
670
671                         if (error != 0)
672                                 throw new SocketException (error);
673                 }
674
675                 private void ThrowIfUpd ()
676                 {
677 #if !NET_2_1
678                         if (protocol_type == ProtocolType.Udp)
679                                 throw new SocketException ((int)SocketError.ProtocolOption);
680 #endif
681                 }
682
683 #if NET_2_1
684                 static MethodInfo check_socket_policy;
685
686                 static void CheckConnect (SocketAsyncEventArgs e, bool checkPolicy)
687                 {
688                         // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
689
690                         if (e.RemoteEndPoint == null)
691                                 throw new ArgumentNullException ("remoteEP");
692                         if (e.BufferList != null)
693                                 throw new ArgumentException ("Multiple buffers cannot be used with this method.");
694
695                         if (!checkPolicy)
696                                 return;
697
698                         if (check_socket_policy == null) {
699                                 Type type = Type.GetType ("System.Windows.Browser.Net.CrossDomainPolicyManager, System.Windows.Browser, Version=2.0.5.0, Culture=Neutral, PublicKeyToken=7cec85d7bea7798e");
700                                 check_socket_policy = type.GetMethod ("CheckEndPoint");
701                                 if (check_socket_policy == null)
702                                         throw new SecurityException ();
703                         }
704                         if (!(bool) check_socket_policy.Invoke (null, new object [1] { e.RemoteEndPoint }))
705                                 throw new SecurityException ();
706                 }
707
708                 // only _directly_ used (with false) to download the socket policy
709                 internal bool ConnectAsync (SocketAsyncEventArgs e, bool checkPolicy)
710                 {
711                         if (disposed && closed)
712                                 throw new ObjectDisposedException (GetType ().ToString ());
713
714                         CheckConnect (e, checkPolicy);
715
716                         e.DoOperation (SocketAsyncOperation.Connect, this);
717
718                         // We always return true for now
719                         return true;
720                 }
721
722                 public bool ConnectAsync (SocketAsyncEventArgs e)
723                 {
724                         return ConnectAsync (e, true);
725                 }
726
727                 public static bool ConnectAsync (SocketType socketType, ProtocolType protocolType, SocketAsyncEventArgs e)
728                 {
729                         CheckConnect (e, true);
730
731                         Socket s = new Socket (AddressFamily.InterNetwork, socketType, protocolType);
732                         e.DoOperation (SocketAsyncOperation.Connect, s);
733
734                         // We always return true for now
735                         return true;
736                 }
737
738                 public static void CancelConnectAsync (SocketAsyncEventArgs e)
739                 {
740                         if (e == null)
741                                 throw new ArgumentNullException ("e");
742
743                         Socket s = e.ConnectSocket;
744                         if ((s != null) && (s.blocking_thread != null))
745                                 s.blocking_thread.Abort ();
746                 }
747 #endif
748         }
749 }
750