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