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