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