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