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