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