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