[Socket] Move properties to their own region
[mono.git] / mcs / class / System / System.Net.Sockets / Socket.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-2011 Novell, Inc. (http://www.novell.com)
13 //
14 //
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
22 // 
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
25 // 
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 //
34
35 using System;
36 using System.Net;
37 using System.Collections;
38 using System.Collections.Generic;
39 using System.Runtime.CompilerServices;
40 using System.Runtime.InteropServices;
41 using System.Threading;
42 using System.Reflection;
43 using System.IO;
44 using System.Net.Configuration;
45 using System.Text;
46 using System.Timers;
47 using System.Net.NetworkInformation;
48
49 namespace System.Net.Sockets 
50 {
51         public partial class Socket : IDisposable
52         {
53                 const int SOCKET_CLOSED_CODE = 10004;
54                 const string TIMEOUT_EXCEPTION_MSG = "A connection attempt failed because the connected party did not properly respond" +
55                         "after a period of time, or established connection failed because connected host has failed to respond";
56
57                 /*
58                  *      These two fields are looked up by name by the runtime, don't change
59                  *  their name without also updating the runtime code.
60                  */
61                 static int ipv4_supported = -1;
62                 static int ipv6_supported = -1;
63
64                 /* true if we called Close_internal */
65                 bool is_closed;
66
67                 bool is_listening;
68                 bool use_overlapped_io;
69
70                 int linger_timeout;
71
72                 /* the field "safe_handle" is looked up by name by the runtime */
73                 SafeSocketHandle safe_handle;
74
75                 AddressFamily address_family;
76                 SocketType socket_type;
77                 ProtocolType protocol_type;
78
79                 /*
80                  * This EndPoint is used when creating new endpoints. Because
81                  * there are many types of EndPoints possible,
82                  * seed_endpoint.Create(addr) is used for creating new ones.
83                  * As such, this value is set on Bind, SentTo, ReceiveFrom,
84                  * Connect, etc.
85                  */
86                 internal EndPoint seed_endpoint = null;
87
88                 internal Queue readQ = new Queue (2);
89                 internal Queue writeQ = new Queue (2);
90
91                 internal bool is_blocking = true;
92                 internal bool is_bound;
93
94                 /* When true, the socket was connected at the time of the last IO operation */
95                 internal bool is_connected;
96
97                 internal bool is_disposed;
98                 internal bool connect_in_progress;
99
100 #region Constructors
101
102                 static Socket ()
103                 {
104                         if (ipv4_supported == -1) {
105                                 try {
106                                         Socket tmp = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
107                                         tmp.Close();
108
109                                         ipv4_supported = 1;
110                                 } catch {
111                                         ipv4_supported = 0;
112                                 }
113                         }
114
115                         if (ipv6_supported == -1) {
116                                 // We need to put a try/catch around ConfigurationManager methods as will always throw an exception 
117                                 // when run in a mono embedded application.  This occurs as embedded applications do not have a setup
118                                 // for application config.  The exception is not thrown when called from a normal .NET application. 
119                                 //
120                                 // We, then, need to guard calls to the ConfigurationManager.  If the config is not found or throws an
121                                 // exception, will fall through to the existing Socket / API directly below in the code.
122                                 //
123                                 // Also note that catching ConfigurationErrorsException specifically would require library dependency
124                                 // System.Configuration, and wanted to avoid that.
125 #if !NET_2_1
126 #if CONFIGURATION_DEP
127                                 try {
128                                         SettingsSection config;
129                                         config = (SettingsSection) System.Configuration.ConfigurationManager.GetSection ("system.net/settings");
130                                         if (config != null)
131                                                 ipv6_supported = config.Ipv6.Enabled ? -1 : 0;
132                                 } catch {
133                                         ipv6_supported = -1;
134                                 }
135 #else
136                                 try {
137                                         NetConfig config = System.Configuration.ConfigurationSettings.GetConfig("system.net/settings") as NetConfig;
138                                         if (config != null)
139                                                 ipv6_supported = config.ipv6Enabled ? -1 : 0;
140                                 } catch {
141                                         ipv6_supported = -1;
142                                 }
143 #endif
144 #endif
145                                 if (ipv6_supported != 0) {
146                                         try {
147                                                 Socket tmp = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
148                                                 tmp.Close();
149
150                                                 ipv6_supported = 1;
151                                         } catch {
152                                                 ipv6_supported = 0;
153                                         }
154                                 }
155                         }
156                 }
157
158                 [MonoTODO ("Currently hardcoded to IPv4. Ideally, support v4/v6 dual-stack.")]
159                 public Socket (SocketType socketType, ProtocolType protocolType)
160                         : this (AddressFamily.InterNetwork, socketType, protocolType)
161                 {
162                 }
163                 
164                 public Socket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)
165                 {
166 #if NET_2_1 && !MOBILE
167                         switch (addressFamily) {
168                         case AddressFamily.InterNetwork:    // ok
169                         case AddressFamily.InterNetworkV6:  // ok
170                         case AddressFamily.Unknown:         // SocketException will be thrown later (with right error #)
171                                 break;
172                         // case AddressFamily.Unspecified:
173                         default:
174                                 throw new ArgumentException ("addressFamily");
175                         }
176
177                         switch (socketType) {
178                         case SocketType.Stream:             // ok
179                         case SocketType.Unknown:            // SocketException will be thrown later (with right error #)
180                                 break;
181                         default:
182                                 throw new ArgumentException ("socketType");
183                         }
184
185                         switch (protocolType) {
186                         case ProtocolType.Tcp:              // ok
187                         case ProtocolType.Unspecified:      // ok
188                         case ProtocolType.Unknown:          // SocketException will be thrown later (with right error #)
189                                 break;
190                         default:
191                                 throw new ArgumentException ("protocolType");
192                         }
193 #endif
194                         this.address_family = addressFamily;
195                         this.socket_type = socketType;
196                         this.protocol_type = protocolType;
197                         
198                         int error;
199                         var handle = Socket_internal (addressFamily, socketType, protocolType, out error);
200
201                         this.safe_handle = new SafeSocketHandle (handle, true);
202
203                         if (error != 0)
204                                 throw new SocketException (error);
205
206 #if !NET_2_1 || MOBILE
207                         SocketDefaults ();
208 #endif
209                 }
210
211 #if !MOBILE
212                 public Socket (SocketInformation socketInformation)
213                 {
214                         this.is_listening      = (socketInformation.Options & SocketInformationOptions.Listening) != 0;
215                         this.is_connected      = (socketInformation.Options & SocketInformationOptions.Connected) != 0;
216                         this.is_blocking       = (socketInformation.Options & SocketInformationOptions.NonBlocking) == 0;
217                         this.use_overlapped_io = (socketInformation.Options & SocketInformationOptions.UseOnlyOverlappedIO) != 0;
218
219                         var result = Mono.DataConverter.Unpack ("iiiil", socketInformation.ProtocolInformation, 0);
220
221                         this.address_family = (AddressFamily) (int) result [0];
222                         this.socket_type = (SocketType) (int) result [1];
223                         this.protocol_type = (ProtocolType) (int) result [2];
224                         this.is_bound = (ProtocolType) (int) result [3] != 0;
225                         this.safe_handle = new SafeSocketHandle ((IntPtr) (long) result [4], true);
226
227                         SocketDefaults ();
228                 }
229 #endif
230
231                 /* private constructor used by Accept, which already has a socket handle to use */
232                 internal Socket(AddressFamily family, SocketType type, ProtocolType proto, SafeSocketHandle safe_handle)
233                 {
234                         this.address_family = family;
235                         this.socket_type = type;
236                         this.protocol_type = proto;
237                         
238                         this.safe_handle = safe_handle;
239                         this.is_connected = true;
240                 }
241
242                 ~Socket ()
243                 {
244                         Dispose (false);
245                 }
246
247                 void SocketDefaults ()
248                 {
249                         try {
250                                 /* Need to test IPv6 further */
251                                 if (address_family == AddressFamily.InterNetwork
252                                         // || address_family == AddressFamily.InterNetworkV6
253                                 ) {
254                                         /* This is the default, but it probably has nasty side
255                                          * effects on Linux, as the socket option is kludged by
256                                          * turning on or off PMTU discovery... */
257                                         this.DontFragment = false;
258                                 }
259
260                                 /* Microsoft sets these to 8192, but we are going to keep them
261                                  * both to the OS defaults as these have a big performance impact.
262                                  * on WebClient performance. */
263                                 // this.ReceiveBufferSize = 8192;
264                                 // this.SendBufferSize = 8192;
265                         } catch (SocketException) {
266                         }
267                 }
268
269                 /* Creates a new system socket, returning the handle */
270                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
271                 extern IntPtr Socket_internal (AddressFamily family, SocketType type, ProtocolType proto, out int error);
272
273 #endregion
274
275 #region Properties
276
277                 public static bool SupportsIPv4 {
278                         get { return ipv4_supported == 1; }
279                 }
280
281                 [ObsoleteAttribute ("Use OSSupportsIPv6 instead")]
282                 public static bool SupportsIPv6 {
283                         get { return ipv6_supported == 1; }
284                 }
285
286 #if NET_2_1
287                 public static bool OSSupportsIPv4 {
288                         get { return ipv4_supported == 1; }
289                 }
290 #endif
291
292 #if NET_2_1
293                 public static bool OSSupportsIPv6 {
294                         get { return ipv6_supported == 1; }
295                 }
296 #else
297                 public static bool OSSupportsIPv6 {
298                         get {
299                                 NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces ();
300
301                                 foreach (NetworkInterface adapter in nics) {
302                                         if (adapter.Supports (NetworkInterfaceComponent.IPv6))
303                                                 return true;
304                                 }
305
306                                 return false;
307                         }
308                 }
309 #endif
310
311                 public int Available {
312                         get {
313                                 ThrowIfDisposedAndClosed ();
314
315                                 int ret, error;
316                                 ret = Available_internal (safe_handle, out error);
317
318                                 if (error != 0)
319                                         throw new SocketException (error);
320
321                                 return ret;
322                         }
323                 }
324
325                 static int Available_internal (SafeSocketHandle safeHandle, out int error)
326                 {
327                         bool release = false;
328                         try {
329                                 safeHandle.DangerousAddRef (ref release);
330                                 return Available_internal (safeHandle.DangerousGetHandle (), out error);
331                         } finally {
332                                 if (release)
333                                         safeHandle.DangerousRelease ();
334                         }
335                 }
336
337                 /* Returns the amount of data waiting to be read on socket */
338                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
339                 extern static int Available_internal (IntPtr socket, out int error);
340
341                 public bool DontFragment {
342                         get {
343                                 ThrowIfDisposedAndClosed ();
344
345                                 switch (address_family) {
346                                 case AddressFamily.InterNetwork:
347                                         return ((int) GetSocketOption (SocketOptionLevel.IP, SocketOptionName.DontFragment)) != 0;
348                                 case AddressFamily.InterNetworkV6:
349                                         return ((int) GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.DontFragment)) != 0;
350                                 default:
351                                         throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
352                                 }
353                         }
354                         set {
355                                 ThrowIfDisposedAndClosed ();
356
357                                 switch (address_family) {
358                                 case AddressFamily.InterNetwork:
359                                         SetSocketOption (SocketOptionLevel.IP, SocketOptionName.DontFragment, value ? 1 : 0);
360                                         break;
361                                 case AddressFamily.InterNetworkV6:
362                                         SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.DontFragment, value ? 1 : 0);
363                                         break;
364                                 default:
365                                         throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
366                                 }
367                         }
368                 }
369
370                 public bool EnableBroadcast {
371                         get {
372                                 ThrowIfDisposedAndClosed ();
373
374                                 if (protocol_type != ProtocolType.Udp)
375                                         throw new SocketException ((int) SocketError.ProtocolOption);
376
377                                 return ((int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Broadcast)) != 0;
378                         }
379                         set {
380                                 ThrowIfDisposedAndClosed ();
381
382                                 if (protocol_type != ProtocolType.Udp)
383                                         throw new SocketException ((int) SocketError.ProtocolOption);
384
385                                 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Broadcast, value ? 1 : 0);
386                         }
387                 }
388
389                 public bool ExclusiveAddressUse {
390                         get {
391                                 ThrowIfDisposedAndClosed ();
392
393                                 return ((int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse)) != 0;
394                         }
395                         set {
396                                 ThrowIfDisposedAndClosed ();
397
398                                 if (is_bound)
399                                         throw new InvalidOperationException ("Bind has already been called for this socket");
400
401                                 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse, value ? 1 : 0);
402                         }
403                 }
404
405                 public bool IsBound {
406                         get {
407                                 return is_bound;
408                         }
409                 }
410
411                 public LingerOption LingerState {
412                         get {
413                                 ThrowIfDisposedAndClosed ();
414
415                                 return (LingerOption) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Linger);
416                         }
417                         set {
418                                 ThrowIfDisposedAndClosed ();
419                                 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Linger, value);
420                         }
421                 }
422
423                 public bool MulticastLoopback {
424                         get {
425                                 ThrowIfDisposedAndClosed ();
426
427                                 /* Even though this option can be set for TCP sockets on Linux, throw
428                                  * this exception anyway to be compatible (the MSDN docs say
429                                  * "Setting this property on a Transmission Control Protocol (TCP)
430                                  * socket will have no effect." but the MS runtime throws the
431                                  * exception...) */
432                                 if (protocol_type == ProtocolType.Tcp)
433                                         throw new SocketException ((int)SocketError.ProtocolOption);
434
435                                 switch (address_family) {
436                                 case AddressFamily.InterNetwork:
437                                         return ((int) GetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastLoopback)) != 0;
438                                 case AddressFamily.InterNetworkV6:
439                                         return ((int) GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback)) != 0;
440                                 default:
441                                         throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
442                                 }
443                         }
444                         set {
445                                 ThrowIfDisposedAndClosed ();
446
447                                 /* Even though this option can be set for TCP sockets on Linux, throw
448                                  * this exception anyway to be compatible (the MSDN docs say
449                                  * "Setting this property on a Transmission Control Protocol (TCP)
450                                  * socket will have no effect." but the MS runtime throws the
451                                  * exception...) */
452                                 if (protocol_type == ProtocolType.Tcp)
453                                         throw new SocketException ((int)SocketError.ProtocolOption);
454
455                                 switch (address_family) {
456                                 case AddressFamily.InterNetwork:
457                                         SetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastLoopback, value ? 1 : 0);
458                                         break;
459                                 case AddressFamily.InterNetworkV6:
460                                         SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback, value ? 1 : 0);
461                                         break;
462                                 default:
463                                         throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
464                                 }
465                         }
466                 }
467
468                 [MonoTODO ("This doesn't do anything on Mono yet")]
469                 public bool UseOnlyOverlappedIO {
470                         get { return use_overlapped_io; }
471                         set { use_overlapped_io = value; }
472                 }
473
474                 public IntPtr Handle {
475                         get { return safe_handle.DangerousGetHandle (); }
476                 }
477
478                 // Wish:  support non-IP endpoints.
479                 public EndPoint LocalEndPoint {
480                         get {
481                                 ThrowIfDisposedAndClosed ();
482
483                                 /* If the seed EndPoint is null, Connect, Bind, etc has not yet
484                                  * been called. MS returns null in this case. */
485                                 if (seed_endpoint == null)
486                                         return null;
487
488                                 int error;
489                                 SocketAddress sa = LocalEndPoint_internal (safe_handle, (int) address_family, out error);
490
491                                 if (error != 0)
492                                         throw new SocketException (error);
493
494                                 return seed_endpoint.Create (sa);
495                         }
496                 }
497
498                 static SocketAddress LocalEndPoint_internal (SafeSocketHandle safeHandle, int family, out int error)
499                 {
500                         bool release = false;
501                         try {
502                                 safeHandle.DangerousAddRef (ref release);
503                                 return LocalEndPoint_internal (safeHandle.DangerousGetHandle (), family, out error);
504                         } finally {
505                                 if (release)
506                                         safeHandle.DangerousRelease ();
507                         }
508                 }
509
510                 /* Returns the local endpoint details in addr and port */
511                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
512                 extern static SocketAddress LocalEndPoint_internal (IntPtr socket, int family, out int error);
513
514                 public SocketType SocketType {
515                         get { return socket_type; }
516                 }
517
518                 public int SendTimeout {
519                         get {
520                                 ThrowIfDisposedAndClosed ();
521
522                                 return (int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendTimeout);
523                         }
524                         set {
525                                 ThrowIfDisposedAndClosed ();
526
527                                 if (value < -1)
528                                         throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than -1");
529
530                                 /* According to the MSDN docs we should adjust values between 1 and
531                                  * 499 to 500, but the MS runtime doesn't do this. */
532                                 if (value == -1)
533                                         value = 0;
534
535                                 SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, value);
536                         }
537                 }
538
539                 public int ReceiveTimeout {
540                         get {
541                                 ThrowIfDisposedAndClosed ();
542
543                                 return (int) GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout);
544                         }
545                         set {
546                                 ThrowIfDisposedAndClosed ();
547
548                                 if (value < -1)
549                                         throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than -1");
550
551                                 if (value == -1)
552                                         value = 0;
553
554                                 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, value);
555                         }
556                 }
557
558                 public AddressFamily AddressFamily {
559                         get { return address_family; }
560                 }
561
562                 public bool Blocking {
563                         get { return is_blocking; }
564                         set {
565                                 ThrowIfDisposedAndClosed ();
566
567                                 int error;
568                                 Blocking_internal (safe_handle, value, out error);
569
570                                 if (error != 0)
571                                         throw new SocketException (error);
572
573                                 is_blocking = value;
574                         }
575                 }
576
577                 static void Blocking_internal (SafeSocketHandle safeHandle, bool block, out int error)
578                 {
579                         bool release = false;
580                         try {
581                                 safeHandle.DangerousAddRef (ref release);
582                                 Blocking_internal (safeHandle.DangerousGetHandle (), block, out error);
583                         } finally {
584                                 if (release)
585                                         safeHandle.DangerousRelease ();
586                         }
587                 }
588
589                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
590                 internal extern static void Blocking_internal(IntPtr socket, bool block, out int error);
591
592                 public bool Connected {
593                         get { return is_connected; }
594                         internal set { is_connected = value; }
595                 }
596
597                 public ProtocolType ProtocolType {
598                         get { return protocol_type; }
599                 }
600
601                 public bool NoDelay {
602                         get {
603                                 ThrowIfDisposedAndClosed ();
604                                 ThrowIfUdp ();
605
606                                 return ((int) GetSocketOption (SocketOptionLevel.Tcp, SocketOptionName.NoDelay)) != 0;
607                         }
608
609                         set {
610                                 ThrowIfDisposedAndClosed ();
611                                 ThrowIfUdp ();
612
613                                 SetSocketOption (SocketOptionLevel.Tcp, SocketOptionName.NoDelay, value ? 1 : 0);
614                         }
615                 }
616
617                 public int ReceiveBufferSize {
618                         get {
619                                 ThrowIfDisposedAndClosed ();
620
621                                 return (int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer);
622                         }
623                         set {
624                                 ThrowIfDisposedAndClosed ();
625
626                                 if (value < 0)
627                                         throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
628
629                                 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, value);
630                         }
631                 }
632
633                 public int SendBufferSize {
634                         get {
635                                 ThrowIfDisposedAndClosed ();
636
637                                 return (int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendBuffer);
638                         }
639                         set {
640                                 ThrowIfDisposedAndClosed ();
641
642                                 if (value < 0)
643                                         throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
644
645                                 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendBuffer, value);
646                         }
647                 }
648
649                 public short Ttl {
650                         get {
651                                 ThrowIfDisposedAndClosed ();
652
653                                 switch (address_family) {
654                                 case AddressFamily.InterNetwork:
655                                         return (short) (int) GetSocketOption (SocketOptionLevel.IP, SocketOptionName.IpTimeToLive);
656                                 case AddressFamily.InterNetworkV6:
657                                         return (short) (int) GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.HopLimit);
658                                 default:
659                                         throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
660                                 }
661                         }
662                         set {
663                                 ThrowIfDisposedAndClosed ();
664
665                                 if (value < 0)
666                                         throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
667
668                                 switch (address_family) {
669                                 case AddressFamily.InterNetwork:
670                                         SetSocketOption (SocketOptionLevel.IP, SocketOptionName.IpTimeToLive, value);
671                                         break;
672                                 case AddressFamily.InterNetworkV6:
673                                         SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.HopLimit, value);
674                                         break;
675                                 default:
676                                         throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
677                                 }
678                         }
679                 }
680
681                 public EndPoint RemoteEndPoint {
682                         get {
683                                 ThrowIfDisposedAndClosed ();
684
685                                 /* If the seed EndPoint is null, Connect, Bind, etc has
686                                  * not yet been called. MS returns null in this case. */
687                                 if (!is_connected || seed_endpoint == null)
688                                         return null;
689
690                                 int error;
691                                 SocketAddress sa = RemoteEndPoint_internal (safe_handle, (int) address_family, out error);
692
693                                 if (error != 0)
694                                         throw new SocketException (error);
695
696                                 return seed_endpoint.Create (sa);
697                         }
698                 }
699
700                 static SocketAddress RemoteEndPoint_internal (SafeSocketHandle safeHandle, int family, out int error)
701                 {
702                         bool release = false;
703                         try {
704                                 safeHandle.DangerousAddRef (ref release);
705                                 return RemoteEndPoint_internal (safeHandle.DangerousGetHandle (), family, out error);
706                         } finally {
707                                 if (release)
708                                         safeHandle.DangerousRelease ();
709                         }
710                 }
711
712                 /* Returns the remote endpoint details in addr and port */
713                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
714                 extern static SocketAddress RemoteEndPoint_internal (IntPtr socket, int family, out int error);
715
716 #endregion
717
718 #region Select
719
720                 public static void Select (IList checkRead, IList checkWrite, IList checkError, int microSeconds)
721                 {
722                         var list = new List<Socket> ();
723                         AddSockets (list, checkRead, "checkRead");
724                         AddSockets (list, checkWrite, "checkWrite");
725                         AddSockets (list, checkError, "checkError");
726
727                         if (list.Count == 3)
728                                 throw new ArgumentNullException ("checkRead, checkWrite, checkError", "All the lists are null or empty.");
729
730                         /* The 'sockets' array contains:
731                          *  - READ socket 0-n, null,
732                          *  - WRITE socket 0-n, null,
733                          *  - ERROR socket 0-n, null */
734                         Socket [] sockets = list.ToArray ();
735
736                         int error;
737                         Select_internal (ref sockets, microSeconds, out error);
738
739                         if (error != 0)
740                                 throw new SocketException (error);
741
742                         if (sockets == null) {
743                                 if (checkRead != null)
744                                         checkRead.Clear ();
745                                 if (checkWrite != null)
746                                         checkWrite.Clear ();
747                                 if (checkError != null)
748                                         checkError.Clear ();
749                                 return;
750                         }
751
752                         int mode = 0;
753                         int count = sockets.Length;
754                         IList currentList = checkRead;
755                         int currentIdx = 0;
756                         for (int i = 0; i < count; i++) {
757                                 Socket sock = sockets [i];
758                                 if (sock == null) { // separator
759                                         if (currentList != null) {
760                                                 // Remove non-signaled sockets after the current one
761                                                 int to_remove = currentList.Count - currentIdx;
762                                                 for (int k = 0; k < to_remove; k++)
763                                                         currentList.RemoveAt (currentIdx);
764                                         }
765                                         currentList = (mode == 0) ? checkWrite : checkError;
766                                         currentIdx = 0;
767                                         mode++;
768                                         continue;
769                                 }
770
771                                 if (mode == 1 && currentList == checkWrite && !sock.is_connected) {
772                                         if ((int) sock.GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error) == 0)
773                                                 sock.is_connected = true;
774                                 }
775
776                                 /* Remove non-signaled sockets before the current one */
777                                 while (((Socket) currentList [currentIdx]) != sock)
778                                         currentList.RemoveAt (currentIdx);
779
780                                 currentIdx++;
781                         }
782                 }
783
784                 static void AddSockets (List<Socket> sockets, IList list, string name)
785                 {
786                         if (list != null) {
787                                 foreach (Socket sock in list) {
788                                         if (sock == null) // MS throws a NullRef
789                                                 throw new ArgumentNullException ("name", "Contains a null element");
790                                         sockets.Add (sock);
791                                 }
792                         }
793
794                         sockets.Add (null);
795                 }
796
797                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
798                 extern static void Select_internal (ref Socket [] sockets, int microSeconds, out int error);
799
800 #endregion
801
802                 public bool AcceptAsync (SocketAsyncEventArgs e)
803                 {
804                         // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
805                         
806                         if (is_disposed && is_closed)
807                                 throw new ObjectDisposedException (GetType ().ToString ());
808                         if (!IsBound)
809                                 throw new InvalidOperationException ("You must call the Bind method before performing this operation.");
810                         if (!is_listening)
811                                 throw new InvalidOperationException ("You must call the Listen method before performing this operation.");
812                         if (e.BufferList != null)
813                                 throw new ArgumentException ("Multiple buffers cannot be used with this method.");
814                         if (e.Count < 0)
815                                 throw new ArgumentOutOfRangeException ("e.Count");
816
817                         Socket acceptSocket = e.AcceptSocket;
818                         if (acceptSocket != null) {
819                                 if (acceptSocket.IsBound || acceptSocket.Connected)
820                                         throw new InvalidOperationException ("AcceptSocket: The socket must not be bound or connected.");
821                         }
822
823                         e.curSocket = this;
824                         SocketAsyncWorker w = e.Worker;
825                         w.Init (this, e, SocketOperation.Accept);
826                         int count;
827                         lock (readQ) {
828                                 readQ.Enqueue (e.Worker);
829                                 count = readQ.Count;
830                         }
831                         if (count == 1)
832                                 socket_pool_queue (SocketAsyncWorker.Dispatcher, w.result);
833                         return true;
834                 }
835                 // Creates a new system socket, returning the handle
836                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
837                 private extern static IntPtr Accept_internal(IntPtr sock, out int error, bool blocking);
838
839                 private static SafeSocketHandle Accept_internal(SafeSocketHandle safeHandle, out int error, bool blocking)
840                 {
841                         try {
842                                 safeHandle.RegisterForBlockingSyscall ();
843                                 var ret = Accept_internal (safeHandle.DangerousGetHandle (), out error, blocking);
844                                 return new SafeSocketHandle (ret, true);
845                         } finally {
846                                 safeHandle.UnRegisterForBlockingSyscall ();
847                         }
848                 }
849
850                 public Socket Accept() {
851                         if (is_disposed && is_closed)
852                                 throw new ObjectDisposedException (GetType ().ToString ());
853
854                         int error = 0;
855                         var sock = Accept_internal(safe_handle, out error, is_blocking);
856
857                         if (error != 0) {
858                                 if (is_closed)
859                                         error = SOCKET_CLOSED_CODE;
860                                 throw new SocketException(error);
861                         }
862
863                         Socket accepted = new Socket(this.AddressFamily, this.SocketType,
864                                 this.ProtocolType, sock);
865
866                         accepted.seed_endpoint = this.seed_endpoint;
867                         accepted.Blocking = this.Blocking;
868                         return(accepted);
869                 }
870
871                 internal void Accept (Socket acceptSocket)
872                 {
873                         if (is_disposed && is_closed)
874                                 throw new ObjectDisposedException (GetType ().ToString ());
875                         
876                         int error = 0;
877                         var sock = Accept_internal (safe_handle, out error, is_blocking);
878                         
879                         if (error != 0) {
880                                 if (is_closed)
881                                         error = SOCKET_CLOSED_CODE;
882                                 throw new SocketException (error);
883                         }
884                         
885                         acceptSocket.address_family = this.AddressFamily;
886                         acceptSocket.socket_type = this.SocketType;
887                         acceptSocket.protocol_type = this.ProtocolType;
888                         acceptSocket.safe_handle = sock;
889                         acceptSocket.is_connected = true;
890                         acceptSocket.seed_endpoint = this.seed_endpoint;
891                         acceptSocket.Blocking = this.Blocking;
892
893                         /* FIXME: figure out what if anything else
894                          * needs to be reset
895                          */
896                 }
897
898                 public IAsyncResult BeginAccept(AsyncCallback callback, object state)
899                 {
900                         if (is_disposed && is_closed)
901                                 throw new ObjectDisposedException (GetType ().ToString ());
902
903                         if (!is_bound || !is_listening)
904                                 throw new InvalidOperationException ();
905
906                         SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Accept);
907                         int count;
908                         lock (readQ) {
909                                 readQ.Enqueue (req.Worker);
910                                 count = readQ.Count;
911                         }
912                         if (count == 1)
913                                 socket_pool_queue (SocketAsyncWorker.Dispatcher, req);
914                         return req;
915                 }
916
917                 public IAsyncResult BeginAccept (int receiveSize,
918                                                  AsyncCallback callback,
919                                                  object state)
920                 {
921                         if (is_disposed && is_closed)
922                                 throw new ObjectDisposedException (GetType ().ToString ());
923
924                         if (receiveSize < 0)
925                                 throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
926
927                         SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.AcceptReceive);
928                         req.Buffer = new byte[receiveSize];
929                         req.Offset = 0;
930                         req.Size = receiveSize;
931                         req.SockFlags = SocketFlags.None;
932                         int count;
933                         lock (readQ) {
934                                 readQ.Enqueue (req.Worker);
935                                 count = readQ.Count;
936                         }
937                         if (count == 1)
938                                 socket_pool_queue (SocketAsyncWorker.Dispatcher, req);
939                         return req;
940                 }
941
942                 public IAsyncResult BeginAccept (Socket acceptSocket,
943                                                  int receiveSize,
944                                                  AsyncCallback callback,
945                                                  object state)
946                 {
947                         if (is_disposed && is_closed)
948                                 throw new ObjectDisposedException (GetType ().ToString ());
949
950                         if (receiveSize < 0)
951                                 throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
952
953                         if (acceptSocket != null) {
954                                 if (acceptSocket.is_disposed && acceptSocket.is_closed)
955                                         throw new ObjectDisposedException (acceptSocket.GetType ().ToString ());
956
957                                 if (acceptSocket.IsBound)
958                                         throw new InvalidOperationException ();
959
960                                 /* For some reason the MS runtime
961                                  * barfs if the new socket is not TCP,
962                                  * even though it's just about to blow
963                                  * away all those parameters
964                                  */
965                                 if (acceptSocket.ProtocolType != ProtocolType.Tcp)
966                                         throw new SocketException ((int)SocketError.InvalidArgument);
967                         }
968                         
969                         SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.AcceptReceive);
970                         req.Buffer = new byte[receiveSize];
971                         req.Offset = 0;
972                         req.Size = receiveSize;
973                         req.SockFlags = SocketFlags.None;
974                         req.AcceptSocket = acceptSocket;
975                         int count;
976                         lock (readQ) {
977                                 readQ.Enqueue (req.Worker);
978                                 count = readQ.Count;
979                         }
980                         if (count == 1)
981                                 socket_pool_queue (SocketAsyncWorker.Dispatcher, req);
982                         return(req);
983                 }
984
985                 public IAsyncResult BeginConnect (IPAddress address, int port,
986                                                   AsyncCallback callback,
987                                                   object state)
988                 {
989                         if (is_disposed && is_closed)
990                                 throw new ObjectDisposedException (GetType ().ToString ());
991
992                         if (address == null)
993                                 throw new ArgumentNullException ("address");
994
995                         if (address.ToString ().Length == 0)
996                                 throw new ArgumentException ("The length of the IP address is zero");
997
998                         if (port <= 0 || port > 65535)
999                                 throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
1000
1001                         if (is_listening)
1002                                 throw new InvalidOperationException ();
1003
1004                         IPEndPoint iep = new IPEndPoint (address, port);
1005                         return(BeginConnect (iep, callback, state));
1006                 }
1007
1008                 public IAsyncResult BeginConnect (string host, int port,
1009                                                   AsyncCallback callback,
1010                                                   object state)
1011                 {
1012                         if (is_disposed && is_closed)
1013                                 throw new ObjectDisposedException (GetType ().ToString ());
1014
1015                         if (host == null)
1016                                 throw new ArgumentNullException ("host");
1017
1018                         if (address_family != AddressFamily.InterNetwork &&
1019                                 address_family != AddressFamily.InterNetworkV6)
1020                                 throw new NotSupportedException ("This method is valid only for sockets in the InterNetwork and InterNetworkV6 families");
1021
1022                         if (port <= 0 || port > 65535)
1023                                 throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
1024
1025                         if (is_listening)
1026                                 throw new InvalidOperationException ();
1027
1028                         return BeginConnect (Dns.GetHostAddresses (host), port, callback, state);
1029                 }
1030
1031                 public IAsyncResult BeginDisconnect (bool reuseSocket,
1032                                                      AsyncCallback callback,
1033                                                      object state)
1034                 {
1035                         if (is_disposed && is_closed)
1036                                 throw new ObjectDisposedException (GetType ().ToString ());
1037
1038                         SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Disconnect);
1039                         req.ReuseSocket = reuseSocket;
1040                         socket_pool_queue (SocketAsyncWorker.Dispatcher, req);
1041                         return(req);
1042                 }
1043
1044                 void CheckRange (byte[] buffer, int offset, int size)
1045                 {
1046                         if (offset < 0)
1047                                 throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
1048                                 
1049                         if (offset > buffer.Length)
1050                                 throw new ArgumentOutOfRangeException ("offset", "offset must be <= buffer.Length");
1051
1052                         if (size < 0)                          
1053                                 throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
1054                                 
1055                         if (size > buffer.Length - offset)
1056                                 throw new ArgumentOutOfRangeException ("size", "size must be <= buffer.Length - offset");
1057                 }
1058                 
1059                 public IAsyncResult BeginReceive(byte[] buffer, int offset,
1060                                                  int size,
1061                                                  SocketFlags socket_flags,
1062                                                  AsyncCallback callback,
1063                                                  object state) {
1064
1065                         if (is_disposed && is_closed)
1066                                 throw new ObjectDisposedException (GetType ().ToString ());
1067
1068                         if (buffer == null)
1069                                 throw new ArgumentNullException ("buffer");
1070
1071                         CheckRange (buffer, offset, size);
1072
1073                         SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Receive);
1074                         req.Buffer = buffer;
1075                         req.Offset = offset;
1076                         req.Size = size;
1077                         req.SockFlags = socket_flags;
1078                         int count;
1079                         lock (readQ) {
1080                                 readQ.Enqueue (req.Worker);
1081                                 count = readQ.Count;
1082                         }
1083                         if (count == 1)
1084                                 socket_pool_queue (SocketAsyncWorker.Dispatcher, req);
1085                         return req;
1086                 }
1087
1088                 public IAsyncResult BeginReceive (byte[] buffer, int offset,
1089                                                   int size, SocketFlags flags,
1090                                                   out SocketError error,
1091                                                   AsyncCallback callback,
1092                                                   object state)
1093                 {
1094                         /* As far as I can tell from the docs and from
1095                          * experimentation, a pointer to the
1096                          * SocketError parameter is not supposed to be
1097                          * saved for the async parts.  And as we don't
1098                          * set any socket errors in the setup code, we
1099                          * just have to set it to Success.
1100                          */
1101                         error = SocketError.Success;
1102                         return (BeginReceive (buffer, offset, size, flags, callback, state));
1103                 }
1104
1105                 [CLSCompliant (false)]
1106                 public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers,
1107                                                   SocketFlags socketFlags,
1108                                                   AsyncCallback callback,
1109                                                   object state)
1110                 {
1111                         if (is_disposed && is_closed)
1112                                 throw new ObjectDisposedException (GetType ().ToString ());
1113
1114                         if (buffers == null)
1115                                 throw new ArgumentNullException ("buffers");
1116
1117                         SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveGeneric);
1118                         req.Buffers = buffers;
1119                         req.SockFlags = socketFlags;
1120                         int count;
1121                         lock(readQ) {
1122                                 readQ.Enqueue (req.Worker);
1123                                 count = readQ.Count;
1124                         }
1125                         if (count == 1)
1126                                 socket_pool_queue (SocketAsyncWorker.Dispatcher, req);
1127                         return req;
1128                 }
1129                 
1130                 [CLSCompliant (false)]
1131                 public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers,
1132                                                   SocketFlags socketFlags,
1133                                                   out SocketError errorCode,
1134                                                   AsyncCallback callback,
1135                                                   object state)
1136                 {
1137                         /* I assume the same SocketError semantics as
1138                          * above
1139                          */
1140                         errorCode = SocketError.Success;
1141                         return (BeginReceive (buffers, socketFlags, callback, state));
1142                 }
1143
1144                 public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset,
1145                                                      int size,
1146                                                      SocketFlags socket_flags,
1147                                                      ref EndPoint remote_end,
1148                                                      AsyncCallback callback,
1149                                                      object state) {
1150                         if (is_disposed && is_closed)
1151                                 throw new ObjectDisposedException (GetType ().ToString ());
1152
1153                         if (buffer == null)
1154                                 throw new ArgumentNullException ("buffer");
1155
1156                         if (remote_end == null)
1157                                 throw new ArgumentNullException ("remote_end");
1158
1159                         CheckRange (buffer, offset, size);
1160
1161                         SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveFrom);
1162                         req.Buffer = buffer;
1163                         req.Offset = offset;
1164                         req.Size = size;
1165                         req.SockFlags = socket_flags;
1166                         req.EndPoint = remote_end;
1167                         int count;
1168                         lock (readQ) {
1169                                 readQ.Enqueue (req.Worker);
1170                                 count = readQ.Count;
1171                         }
1172                         if (count == 1)
1173                                 socket_pool_queue (SocketAsyncWorker.Dispatcher, req);
1174                         return req;
1175                 }
1176
1177                 [MonoTODO]
1178                 public IAsyncResult BeginReceiveMessageFrom (
1179                         byte[] buffer, int offset, int size,
1180                         SocketFlags socketFlags, ref EndPoint remoteEP,
1181                         AsyncCallback callback, object state)
1182                 {
1183                         if (is_disposed && is_closed)
1184                                 throw new ObjectDisposedException (GetType ().ToString ());
1185
1186                         if (buffer == null)
1187                                 throw new ArgumentNullException ("buffer");
1188
1189                         if (remoteEP == null)
1190                                 throw new ArgumentNullException ("remoteEP");
1191
1192                         CheckRange (buffer, offset, size);
1193
1194                         throw new NotImplementedException ();
1195                 }
1196
1197                 public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socket_flags,
1198                                                AsyncCallback callback, object state)
1199                 {
1200                         if (is_disposed && is_closed)
1201                                 throw new ObjectDisposedException (GetType ().ToString ());
1202
1203                         if (buffer == null)
1204                                 throw new ArgumentNullException ("buffer");
1205
1206                         CheckRange (buffer, offset, size);
1207
1208                         if (!is_connected)
1209                                 throw new SocketException ((int)SocketError.NotConnected);
1210
1211                         SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Send);
1212                         req.Buffer = buffer;
1213                         req.Offset = offset;
1214                         req.Size = size;
1215                         req.SockFlags = socket_flags;
1216                         int count;
1217                         lock (writeQ) {
1218                                 writeQ.Enqueue (req.Worker);
1219                                 count = writeQ.Count;
1220                         }
1221                         if (count == 1)
1222                                 socket_pool_queue (SocketAsyncWorker.Dispatcher, req);
1223                         return req;
1224                 }
1225
1226                 public IAsyncResult BeginSend (byte[] buffer, int offset,
1227                                                int size,
1228                                                SocketFlags socketFlags,
1229                                                out SocketError errorCode,
1230                                                AsyncCallback callback,
1231                                                object state)
1232                 {
1233                         if (!is_connected) {
1234                                 errorCode = SocketError.NotConnected;
1235                                 throw new SocketException ((int)errorCode);
1236                         }
1237                         
1238                         errorCode = SocketError.Success;
1239                         
1240                         return (BeginSend (buffer, offset, size, socketFlags, callback,
1241                                 state));
1242                 }
1243
1244                 public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers,
1245                                                SocketFlags socketFlags,
1246                                                AsyncCallback callback,
1247                                                object state)
1248                 {
1249                         if (is_disposed && is_closed)
1250                                 throw new ObjectDisposedException (GetType ().ToString ());
1251
1252                         if (buffers == null)
1253                                 throw new ArgumentNullException ("buffers");
1254
1255                         if (!is_connected)
1256                                 throw new SocketException ((int)SocketError.NotConnected);
1257
1258                         SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.SendGeneric);
1259                         req.Buffers = buffers;
1260                         req.SockFlags = socketFlags;
1261                         int count;
1262                         lock (writeQ) {
1263                                 writeQ.Enqueue (req.Worker);
1264                                 count = writeQ.Count;
1265                         }
1266                         if (count == 1)
1267                                 socket_pool_queue (SocketAsyncWorker.Dispatcher, req);
1268                         return req;
1269                 }
1270
1271                 [CLSCompliant (false)]
1272                 public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers,
1273                                                SocketFlags socketFlags,
1274                                                out SocketError errorCode,
1275                                                AsyncCallback callback,
1276                                                object state)
1277                 {
1278                         if (!is_connected) {
1279                                 errorCode = SocketError.NotConnected;
1280                                 throw new SocketException ((int)errorCode);
1281                         }
1282                         
1283                         errorCode = SocketError.Success;
1284                         return (BeginSend (buffers, socketFlags, callback, state));
1285                 }
1286
1287                 delegate void SendFileHandler (string fileName, byte [] preBuffer, byte [] postBuffer, TransmitFileOptions flags);
1288
1289                 sealed class SendFileAsyncResult : IAsyncResult {
1290                         IAsyncResult ares;
1291                         SendFileHandler d;
1292
1293                         public SendFileAsyncResult (SendFileHandler d, IAsyncResult ares)
1294                         {
1295                                 this.d = d;
1296                                 this.ares = ares;
1297                         }
1298
1299                         public object AsyncState {
1300                                 get { return ares.AsyncState; }
1301                         }
1302
1303                         public WaitHandle AsyncWaitHandle {
1304                                 get { return ares.AsyncWaitHandle; }
1305                         }
1306
1307                         public bool CompletedSynchronously {
1308                                 get { return ares.CompletedSynchronously; }
1309                         }
1310
1311                         public bool IsCompleted {
1312                                 get { return ares.IsCompleted; }
1313                         }
1314
1315                         public SendFileHandler Delegate {
1316                                 get { return d; }
1317                         }
1318
1319                         public IAsyncResult Original {
1320                                 get { return ares; }
1321                         }
1322                 }
1323
1324                 public IAsyncResult BeginSendFile (string fileName,
1325                                                    AsyncCallback callback,
1326                                                    object state)
1327                 {
1328                         if (is_disposed && is_closed)
1329                                 throw new ObjectDisposedException (GetType ().ToString ());
1330
1331                         if (!is_connected)
1332                                 throw new NotSupportedException ();
1333
1334                         if (!File.Exists (fileName))
1335                                 throw new FileNotFoundException ();
1336
1337                         return BeginSendFile (fileName, null, null, 0, callback, state);
1338                 }
1339
1340                 public IAsyncResult BeginSendFile (string fileName,
1341                                                    byte[] preBuffer,
1342                                                    byte[] postBuffer,
1343                                                    TransmitFileOptions flags,
1344                                                    AsyncCallback callback,
1345                                                    object state)
1346                 {
1347                         if (is_disposed && is_closed)
1348                                 throw new ObjectDisposedException (GetType ().ToString ());
1349
1350                         if (!is_connected)
1351                                 throw new NotSupportedException ();
1352
1353                         if (!File.Exists (fileName))
1354                                 throw new FileNotFoundException ();
1355
1356                         SendFileHandler d = new SendFileHandler (SendFile);
1357                         return new SendFileAsyncResult (d, d.BeginInvoke (fileName, preBuffer, postBuffer, flags, ar => {
1358                                 SendFileAsyncResult sfar = new SendFileAsyncResult (d, ar);
1359                                 callback (sfar);
1360                         }, state));
1361                 }
1362
1363                 public IAsyncResult BeginSendTo(byte[] buffer, int offset,
1364                                                 int size,
1365                                                 SocketFlags socket_flags,
1366                                                 EndPoint remote_end,
1367                                                 AsyncCallback callback,
1368                                                 object state) {
1369                         if (is_disposed && is_closed)
1370                                 throw new ObjectDisposedException (GetType ().ToString ());
1371
1372                         if (buffer == null)
1373                                 throw new ArgumentNullException ("buffer");
1374
1375                         CheckRange (buffer, offset, size);
1376
1377                         SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.SendTo);
1378                         req.Buffer = buffer;
1379                         req.Offset = offset;
1380                         req.Size = size;
1381                         req.SockFlags = socket_flags;
1382                         req.EndPoint = remote_end;
1383                         int count;
1384                         lock (writeQ) {
1385                                 writeQ.Enqueue (req.Worker);
1386                                 count = writeQ.Count;
1387                         }
1388                         if (count == 1)
1389                                 socket_pool_queue (SocketAsyncWorker.Dispatcher, req);
1390                         return req;
1391                 }
1392
1393                 // Creates a new system socket, returning the handle
1394                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1395                 private extern static void Bind_internal(IntPtr sock,
1396                                                          SocketAddress sa,
1397                                                          out int error);
1398
1399                 private static void Bind_internal (SafeSocketHandle safeHandle,
1400                                                          SocketAddress sa,
1401                                                          out int error)
1402                 {
1403                         bool release = false;
1404                         try {
1405                                 safeHandle.DangerousAddRef (ref release);
1406                                 Bind_internal (safeHandle.DangerousGetHandle (), sa, out error);
1407                         } finally {
1408                                 if (release)
1409                                         safeHandle.DangerousRelease ();
1410                         }
1411                 }
1412
1413                 public void Bind(EndPoint local_end) {
1414                         if (is_disposed && is_closed)
1415                                 throw new ObjectDisposedException (GetType ().ToString ());
1416
1417                         if (local_end == null)
1418                                 throw new ArgumentNullException("local_end");
1419                         
1420                         int error;
1421                         
1422                         Bind_internal (safe_handle, local_end.Serialize(), out error);
1423                         if (error != 0)
1424                                 throw new SocketException (error);
1425                         if (error == 0)
1426                                 is_bound = true;
1427                         
1428                         seed_endpoint = local_end;
1429                 }
1430
1431                 public void Connect (IPAddress address, int port)
1432                 {
1433                         Connect (new IPEndPoint (address, port));
1434                 }
1435                 
1436                 public void Connect (IPAddress[] addresses, int port)
1437                 {
1438                         if (is_disposed && is_closed)
1439                                 throw new ObjectDisposedException (GetType ().ToString ());
1440
1441                         if (addresses == null)
1442                                 throw new ArgumentNullException ("addresses");
1443
1444                         if (this.AddressFamily != AddressFamily.InterNetwork &&
1445                                 this.AddressFamily != AddressFamily.InterNetworkV6)
1446                                 throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
1447
1448                         if (is_listening)
1449                                 throw new InvalidOperationException ();
1450
1451                         /* FIXME: do non-blocking sockets Poll here? */
1452                         int error = 0;
1453                         foreach (IPAddress address in addresses) {
1454                                 IPEndPoint iep = new IPEndPoint (address, port);
1455                                 SocketAddress serial = iep.Serialize ();
1456                                 
1457                                 Connect_internal (safe_handle, serial, out error);
1458                                 if (error == 0) {
1459                                         is_connected = true;
1460                                         is_bound = true;
1461                                         seed_endpoint = iep;
1462                                         return;
1463                                 } else if (error != (int)SocketError.InProgress &&
1464                                            error != (int)SocketError.WouldBlock) {
1465                                         continue;
1466                                 }
1467                                 
1468                                 if (!is_blocking) {
1469                                         Poll (-1, SelectMode.SelectWrite);
1470                                         error = (int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
1471                                         if (error == 0) {
1472                                                 is_connected = true;
1473                                                 is_bound = true;
1474                                                 seed_endpoint = iep;
1475                                                 return;
1476                                         }
1477                                 }
1478                         }
1479                         if (error != 0)
1480                                 throw new SocketException (error);
1481                 }
1482
1483                 public void Connect (string host, int port)
1484                 {
1485                         IPAddress [] addresses = Dns.GetHostAddresses (host);
1486                         Connect (addresses, port);
1487                 }
1488
1489                 public bool DisconnectAsync (SocketAsyncEventArgs e)
1490                 {
1491                         // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1492                         if (is_disposed && is_closed)
1493                                 throw new ObjectDisposedException (GetType ().ToString ());
1494
1495                         e.curSocket = this;
1496                         e.Worker.Init (this, e, SocketOperation.Disconnect);
1497                         socket_pool_queue (SocketAsyncWorker.Dispatcher, e.Worker.result);
1498                         return true;
1499                 }
1500
1501                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1502                 extern static void Disconnect_internal(IntPtr sock, bool reuse, out int error);
1503
1504                 private static void Disconnect_internal(SafeSocketHandle safeHandle, bool reuse, out int error)
1505                 {
1506                         bool release = false;
1507                         try {
1508                                 safeHandle.DangerousAddRef (ref release);
1509                                 Disconnect_internal (safeHandle.DangerousGetHandle (), reuse, out error);
1510                         } finally {
1511                                 if (release)
1512                                         safeHandle.DangerousRelease ();
1513                         }
1514                 }
1515
1516                 /* According to the docs, the MS runtime will throw
1517                  * PlatformNotSupportedException if the platform is
1518                  * newer than w2k.  We should be able to cope...
1519                  */
1520                 public void Disconnect (bool reuseSocket)
1521                 {
1522                         if (is_disposed && is_closed)
1523                                 throw new ObjectDisposedException (GetType ().ToString ());
1524
1525                         int error = 0;
1526                         
1527                         Disconnect_internal (safe_handle, reuseSocket, out error);
1528
1529                         if (error != 0) {
1530                                 if (error == 50) {
1531                                         /* ERROR_NOT_SUPPORTED */
1532                                         throw new PlatformNotSupportedException ();
1533                                 } else {
1534                                         throw new SocketException (error);
1535                                 }
1536                         }
1537
1538                         is_connected = false;
1539                         
1540                         if (reuseSocket) {
1541                                 /* Do managed housekeeping here... */
1542                         }
1543                 }
1544
1545 #if !MOBILE
1546                 [MonoLimitation ("We do not support passing sockets across processes, we merely allow this API to pass the socket across AppDomains")]
1547                 public SocketInformation DuplicateAndClose (int targetProcessId)
1548                 {
1549                         var si = new SocketInformation ();
1550                         si.Options =
1551                                 (is_listening      ? SocketInformationOptions.Listening : 0) |
1552                                 (is_connected      ? SocketInformationOptions.Connected : 0) |
1553                                 (is_blocking       ? 0 : SocketInformationOptions.NonBlocking) |
1554                                 (use_overlapped_io ? SocketInformationOptions.UseOnlyOverlappedIO : 0);
1555
1556                         si.ProtocolInformation = Mono.DataConverter.Pack ("iiiil", (int)address_family, (int)socket_type, (int)protocol_type, is_bound ? 1 : 0, (long)Handle);
1557                         safe_handle = null;
1558
1559                         return si;
1560                 }
1561 #endif
1562         
1563                 public Socket EndAccept (IAsyncResult result)
1564                 {
1565                         int bytes;
1566                         byte[] buffer;
1567                         
1568                         return(EndAccept (out buffer, out bytes, result));
1569                 }
1570
1571                 public Socket EndAccept (out byte[] buffer, IAsyncResult asyncResult)
1572                 {
1573                         int bytes;
1574                         return(EndAccept (out buffer, out bytes, asyncResult));
1575                 }
1576
1577                 public Socket EndAccept (out byte[] buffer, out int bytesTransferred, IAsyncResult asyncResult)
1578                 {
1579                         if (is_disposed && is_closed)
1580                                 throw new ObjectDisposedException (GetType ().ToString ());
1581
1582                         if (asyncResult == null)
1583                                 throw new ArgumentNullException ("asyncResult");
1584                         
1585                         SocketAsyncResult req = asyncResult as SocketAsyncResult;
1586                         if (req == null)
1587                                 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
1588
1589                         if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
1590                                 throw InvalidAsyncOp ("EndAccept");
1591                         if (!asyncResult.IsCompleted)
1592                                 asyncResult.AsyncWaitHandle.WaitOne ();
1593
1594                         req.CheckIfThrowDelayedException ();
1595                         
1596                         buffer = req.Buffer;
1597                         bytesTransferred = req.Total;
1598                         
1599                         return(req.Socket);
1600                 }
1601
1602                 public void EndConnect (IAsyncResult result)
1603                 {
1604                         if (is_disposed && is_closed)
1605                                 throw new ObjectDisposedException (GetType ().ToString ());
1606
1607                         if (result == null)
1608                                 throw new ArgumentNullException ("result");
1609
1610                         SocketAsyncResult req = result as SocketAsyncResult;
1611                         if (req == null)
1612                                 throw new ArgumentException ("Invalid IAsyncResult", "result");
1613
1614                         if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
1615                                 throw InvalidAsyncOp ("EndConnect");
1616                         if (!result.IsCompleted)
1617                                 result.AsyncWaitHandle.WaitOne();
1618
1619                         req.CheckIfThrowDelayedException();
1620                 }
1621
1622                 public void EndDisconnect (IAsyncResult asyncResult)
1623                 {
1624                         if (is_disposed && is_closed)
1625                                 throw new ObjectDisposedException (GetType ().ToString ());
1626
1627                         if (asyncResult == null)
1628                                 throw new ArgumentNullException ("asyncResult");
1629
1630                         SocketAsyncResult req = asyncResult as SocketAsyncResult;
1631                         if (req == null)
1632                                 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
1633
1634                         if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
1635                                 throw InvalidAsyncOp ("EndDisconnect");
1636                         if (!asyncResult.IsCompleted)
1637                                 asyncResult.AsyncWaitHandle.WaitOne ();
1638
1639                         req.CheckIfThrowDelayedException ();
1640                 }
1641
1642                 [MonoTODO]
1643                 public int EndReceiveMessageFrom (IAsyncResult asyncResult,
1644                                                   ref SocketFlags socketFlags,
1645                                                   ref EndPoint endPoint,
1646                                                   out IPPacketInformation ipPacketInformation)
1647                 {
1648                         if (is_disposed && is_closed)
1649                                 throw new ObjectDisposedException (GetType ().ToString ());
1650
1651                         if (asyncResult == null)
1652                                 throw new ArgumentNullException ("asyncResult");
1653
1654                         if (endPoint == null)
1655                                 throw new ArgumentNullException ("endPoint");
1656
1657                         SocketAsyncResult req = asyncResult as SocketAsyncResult;
1658                         if (req == null)
1659                                 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
1660
1661                         if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
1662                                 throw InvalidAsyncOp ("EndReceiveMessageFrom");
1663                         throw new NotImplementedException ();
1664                 }
1665
1666                 public void EndSendFile (IAsyncResult asyncResult)
1667                 {
1668                         if (is_disposed && is_closed)
1669                                 throw new ObjectDisposedException (GetType ().ToString ());
1670
1671                         if (asyncResult == null)
1672                                 throw new ArgumentNullException ("asyncResult");
1673
1674                         SendFileAsyncResult ares = asyncResult as SendFileAsyncResult;
1675                         if (ares == null)
1676                                 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
1677
1678                         ares.Delegate.EndInvoke (ares.Original);
1679                 }
1680
1681                 public int EndSendTo (IAsyncResult result)
1682                 {
1683                         if (is_disposed && is_closed)
1684                                 throw new ObjectDisposedException (GetType ().ToString ());
1685
1686                         if (result == null)
1687                                 throw new ArgumentNullException ("result");
1688
1689                         SocketAsyncResult req = result as SocketAsyncResult;
1690                         if (req == null)
1691                                 throw new ArgumentException ("Invalid IAsyncResult", "result");
1692
1693                         if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
1694                                 throw InvalidAsyncOp ("EndSendTo");
1695                         if (!result.IsCompleted)
1696                                 result.AsyncWaitHandle.WaitOne();
1697
1698                         req.CheckIfThrowDelayedException();
1699                         return req.Total;
1700                 }
1701
1702                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1703                 private extern static void GetSocketOption_arr_internal(IntPtr socket,
1704                         SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val,
1705                         out int error);
1706
1707                 private static void GetSocketOption_arr_internal (SafeSocketHandle safeHandle,
1708                         SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val,
1709                         out int error)
1710                 {
1711                         bool release = false;
1712                         try {
1713                                 safeHandle.DangerousAddRef (ref release);
1714                                 GetSocketOption_arr_internal (safeHandle.DangerousGetHandle (), level, name, ref byte_val, out error);
1715                         } finally {
1716                                 if (release)
1717                                         safeHandle.DangerousRelease ();
1718                         }
1719                 }
1720
1721                 public void GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, byte [] optionValue)
1722                 {
1723                         if (is_disposed && is_closed)
1724                                 throw new ObjectDisposedException (GetType ().ToString ());
1725
1726                         if (optionValue == null)
1727                                 throw new SocketException ((int) SocketError.Fault,
1728                                         "Error trying to dereference an invalid pointer");
1729
1730                         int error;
1731
1732                         GetSocketOption_arr_internal (safe_handle, optionLevel, optionName, ref optionValue,
1733                                 out error);
1734                         if (error != 0)
1735                                 throw new SocketException (error);
1736                 }
1737
1738                 public byte [] GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int length)
1739                 {
1740                         if (is_disposed && is_closed)
1741                                 throw new ObjectDisposedException (GetType ().ToString ());
1742
1743                         byte[] byte_val=new byte[length];
1744                         int error;
1745
1746                         GetSocketOption_arr_internal (safe_handle, optionLevel, optionName, ref byte_val,
1747                                 out error);
1748                         if (error != 0)
1749                                 throw new SocketException (error);
1750
1751                         return(byte_val);
1752                 }
1753
1754                 // See Socket.IOControl, WSAIoctl documentation in MSDN. The
1755                 // common options between UNIX and Winsock are FIONREAD,
1756                 // FIONBIO and SIOCATMARK. Anything else will depend on the
1757                 // system except SIO_KEEPALIVE_VALS which is properly handled
1758                 // on both windows and linux.
1759                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1760                 extern static int WSAIoctl (IntPtr sock, int ioctl_code, byte [] input,
1761                         byte [] output, out int error);
1762
1763                 private static int WSAIoctl (SafeSocketHandle safeHandle, int ioctl_code, byte [] input,
1764                         byte [] output, out int error)
1765                 {
1766                         bool release = false;
1767                         try {
1768                                 safeHandle.DangerousAddRef (ref release);
1769                                 return WSAIoctl (safeHandle.DangerousGetHandle (), ioctl_code, input, output, out error);
1770                         } finally {
1771                                 if (release)
1772                                         safeHandle.DangerousRelease ();
1773                         }
1774                 }
1775
1776                 public int IOControl (int ioctl_code, byte [] in_value, byte [] out_value)
1777                 {
1778                         if (is_disposed)
1779                                 throw new ObjectDisposedException (GetType ().ToString ());
1780
1781                         int error;
1782                         int result = WSAIoctl (safe_handle, ioctl_code, in_value, out_value,
1783                                 out error);
1784
1785                         if (error != 0)
1786                                 throw new SocketException (error);
1787                         
1788                         if (result == -1)
1789                                 throw new InvalidOperationException ("Must use Blocking property instead.");
1790
1791                         return result;
1792                 }
1793
1794                 public int IOControl (IOControlCode ioControlCode, byte[] optionInValue, byte[] optionOutValue)
1795                 {
1796                         return IOControl ((int) ioControlCode, optionInValue, optionOutValue);
1797                 }
1798
1799                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1800                 private extern static void Listen_internal(IntPtr sock, int backlog, out int error);
1801
1802                 private static void Listen_internal (SafeSocketHandle safeHandle, int backlog, out int error)
1803                 {
1804                         bool release = false;
1805                         try {
1806                                 safeHandle.DangerousAddRef (ref release);
1807                                 Listen_internal (safeHandle.DangerousGetHandle (), backlog, out error);
1808                         } finally {
1809                                 if (release)
1810                                         safeHandle.DangerousRelease ();
1811                         }
1812                 }
1813
1814                 public void Listen (int backlog)
1815                 {
1816                         if (is_disposed && is_closed)
1817                                 throw new ObjectDisposedException (GetType ().ToString ());
1818
1819                         if (!is_bound)
1820                                 throw new SocketException ((int)SocketError.InvalidArgument);
1821
1822                         int error;
1823                         Listen_internal(safe_handle, backlog, out error);
1824
1825                         if (error != 0)
1826                                 throw new SocketException (error);
1827
1828                         is_listening = true;
1829                 }
1830
1831                 public bool Poll (int time_us, SelectMode mode)
1832                 {
1833                         if (is_disposed && is_closed)
1834                                 throw new ObjectDisposedException (GetType ().ToString ());
1835
1836                         if (mode != SelectMode.SelectRead &&
1837                             mode != SelectMode.SelectWrite &&
1838                             mode != SelectMode.SelectError)
1839                                 throw new NotSupportedException ("'mode' parameter is not valid.");
1840
1841                         int error;
1842                         bool result = Poll_internal (safe_handle, mode, time_us, out error);
1843                         if (error != 0)
1844                                 throw new SocketException (error);
1845
1846                         if (mode == SelectMode.SelectWrite && result && !is_connected) {
1847                                 /* Update the is_connected state; for
1848                                  * non-blocking Connect()s this is
1849                                  * when we can find out that the
1850                                  * connect succeeded.
1851                                  */
1852                                 if ((int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error) == 0) {
1853                                         is_connected = true;
1854                                 }
1855                         }
1856                         
1857                         return result;
1858                 }
1859
1860                 public int Receive (byte [] buffer)
1861                 {
1862                         return Receive (buffer, SocketFlags.None);
1863                 }
1864
1865                 public int Receive (byte [] buffer, SocketFlags flags)
1866                 {
1867                         if (is_disposed && is_closed)
1868                                 throw new ObjectDisposedException (GetType ().ToString ());
1869
1870                         if (buffer == null)
1871                                 throw new ArgumentNullException ("buffer");
1872
1873                         SocketError error;
1874
1875                         int ret = Receive_nochecks (buffer, 0, buffer.Length, flags, out error);
1876                         
1877                         if (error != SocketError.Success) {
1878                                 if (error == SocketError.WouldBlock && is_blocking) // This might happen when ReceiveTimeout is set
1879                                         throw new SocketException ((int) error, TIMEOUT_EXCEPTION_MSG);
1880                                 throw new SocketException ((int) error);
1881                         }
1882
1883                         return ret;
1884                 }
1885
1886                 public int Receive (byte [] buffer, int size, SocketFlags flags)
1887                 {
1888                         if (is_disposed && is_closed)
1889                                 throw new ObjectDisposedException (GetType ().ToString ());
1890
1891                         if (buffer == null)
1892                                 throw new ArgumentNullException ("buffer");
1893
1894                         CheckRange (buffer, 0, size);
1895
1896                         SocketError error;
1897
1898                         int ret = Receive_nochecks (buffer, 0, size, flags, out error);
1899                         
1900                         if (error != SocketError.Success) {
1901                                 if (error == SocketError.WouldBlock && is_blocking) // This might happen when ReceiveTimeout is set
1902                                         throw new SocketException ((int) error, TIMEOUT_EXCEPTION_MSG);
1903                                 throw new SocketException ((int) error);
1904                         }
1905
1906                         return ret;
1907                 }
1908
1909                 public int Receive (byte [] buffer, int offset, int size, SocketFlags flags)
1910                 {
1911                         if (is_disposed && is_closed)
1912                                 throw new ObjectDisposedException (GetType ().ToString ());
1913
1914                         if (buffer == null)
1915                                 throw new ArgumentNullException ("buffer");
1916
1917                         CheckRange (buffer, offset, size);
1918                         
1919                         SocketError error;
1920
1921                         int ret = Receive_nochecks (buffer, offset, size, flags, out error);
1922                         
1923                         if (error != SocketError.Success) {
1924                                 if (error == SocketError.WouldBlock && is_blocking) // This might happen when ReceiveTimeout is set
1925                                         throw new SocketException ((int) error, TIMEOUT_EXCEPTION_MSG);
1926                                 throw new SocketException ((int) error);
1927                         }
1928
1929                         return ret;
1930                 }
1931
1932                 public int Receive (byte [] buffer, int offset, int size, SocketFlags flags, out SocketError error)
1933                 {
1934                         if (is_disposed && is_closed)
1935                                 throw new ObjectDisposedException (GetType ().ToString ());
1936
1937                         if (buffer == null)
1938                                 throw new ArgumentNullException ("buffer");
1939
1940                         CheckRange (buffer, offset, size);
1941                         
1942                         return Receive_nochecks (buffer, offset, size, flags, out error);
1943                 }
1944
1945                 public bool ReceiveFromAsync (SocketAsyncEventArgs e)
1946                 {
1947                         if (is_disposed && is_closed)
1948                                 throw new ObjectDisposedException (GetType ().ToString ());
1949
1950                         // We do not support recv into multiple buffers yet
1951                         if (e.BufferList != null)
1952                                 throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
1953                         if (e.RemoteEndPoint == null)
1954                                 throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
1955
1956                         e.curSocket = this;
1957                         e.Worker.Init (this, e, SocketOperation.ReceiveFrom);
1958                         SocketAsyncResult res = e.Worker.result;
1959                         res.Buffer = e.Buffer;
1960                         res.Offset = e.Offset;
1961                         res.Size = e.Count;
1962                         res.EndPoint = e.RemoteEndPoint;
1963                         res.SockFlags = e.SocketFlags;
1964                         int count;
1965                         lock (readQ) {
1966                                 readQ.Enqueue (e.Worker);
1967                                 count = readQ.Count;
1968                         }
1969                         if (count == 1)
1970                                 socket_pool_queue (SocketAsyncWorker.Dispatcher, res);
1971                         return true;
1972                 }
1973
1974                 public int ReceiveFrom (byte [] buffer, ref EndPoint remoteEP)
1975                 {
1976                         if (is_disposed && is_closed)
1977                                 throw new ObjectDisposedException (GetType ().ToString ());
1978
1979                         if (buffer == null)
1980                                 throw new ArgumentNullException ("buffer");
1981
1982                         if (remoteEP == null)
1983                                 throw new ArgumentNullException ("remoteEP");
1984
1985                         return ReceiveFrom_nochecks (buffer, 0, buffer.Length, SocketFlags.None, ref remoteEP);
1986                 }
1987
1988                 public int ReceiveFrom (byte [] buffer, SocketFlags flags, ref EndPoint remoteEP)
1989                 {
1990                         if (is_disposed && is_closed)
1991                                 throw new ObjectDisposedException (GetType ().ToString ());
1992
1993                         if (buffer == null)
1994                                 throw new ArgumentNullException ("buffer");
1995
1996                         if (remoteEP == null)
1997                                 throw new ArgumentNullException ("remoteEP");
1998
1999                         return ReceiveFrom_nochecks (buffer, 0, buffer.Length, flags, ref remoteEP);
2000                 }
2001
2002                 public int ReceiveFrom (byte [] buffer, int size, SocketFlags flags,
2003                                         ref EndPoint remoteEP)
2004                 {
2005                         if (is_disposed && is_closed)
2006                                 throw new ObjectDisposedException (GetType ().ToString ());
2007
2008                         if (buffer == null)
2009                                 throw new ArgumentNullException ("buffer");
2010
2011                         if (remoteEP == null)
2012                                 throw new ArgumentNullException ("remoteEP");
2013
2014                         if (size < 0 || size > buffer.Length)
2015                                 throw new ArgumentOutOfRangeException ("size");
2016
2017                         return ReceiveFrom_nochecks (buffer, 0, size, flags, ref remoteEP);
2018                 }
2019
2020                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2021                 private extern static int RecvFrom_internal(IntPtr sock,
2022                                                             byte[] buffer,
2023                                                             int offset,
2024                                                             int count,
2025                                                             SocketFlags flags,
2026                                                             ref SocketAddress sockaddr,
2027                                                             out int error);
2028
2029                 private static int RecvFrom_internal (SafeSocketHandle safeHandle,
2030                                                             byte[] buffer,
2031                                                             int offset,
2032                                                             int count,
2033                                                             SocketFlags flags,
2034                                                             ref SocketAddress sockaddr,
2035                                                             out int error)
2036                 {
2037                         try {
2038                                 safeHandle.RegisterForBlockingSyscall ();
2039                                 return RecvFrom_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, ref sockaddr, out error);
2040                         } finally {
2041                                 safeHandle.UnRegisterForBlockingSyscall ();
2042                         }
2043                 }
2044
2045                 public int ReceiveFrom (byte [] buffer, int offset, int size, SocketFlags flags,
2046                                         ref EndPoint remoteEP)
2047                 {
2048                         if (is_disposed && is_closed)
2049                                 throw new ObjectDisposedException (GetType ().ToString ());
2050
2051                         if (buffer == null)
2052                                 throw new ArgumentNullException ("buffer");
2053
2054                         if (remoteEP == null)
2055                                 throw new ArgumentNullException ("remoteEP");
2056
2057                         CheckRange (buffer, offset, size);
2058
2059                         return ReceiveFrom_nochecks (buffer, offset, size, flags, ref remoteEP);
2060                 }
2061
2062                 internal int ReceiveFrom_nochecks (byte [] buf, int offset, int size, SocketFlags flags,
2063                                                    ref EndPoint remote_end)
2064                 {
2065                         int error;
2066                         return ReceiveFrom_nochecks_exc (buf, offset, size, flags, ref remote_end, true, out error);
2067                 }
2068
2069                 internal int ReceiveFrom_nochecks_exc (byte [] buf, int offset, int size, SocketFlags flags,
2070                                                    ref EndPoint remote_end, bool throwOnError, out int error)
2071                 {
2072                         SocketAddress sockaddr = remote_end.Serialize();
2073                         int cnt = RecvFrom_internal (safe_handle, buf, offset, size, flags, ref sockaddr, out error);
2074                         SocketError err = (SocketError) error;
2075                         if (err != 0) {
2076                                 if (err != SocketError.WouldBlock && err != SocketError.InProgress)
2077                                         is_connected = false;
2078                                 else if (err == SocketError.WouldBlock && is_blocking) { // This might happen when ReceiveTimeout is set
2079                                         if (throwOnError)       
2080                                                 throw new SocketException ((int) SocketError.TimedOut, TIMEOUT_EXCEPTION_MSG);
2081                                         error = (int) SocketError.TimedOut;
2082                                         return 0;
2083                                 }
2084
2085                                 if (throwOnError)
2086                                         throw new SocketException (error);
2087                                 return 0;
2088                         }
2089
2090                         is_connected = true;
2091                         is_bound = true;
2092
2093                         // If sockaddr is null then we're a connection
2094                         // oriented protocol and should ignore the
2095                         // remote_end parameter (see MSDN
2096                         // documentation for Socket.ReceiveFrom(...) )
2097                         
2098                         if ( sockaddr != null ) {
2099                                 // Stupidly, EndPoint.Create() is an
2100                                 // instance method
2101                                 remote_end = remote_end.Create (sockaddr);
2102                         }
2103                         
2104                         seed_endpoint = remote_end;
2105                         
2106                         return cnt;
2107                 }
2108
2109                 [MonoTODO ("Not implemented")]
2110                 public bool ReceiveMessageFromAsync (SocketAsyncEventArgs e)
2111                 {
2112                         // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
2113                         if (is_disposed && is_closed)
2114                                 throw new ObjectDisposedException (GetType ().ToString ());
2115                         
2116                         throw new NotImplementedException ();
2117                 }
2118                 
2119                 [MonoTODO ("Not implemented")]
2120                 public int ReceiveMessageFrom (byte[] buffer, int offset,
2121                                                int size,
2122                                                ref SocketFlags socketFlags,
2123                                                ref EndPoint remoteEP,
2124                                                out IPPacketInformation ipPacketInformation)
2125                 {
2126                         if (is_disposed && is_closed)
2127                                 throw new ObjectDisposedException (GetType ().ToString ());
2128
2129                         if (buffer == null)
2130                                 throw new ArgumentNullException ("buffer");
2131
2132                         if (remoteEP == null)
2133                                 throw new ArgumentNullException ("remoteEP");
2134
2135                         CheckRange (buffer, offset, size);
2136
2137                         /* FIXME: figure out how we get hold of the
2138                          * IPPacketInformation
2139                          */
2140                         throw new NotImplementedException ();
2141                 }
2142
2143                 [MonoTODO ("Not implemented")]
2144                 public bool SendPacketsAsync (SocketAsyncEventArgs e)
2145                 {
2146                         // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
2147                         
2148                         if (is_disposed && is_closed)
2149                                 throw new ObjectDisposedException (GetType ().ToString ());
2150                         
2151                         throw new NotImplementedException ();
2152                 }
2153
2154                 public int Send (byte [] buf)
2155                 {
2156                         if (is_disposed && is_closed)
2157                                 throw new ObjectDisposedException (GetType ().ToString ());
2158
2159                         if (buf == null)
2160                                 throw new ArgumentNullException ("buf");
2161
2162                         SocketError error;
2163
2164                         int ret = Send_nochecks (buf, 0, buf.Length, SocketFlags.None, out error);
2165
2166                         if (error != SocketError.Success)
2167                                 throw new SocketException ((int) error);
2168
2169                         return ret;
2170                 }
2171
2172                 public int Send (byte [] buf, SocketFlags flags)
2173                 {
2174                         if (is_disposed && is_closed)
2175                                 throw new ObjectDisposedException (GetType ().ToString ());
2176
2177                         if (buf == null)
2178                                 throw new ArgumentNullException ("buf");
2179
2180                         SocketError error;
2181
2182                         int ret = Send_nochecks (buf, 0, buf.Length, flags, out error);
2183
2184                         if (error != SocketError.Success)
2185                                 throw new SocketException ((int) error);
2186
2187                         return ret;
2188                 }
2189
2190                 public int Send (byte [] buf, int size, SocketFlags flags)
2191                 {
2192                         if (is_disposed && is_closed)
2193                                 throw new ObjectDisposedException (GetType ().ToString ());
2194
2195                         if (buf == null)
2196                                 throw new ArgumentNullException ("buf");
2197
2198                         CheckRange (buf, 0, size);
2199
2200                         SocketError error;
2201
2202                         int ret = Send_nochecks (buf, 0, size, flags, out error);
2203
2204                         if (error != SocketError.Success)
2205                                 throw new SocketException ((int) error);
2206
2207                         return ret;
2208                 }
2209
2210                 public int Send (byte [] buf, int offset, int size, SocketFlags flags)
2211                 {
2212                         if (is_disposed && is_closed)
2213                                 throw new ObjectDisposedException (GetType ().ToString ());
2214
2215                         if (buf == null)
2216                                 throw new ArgumentNullException ("buffer");
2217
2218                         CheckRange (buf, offset, size);
2219
2220                         SocketError error;
2221
2222                         int ret = Send_nochecks (buf, offset, size, flags, out error);
2223
2224                         if (error != SocketError.Success)
2225                                 throw new SocketException ((int) error);
2226
2227                         return ret;
2228                 }
2229
2230                 public int Send (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
2231                 {
2232                         if (is_disposed && is_closed)
2233                                 throw new ObjectDisposedException (GetType ().ToString ());
2234
2235                         if (buf == null)
2236                                 throw new ArgumentNullException ("buffer");
2237
2238                         CheckRange (buf, offset, size);
2239
2240                         return Send_nochecks (buf, offset, size, flags, out error);
2241                 }
2242
2243                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2244                 private extern static bool SendFile (IntPtr sock, string filename, byte [] pre_buffer, byte [] post_buffer, TransmitFileOptions flags);
2245
2246                 private static bool SendFile (SafeSocketHandle safeHandle, string filename, byte [] pre_buffer, byte [] post_buffer, TransmitFileOptions flags)
2247                 {
2248                         try {
2249                                 safeHandle.RegisterForBlockingSyscall ();
2250                                 return SendFile (safeHandle.DangerousGetHandle (), filename, pre_buffer, post_buffer, flags);
2251                         } finally {
2252                                 safeHandle.UnRegisterForBlockingSyscall ();
2253                         }
2254                 }
2255
2256                 public void SendFile (string fileName)
2257                 {
2258                         if (is_disposed && is_closed)
2259                                 throw new ObjectDisposedException (GetType ().ToString ());
2260
2261                         if (!is_connected)
2262                                 throw new NotSupportedException ();
2263
2264                         if (!is_blocking)
2265                                 throw new InvalidOperationException ();
2266
2267                         SendFile (fileName, null, null, 0);
2268                 }
2269
2270                 public void SendFile (string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags)
2271                 {
2272                         if (is_disposed && is_closed)
2273                                 throw new ObjectDisposedException (GetType ().ToString ());
2274
2275                         if (!is_connected)
2276                                 throw new NotSupportedException ();
2277
2278                         if (!is_blocking)
2279                                 throw new InvalidOperationException ();
2280
2281                         if (!SendFile (safe_handle, fileName, preBuffer, postBuffer, flags)) {
2282                                 SocketException exc = new SocketException ();
2283                                 if (exc.ErrorCode == 2 || exc.ErrorCode == 3)
2284                                         throw new FileNotFoundException ();
2285                                 throw exc;
2286                         }
2287                 }
2288
2289                 public bool SendToAsync (SocketAsyncEventArgs e)
2290                 {
2291                         // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
2292                         
2293                         if (is_disposed && is_closed)
2294                                 throw new ObjectDisposedException (GetType ().ToString ());
2295                         if (e.BufferList != null)
2296                                 throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
2297                         if (e.RemoteEndPoint == null)
2298                                 throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
2299
2300                         e.curSocket = this;
2301                         e.Worker.Init (this, e, SocketOperation.SendTo);
2302                         SocketAsyncResult res = e.Worker.result;
2303                         res.Buffer = e.Buffer;
2304                         res.Offset = e.Offset;
2305                         res.Size = e.Count;
2306                         res.SockFlags = e.SocketFlags;
2307                         res.EndPoint = e.RemoteEndPoint;
2308                         int count;
2309                         lock (writeQ) {
2310                                 writeQ.Enqueue (e.Worker);
2311                                 count = writeQ.Count;
2312                         }
2313                         if (count == 1)
2314                                 socket_pool_queue (SocketAsyncWorker.Dispatcher, res);
2315                         return true;
2316                 }
2317                 
2318                 public int SendTo (byte [] buffer, EndPoint remote_end)
2319                 {
2320                         if (is_disposed && is_closed)
2321                                 throw new ObjectDisposedException (GetType ().ToString ());
2322
2323                         if (buffer == null)
2324                                 throw new ArgumentNullException ("buffer");
2325
2326                         if (remote_end == null)
2327                                 throw new ArgumentNullException ("remote_end");
2328
2329                         return SendTo_nochecks (buffer, 0, buffer.Length, SocketFlags.None, remote_end);
2330                 }
2331
2332                 public int SendTo (byte [] buffer, SocketFlags flags, EndPoint remote_end)
2333                 {
2334                         if (is_disposed && is_closed)
2335                                 throw new ObjectDisposedException (GetType ().ToString ());
2336
2337                         if (buffer == null)
2338                                 throw new ArgumentNullException ("buffer");
2339
2340                         if (remote_end == null)
2341                                 throw new ArgumentNullException ("remote_end");
2342                                 
2343                         return SendTo_nochecks (buffer, 0, buffer.Length, flags, remote_end);
2344                 }
2345
2346                 public int SendTo (byte [] buffer, int size, SocketFlags flags, EndPoint remote_end)
2347                 {
2348                         if (is_disposed && is_closed)
2349                                 throw new ObjectDisposedException (GetType ().ToString ());
2350
2351                         if (buffer == null)
2352                                 throw new ArgumentNullException ("buffer");
2353
2354                         if (remote_end == null)
2355                                 throw new ArgumentNullException ("remote_end");
2356
2357                         CheckRange (buffer, 0, size);
2358
2359                         return SendTo_nochecks (buffer, 0, size, flags, remote_end);
2360                 }
2361
2362                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2363                 private extern static int SendTo_internal(IntPtr sock,
2364                                                           byte[] buffer,
2365                                                           int offset,
2366                                                           int count,
2367                                                           SocketFlags flags,
2368                                                           SocketAddress sa,
2369                                                           out int error);
2370
2371                 private static int SendTo_internal (SafeSocketHandle safeHandle,
2372                                                           byte[] buffer,
2373                                                           int offset,
2374                                                           int count,
2375                                                           SocketFlags flags,
2376                                                           SocketAddress sa,
2377                                                           out int error)
2378                 {
2379                         try {
2380                                 safeHandle.RegisterForBlockingSyscall ();
2381                                 return SendTo_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, sa, out error);
2382                         } finally {
2383                                 safeHandle.UnRegisterForBlockingSyscall ();
2384                         }
2385                 }
2386
2387                 public int SendTo (byte [] buffer, int offset, int size, SocketFlags flags,
2388                                    EndPoint remote_end)
2389                 {
2390                         if (is_disposed && is_closed)
2391                                 throw new ObjectDisposedException (GetType ().ToString ());
2392
2393                         if (buffer == null)
2394                                 throw new ArgumentNullException ("buffer");
2395
2396                         if (remote_end == null)
2397                                 throw new ArgumentNullException("remote_end");
2398
2399                         CheckRange (buffer, offset, size);
2400
2401                         return SendTo_nochecks (buffer, offset, size, flags, remote_end);
2402                 }
2403
2404                 internal int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags,
2405                                               EndPoint remote_end)
2406                 {
2407                         SocketAddress sockaddr = remote_end.Serialize ();
2408
2409                         int ret, error;
2410
2411                         ret = SendTo_internal (safe_handle, buffer, offset, size, flags, sockaddr, out error);
2412
2413                         SocketError err = (SocketError) error;
2414                         if (err != 0) {
2415                                 if (err != SocketError.WouldBlock && err != SocketError.InProgress)
2416                                         is_connected = false;
2417
2418                                 throw new SocketException (error);
2419                         }
2420
2421                         is_connected = true;
2422                         is_bound = true;
2423                         seed_endpoint = remote_end;
2424                         
2425                         return ret;
2426                 }
2427
2428                 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, byte [] optionValue)
2429                 {
2430                         if (is_disposed && is_closed)
2431                                 throw new ObjectDisposedException (GetType ().ToString ());
2432
2433                         // I'd throw an ArgumentNullException, but this is what MS does.
2434                         if (optionValue == null)
2435                                 throw new SocketException ((int) SocketError.Fault,
2436                                         "Error trying to dereference an invalid pointer");
2437                         
2438                         int error;
2439
2440                         SetSocketOption_internal (safe_handle, optionLevel, optionName, null,
2441                                                  optionValue, 0, out error);
2442
2443                         if (error != 0) {
2444                                 if (error == (int) SocketError.InvalidArgument)
2445                                         throw new ArgumentException ();
2446                                 throw new SocketException (error);
2447                         }
2448                 }
2449
2450                 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, object optionValue)
2451                 {
2452                         if (is_disposed && is_closed)
2453                                 throw new ObjectDisposedException (GetType ().ToString ());
2454
2455                         // NOTE: if a null is passed, the byte[] overload is used instead...
2456                         if (optionValue == null)
2457                                 throw new ArgumentNullException("optionValue");
2458                         
2459                         int error;
2460
2461                         if (optionLevel == SocketOptionLevel.Socket && optionName == SocketOptionName.Linger) {
2462                                 LingerOption linger = optionValue as LingerOption;
2463                                 if (linger == null)
2464                                         throw new ArgumentException ("A 'LingerOption' value must be specified.", "optionValue");
2465                                 SetSocketOption_internal (safe_handle, optionLevel, optionName, linger, null, 0, out error);
2466                         } else if (optionLevel == SocketOptionLevel.IP && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
2467                                 MulticastOption multicast = optionValue as MulticastOption;
2468                                 if (multicast == null)
2469                                         throw new ArgumentException ("A 'MulticastOption' value must be specified.", "optionValue");
2470                                 SetSocketOption_internal (safe_handle, optionLevel, optionName, multicast, null, 0, out error);
2471                         } else if (optionLevel == SocketOptionLevel.IPv6 && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
2472                                 IPv6MulticastOption multicast = optionValue as IPv6MulticastOption;
2473                                 if (multicast == null)
2474                                         throw new ArgumentException ("A 'IPv6MulticastOption' value must be specified.", "optionValue");
2475                                 SetSocketOption_internal (safe_handle, optionLevel, optionName, multicast, null, 0, out error);
2476                         } else {
2477                                 throw new ArgumentException ("Invalid value specified.", "optionValue");
2478                         }
2479
2480                         if (error != 0) {
2481                                 if (error == (int) SocketError.InvalidArgument)
2482                                         throw new ArgumentException ();
2483                                 throw new SocketException (error);
2484                         }
2485                 }
2486
2487                 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, bool optionValue)
2488                 {
2489                         if (is_disposed && is_closed)
2490                                 throw new ObjectDisposedException (GetType ().ToString ());
2491
2492                         int error;
2493                         int int_val = (optionValue) ? 1 : 0;
2494                         SetSocketOption_internal (safe_handle, optionLevel, optionName, null, null, int_val, out error);
2495                         if (error != 0) {
2496                                 if (error == (int) SocketError.InvalidArgument)
2497                                         throw new ArgumentException ();
2498                                 throw new SocketException (error);
2499                         }
2500                 }
2501
2502                 void ThrowIfDisposedAndClosed ()
2503                 {
2504                         if (is_disposed && is_closed)
2505                                 throw new ObjectDisposedException (GetType ().ToString ());
2506                 }
2507
2508                 void ThrowIfUdp ()
2509                 {
2510 #if !NET_2_1 || MOBILE
2511                         if (protocol_type == ProtocolType.Udp)
2512                                 throw new SocketException ((int)SocketError.ProtocolOption);
2513 #endif
2514                 }
2515         }
2516 }
2517