copied mono-api-diff.cs from mono-2-2 branch so new patch can be applied and history...
[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                 enum SocketOperation {
57                         Accept,
58                         Connect,
59                         Receive,
60                         ReceiveFrom,
61                         Send,
62                         SendTo,
63                         UsedInManaged1,
64                         UsedInManaged2,
65                         UsedInProcess,
66                         UsedInConsole2,
67                         Disconnect,
68                         AcceptReceive,
69                         ReceiveGeneric,
70                         SendGeneric
71                 }
72
73                 [StructLayout (LayoutKind.Sequential)]
74                 struct WSABUF 
75                 {
76                         public int len;
77                         public IntPtr buf;
78                 };
79
80                 [StructLayout (LayoutKind.Sequential)]
81                 private sealed class SocketAsyncResult: IAsyncResult
82                 {
83                         /* Same structure in the runtime */
84                         /*
85                           Keep this in sync with MonoSocketAsyncResult in
86                           metadata/socket-io.h and ProcessAsyncReader
87                           in System.Diagnostics/Process.cs.
88                         */
89
90                         public Socket Sock;
91                         public IntPtr handle;
92                         object state;
93                         AsyncCallback callback;
94                         WaitHandle waithandle;
95
96                         Exception delayedException;
97
98                         public EndPoint EndPoint;       // Connect,ReceiveFrom,SendTo
99                         public byte [] Buffer;          // Receive,ReceiveFrom,Send,SendTo
100                         public int Offset;              // Receive,ReceiveFrom,Send,SendTo
101                         public int Size;                // Receive,ReceiveFrom,Send,SendTo
102                         public SocketFlags SockFlags;   // Receive,ReceiveFrom,Send,SendTo
103                         public Socket AcceptSocket;     // AcceptReceive
104                         public IPAddress[] Addresses;   // Connect
105                         public int Port;                // Connect
106 #if NET_2_0
107                         public IList<ArraySegment<byte>> Buffers;       // Receive, Send
108 #else
109                         public object Buffers;          // Reserve this slot in older profiles
110 #endif
111                         public bool ReuseSocket;        // Disconnect
112
113                         // Return values
114                         Socket acc_socket;
115                         int total;
116
117                         bool completed_sync;
118                         bool completed;
119                         public bool blocking;
120                         internal int error;
121                         SocketOperation operation;
122                         public object ares;
123                         public int EndCalled;
124
125                         public SocketAsyncResult (Socket sock, object state, AsyncCallback callback, SocketOperation operation)
126                         {
127                                 this.Sock = sock;
128                                 this.blocking = sock.blocking;
129                                 this.handle = sock.socket;
130                                 this.state = state;
131                                 this.callback = callback;
132                                 this.operation = operation;
133                                 SockFlags = SocketFlags.None;
134                         }
135
136                         public void CheckIfThrowDelayedException ()
137                         {
138                                 if (delayedException != null) {
139                                         Sock.connected = false;
140                                         throw delayedException;
141                                 }
142
143                                 if (error != 0) {
144                                         Sock.connected = false;
145                                         throw new SocketException (error);
146                                 }
147                         }
148
149                         void CompleteAllOnDispose (Queue queue)
150                         {
151                                 object [] pending = queue.ToArray ();
152                                 queue.Clear ();
153
154                                 WaitCallback cb;
155                                 for (int i = 0; i < pending.Length; i++) {
156                                         SocketAsyncResult ares = (SocketAsyncResult) pending [i];
157                                         cb = new WaitCallback (ares.CompleteDisposed);
158                                         ThreadPool.QueueUserWorkItem (cb, null);
159                                 }
160                                 if (pending.Length == 0)
161                                         Buffer = null;
162                         }
163
164                         void CompleteDisposed (object unused)
165                         {
166                                 Complete ();
167                         }
168
169                         public void Complete ()
170                         {
171                                 if (operation != SocketOperation.Receive && Sock.disposed)
172                                         delayedException = new ObjectDisposedException (Sock.GetType ().ToString ());
173
174                                 IsCompleted = true;
175
176                                 Queue queue = null;
177                                 if (operation == SocketOperation.Receive || operation == SocketOperation.ReceiveFrom) {
178                                         queue = Sock.readQ;
179                                 } else if (operation == SocketOperation.Send || operation == SocketOperation.SendTo) {
180                                         queue = Sock.writeQ;
181                                 }
182
183                                 if (queue != null) {
184                                         SocketAsyncCall sac = null;
185                                         SocketAsyncResult req = null;
186                                         lock (queue) {
187                                                 queue.Dequeue (); // remove ourselves
188                                                 if (queue.Count > 0) {
189                                                         req = (SocketAsyncResult) queue.Peek ();
190                                                         if (!Sock.disposed) {
191                                                                 Worker worker = new Worker (req);
192                                                                 sac = GetDelegate (worker, req.operation);
193                                                         } else {
194                                                                 CompleteAllOnDispose (queue);
195                                                         }
196                                                 }
197                                         }
198
199                                         if (sac != null)
200                                                 sac.BeginInvoke (null, req);
201                                 }
202
203                                 if (callback != null)
204                                         callback (this);
205                                 Buffer = null;
206                         }
207
208                         SocketAsyncCall GetDelegate (Worker worker, SocketOperation op)
209                         {
210                                 switch (op) {
211                                 case SocketOperation.Receive:
212                                         return new SocketAsyncCall (worker.Receive);
213                                 case SocketOperation.ReceiveFrom:
214                                         return new SocketAsyncCall (worker.ReceiveFrom);
215                                 case SocketOperation.Send:
216                                         return new SocketAsyncCall (worker.Send);
217                                 case SocketOperation.SendTo:
218                                         return new SocketAsyncCall (worker.SendTo);
219                                 default:
220                                         return null; // never happens
221                                 }
222                         }
223
224                         public void Complete (bool synch)
225                         {
226                                 completed_sync = synch;
227                                 Complete ();
228                         }
229
230                         public void Complete (int total)
231                         {
232                                 this.total = total;
233                                 Complete ();
234                         }
235
236                         public void Complete (Exception e, bool synch)
237                         {
238                                 completed_sync = synch;
239                                 delayedException = e;
240                                 Complete ();
241                         }
242
243                         public void Complete (Exception e)
244                         {
245                                 delayedException = e;
246                                 Complete ();
247                         }
248
249                         public void Complete (Socket s)
250                         {
251                                 acc_socket = s;
252                                 Complete ();
253                         }
254
255                         public void Complete (Socket s, int total)
256                         {
257                                 acc_socket = s;
258                                 this.total = total;
259                                 Complete ();
260                         }
261
262                         public object AsyncState {
263                                 get {
264                                         return state;
265                                 }
266                         }
267
268                         public WaitHandle AsyncWaitHandle {
269                                 get {
270                                         lock (this) {
271                                                 if (waithandle == null)
272                                                         waithandle = new ManualResetEvent (completed);
273                                         }
274
275                                         return waithandle;
276                                 }
277                                 set {
278                                         waithandle=value;
279                                 }
280                         }
281
282                         public bool CompletedSynchronously {
283                                 get {
284                                         return(completed_sync);
285                                 }
286                         }
287
288                         public bool IsCompleted {
289                                 get {
290                                         return(completed);
291                                 }
292                                 set {
293                                         completed=value;
294                                         lock (this) {
295                                                 if (waithandle != null && value) {
296                                                         ((ManualResetEvent) waithandle).Set ();
297                                                 }
298                                         }
299                                 }
300                         }
301                         
302                         public Socket Socket {
303                                 get {
304                                         return acc_socket;
305                                 }
306                         }
307
308                         public int Total {
309                                 get { return total; }
310                                 set { total = value; }
311                         }
312
313                         public SocketError ErrorCode
314                         {
315                                 get {
316 #if NET_2_0
317                                         SocketException ex = delayedException as SocketException;
318                                         
319                                         if (ex != null)
320                                                 return(ex.SocketErrorCode);
321
322                                         if (error != 0)
323                                                 return((SocketError)error);
324 #endif
325                                         return(SocketError.Success);
326                                 }
327                         }
328                 }
329
330                 private sealed class Worker 
331                 {
332                         SocketAsyncResult result;
333
334                         public Worker (SocketAsyncResult ares)
335                         {
336                                 this.result = ares;
337                         }
338
339                         public void Accept ()
340                         {
341                                 Socket acc_socket = null;
342                                 try {
343                                         acc_socket = result.Sock.Accept ();
344                                 } catch (Exception e) {
345                                         result.Complete (e);
346                                         return;
347                                 }
348
349                                 result.Complete (acc_socket);
350                         }
351
352                         /* only used in 2.0 profile and newer, but
353                          * leave in older profiles to keep interface
354                          * to runtime consistent
355                          */
356                         public void AcceptReceive ()
357                         {
358                                 Socket acc_socket = null;
359                                 
360                                 try {
361                                         if (result.AcceptSocket == null) {
362                                                 acc_socket = result.Sock.Accept ();
363                                         } else {
364                                                 acc_socket = result.AcceptSocket;
365                                                 result.Sock.Accept (acc_socket);
366                                         }
367                                 } catch (Exception e) {
368                                         result.Complete (e);
369                                         return;
370                                 }
371
372                                 /* It seems the MS runtime
373                                  * special-cases 0-length requested
374                                  * receive data.  See bug 464201.
375                                  */
376                                 int total = 0;
377                                 if (result.Size > 0) {
378                                         try {
379                                                 SocketError error;
380                                         
381                                                 total = acc_socket.Receive_nochecks (result.Buffer,
382                                                                                      result.Offset,
383                                                                                      result.Size,
384                                                                                      result.SockFlags,
385                                                                                      out error);
386                                         } catch (Exception e) {
387                                                 result.Complete (e);
388                                                 return;
389                                         }
390                                 }
391
392                                 result.Complete (acc_socket, total);
393                         }
394
395                         public void Connect ()
396                         {
397                                 /* If result.EndPoint is non-null,
398                                  * this is the standard one-address
399                                  * connect attempt.  Otherwise
400                                  * Addresses must be non-null and
401                                  * contain a list of addresses to try
402                                  * to connect to; the first one to
403                                  * succeed causes the rest of the list
404                                  * to be ignored.
405                                  */
406                                 if (result.EndPoint != null) {
407                                         try {
408                                                 if (!result.Sock.Blocking) {
409                                                         int success;
410                                                         result.Sock.Poll (-1, SelectMode.SelectWrite, out success);
411                                                         if (success == 0) {
412                                                                 result.Sock.connected = true;
413                                                         } else {
414                                                                 result.Complete (new SocketException (success));
415                                                                 return;
416                                                         }
417                                                 } else {
418                                                         result.Sock.seed_endpoint = result.EndPoint;
419                                                         result.Sock.Connect (result.EndPoint);
420                                                         result.Sock.connected = true;
421                                                 }
422                                         } catch (Exception e) {
423                                                 result.Complete (e);
424                                                 return;
425                                         }
426
427                                         result.Complete ();
428                                 } else if (result.Addresses != null) {
429                                         int error = (int) SocketError.InProgress; // why?
430                                         foreach(IPAddress address in result.Addresses) {
431                                                 IPEndPoint iep = new IPEndPoint (address, result.Port);
432                                                 SocketAddress serial = iep.Serialize ();
433                                                 
434                                                 Socket.Connect_internal (result.Sock.socket, serial, out error);
435                                                 if (error == 0) {
436                                                         result.Sock.connected = true;
437                                                         result.Sock.seed_endpoint = iep;
438                                                         result.Complete ();
439                                                         return;
440                                                 } else if (error != (int)SocketError.InProgress &&
441                                                            error != (int)SocketError.WouldBlock) {
442                                                         continue;
443                                                 }
444
445                                                 if (!result.Sock.Blocking) {
446                                                         int success;
447                                                         result.Sock.Poll (-1, SelectMode.SelectWrite, out success);
448                                                         if (success == 0) {
449                                                                 result.Sock.connected = true;
450                                                                 result.Sock.seed_endpoint = iep;
451                                                                 result.Complete ();
452                                                                 return;
453                                                         }
454                                                 }
455                                         }
456                                         
457                                         result.Complete (new SocketException (error));
458                                 } else {
459                                         result.Complete (new SocketException ((int)SocketError.AddressNotAvailable));
460                                 }
461                         }
462
463                         /* Also only used in 2.0 profile and newer */
464                         public void Disconnect ()
465                         {
466 #if NET_2_0
467                                 try {
468                                         result.Sock.Disconnect (result.ReuseSocket);
469                                 } catch (Exception e) {
470                                         result.Complete (e);
471                                         return;
472                                 }
473                                 result.Complete ();
474 #else
475                                 result.Complete (new SocketException ((int)SocketError.Fault));
476 #endif
477                         }
478
479                         public void Receive ()
480                         {
481                                 // Actual recv() done in the runtime
482                                 result.Complete ();
483                         }
484
485                         public void ReceiveFrom ()
486                         {
487                                 int total = 0;
488                                 try {
489                                         total = result.Sock.ReceiveFrom_nochecks (result.Buffer,
490                                                                          result.Offset,
491                                                                          result.Size,
492                                                                          result.SockFlags,
493                                                                          ref result.EndPoint);
494                                 } catch (Exception e) {
495                                         result.Complete (e);
496                                         return;
497                                 }
498
499                                 result.Complete (total);
500                         }
501
502                         public void ReceiveGeneric ()
503                         {
504 #if NET_2_0
505                                 int total = 0;
506                                 try {
507                                         SocketError error;
508                                         
509                                         total = result.Sock.Receive (result.Buffers, result.SockFlags, out error);
510                                 } catch (Exception e) {
511                                         result.Complete (e);
512                                         return;
513                                 }
514                                 
515                                 result.Complete (total);
516 #else
517                                 result.Complete (new SocketException ((int)SocketError.Fault));
518 #endif
519                         }
520
521                         int send_so_far;
522
523                         void UpdateSendValues (int last_sent)
524                         {
525                                 if (result.error == 0) {
526                                         send_so_far += last_sent;
527                                         result.Offset += last_sent;
528                                         result.Size -= last_sent;
529                                 }
530                         }
531
532                         public void Send ()
533                         {
534                                 // Actual send() done in the runtime
535                                 if (result.error == 0) {
536                                         UpdateSendValues (result.Total);
537                                         if (result.Sock.disposed) {
538                                                 result.Complete ();
539                                                 return;
540                                         }
541
542                                         if (result.Size > 0) {
543                                                 SocketAsyncCall sac = new SocketAsyncCall (this.Send);
544                                                 sac.BeginInvoke (null, result);
545                                                 return; // Have to finish writing everything. See bug #74475.
546                                         }
547                                         result.Total = send_so_far;
548                                 }
549                                 result.Complete ();
550                         }
551
552                         public void SendTo ()
553                         {
554                                 int total = 0;
555                                 try {
556                                         total = result.Sock.SendTo_nochecks (result.Buffer,
557                                                                     result.Offset,
558                                                                     result.Size,
559                                                                     result.SockFlags,
560                                                                     result.EndPoint);
561
562                                         UpdateSendValues (total);
563                                         if (result.Size > 0) {
564                                                 SocketAsyncCall sac = new SocketAsyncCall (this.SendTo);
565                                                 sac.BeginInvoke (null, result);
566                                                 return; // Have to finish writing everything. See bug #74475.
567                                         }
568                                         result.Total = send_so_far;
569                                 } catch (Exception e) {
570                                         result.Complete (e);
571                                         return;
572                                 }
573
574                                 result.Complete ();
575                         }
576
577                         public void SendGeneric ()
578                         {
579 #if NET_2_0
580                                 int total = 0;
581                                 try {
582                                         SocketError error;
583                                         
584                                         total = result.Sock.Send (result.Buffers, result.SockFlags, out error);
585                                 } catch (Exception e) {
586                                         result.Complete (e);
587                                         return;
588                                 }
589                                 
590                                 result.Complete (total);
591 #else
592                                 result.Complete (new SocketException ((int)SocketError.Fault));
593 #endif
594                         }
595                 }
596                         
597
598                 private Queue readQ = new Queue (2);
599                 private Queue writeQ = new Queue (2);
600
601                 delegate void SocketAsyncCall ();
602
603 #if NET_2_0
604                 private bool islistening;
605                 private bool useoverlappedIO;
606 #endif
607                 
608
609                 static void AddSockets (ArrayList sockets, IList list, string name)
610                 {
611                         if (list != null) {
612                                 foreach (Socket sock in list) {
613                                         if (sock == null) // MS throws a NullRef
614                                                 throw new ArgumentNullException ("name", "Contains a null element");
615                                         sockets.Add (sock);
616                                 }
617                         }
618
619                         sockets.Add (null);
620                 }
621 #if !TARGET_JVM
622                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
623                 private extern static void Select_internal (ref Socket [] sockets,
624                                                         int microSeconds,
625                                                         out int error);
626 #endif
627                 public static void Select (IList checkRead, IList checkWrite, IList checkError, int microSeconds)
628                 {
629                         ArrayList list = new ArrayList ();
630                         AddSockets (list, checkRead, "checkRead");
631                         AddSockets (list, checkWrite, "checkWrite");
632                         AddSockets (list, checkError, "checkError");
633
634                         if (list.Count == 3) {
635                                 throw new ArgumentNullException ("checkRead, checkWrite, checkError",
636                                                                  "All the lists are null or empty.");
637                         }
638
639                         int error;
640                         /*
641                          * The 'sockets' array contains: READ socket 0-n, null,
642                          *                               WRITE socket 0-n, null,
643                          *                               ERROR socket 0-n, null
644                          */
645                         Socket [] sockets = (Socket []) list.ToArray (typeof (Socket));
646                         Select_internal (ref sockets, microSeconds, out error);
647
648                         if (error != 0)
649                                 throw new SocketException (error);
650
651                         if (sockets == null) {
652                                 if (checkRead != null)
653                                         checkRead.Clear ();
654                                 if (checkWrite != null)
655                                         checkWrite.Clear ();
656                                 if (checkError != null)
657                                         checkError.Clear ();
658                                 return;
659                         }
660
661                         int mode = 0;
662                         int count = sockets.Length;
663                         IList currentList = checkRead;
664                         int currentIdx = 0;
665                         for (int i = 0; i < count; i++) {
666                                 Socket sock = sockets [i];
667                                 if (sock == null) { // separator
668                                         if (currentList != null) {
669                                                 // Remove non-signaled sockets after the current one
670                                                 int to_remove = currentList.Count - currentIdx;
671                                                 for (int k = 0; k < to_remove; k++)
672                                                         currentList.RemoveAt (currentIdx);
673                                         }
674                                         currentList = (mode == 0) ? checkWrite : checkError;
675                                         currentIdx = 0;
676                                         mode++;
677                                         continue;
678                                 }
679
680                                 if (mode == 1 && currentList == checkWrite && !sock.connected) {
681                                         if ((int) sock.GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error) == 0)
682                                                 sock.connected = true;
683                                 }
684
685                                 // Remove non-signaled sockets before the current one
686                                 //int max = currentList.Count;
687                                 while (((Socket) currentList [currentIdx]) != sock) {
688                                         currentList.RemoveAt (currentIdx);
689                                 }
690                                 currentIdx++;
691                         }
692                 }
693
694                 // private constructor used by Accept, which already
695                 // has a socket handle to use
696                 private Socket(AddressFamily family, SocketType type,
697                                ProtocolType proto, IntPtr sock)
698                 {
699                         address_family=family;
700                         socket_type=type;
701                         protocol_type=proto;
702                         
703                         socket=sock;
704                         connected=true;
705                 }
706
707                 private void SocketDefaults ()
708                 {
709 #if NET_2_0
710                         try {
711                                 if (address_family == AddressFamily.InterNetwork /* Need to test IPv6 further ||
712                                                                                    address_family == AddressFamily.InterNetworkV6 */) {
713                                         /* This is the default, but it
714                                          * probably has nasty side
715                                          * effects on Linux, as the
716                                          * socket option is kludged by
717                                          * turning on or off PMTU
718                                          * discovery...
719                                          */
720                                         this.DontFragment = false;
721                                 }
722
723                                 //
724                                 // Microsoft sets these to 8192, but we are going to keep them
725                                 // both to the OS defaults as these have a big performance impact.
726                                 // on WebClient performance.
727                                 //
728                                 //this.ReceiveBufferSize = 8192;
729                                 //this.SendBufferSize = 8192;
730                         } catch (SocketException) {
731                         }
732 #endif
733                 }
734
735
736 #if NET_2_0
737                 [MonoTODO]
738                 public Socket (SocketInformation socketInformation)
739                 {
740                         throw new NotImplementedException ("SocketInformation not figured out yet");
741
742                         // ifdef to avoid the warnings.
743 #if false
744                         //address_family = socketInformation.address_family;
745                         //socket_type = socketInformation.socket_type;
746                         //protocol_type = socketInformation.protocol_type;
747                         address_family = AddressFamily.InterNetwork;
748                         socket_type = SocketType.Stream;
749                         protocol_type = ProtocolType.IP;
750                         
751                         int error;
752                         socket = Socket_internal (address_family, socket_type, protocol_type, out error);
753                         if (error != 0)
754                                 throw new SocketException (error);
755
756                         SocketDefaults ();
757 #endif
758                 }
759 #endif
760
761 #if !TARGET_JVM
762                 // Returns the amount of data waiting to be read on socket
763                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
764                 private extern static int Available_internal(IntPtr socket, out int error);
765 #endif
766
767                 public int Available {
768                         get {
769                                 if (disposed && closed)
770                                         throw new ObjectDisposedException (GetType ().ToString ());
771
772                                 int ret, error;
773                                 
774                                 ret = Available_internal(socket, out error);
775
776                                 if (error != 0)
777                                         throw new SocketException (error);
778
779                                 return(ret);
780                         }
781                 }
782
783
784 #if NET_2_0
785                 public bool DontFragment {
786                         get {
787                                 if (disposed && closed) {
788                                         throw new ObjectDisposedException (GetType ().ToString ());
789                                 }
790
791                                 bool dontfragment;
792                                 
793                                 if (address_family == AddressFamily.InterNetwork) {
794                                         dontfragment = (int)(GetSocketOption (SocketOptionLevel.IP, SocketOptionName.DontFragment)) != 0;
795                                 } else if (address_family == AddressFamily.InterNetworkV6) {
796                                         dontfragment = (int)(GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.DontFragment)) != 0;
797                                 } else {
798                                         throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
799                                 }
800                                 
801                                 return(dontfragment);
802                         }
803                         set {
804                                 if (disposed && closed) {
805                                         throw new ObjectDisposedException (GetType ().ToString ());
806                                 }
807
808                                 if (address_family == AddressFamily.InterNetwork) {
809                                         SetSocketOption (SocketOptionLevel.IP, SocketOptionName.DontFragment, value?1:0);
810                                 } else if (address_family == AddressFamily.InterNetworkV6) {
811                                         SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.DontFragment, value?1:0);
812                                 } else {
813                                         throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
814                                 }
815                         }
816                 }
817
818                 public bool EnableBroadcast {
819                         get {
820                                 if (disposed && closed) {
821                                         throw new ObjectDisposedException (GetType ().ToString ());
822                                 }
823
824                                 if (protocol_type != ProtocolType.Udp) {
825                                         throw new SocketException ((int)SocketError.ProtocolOption);
826                                 }
827                                 
828                                 return((int)(GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Broadcast)) != 0);
829                         }
830                         set {
831                                 if (disposed && closed) {
832                                         throw new ObjectDisposedException (GetType ().ToString ());
833                                 }
834
835                                 if (protocol_type != ProtocolType.Udp) {
836                                         throw new SocketException ((int)SocketError.ProtocolOption);
837                                 }
838
839                                 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Broadcast, value?1:0);
840                         }
841                 }
842                 
843                 public bool ExclusiveAddressUse {
844                         get {
845                                 if (disposed && closed) {
846                                         throw new ObjectDisposedException (GetType ().ToString ());
847                                 }
848
849                                 return((int)(GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse)) != 0);
850                         }
851                         set {
852                                 if (disposed && closed) {
853                                         throw new ObjectDisposedException (GetType ().ToString ());
854                                 }
855                                 if (isbound) {
856                                         throw new InvalidOperationException ("Bind has already been called for this socket");
857                                 }
858                                 
859                                 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse, value?1:0);
860                         }
861                 }
862                 
863                 public bool IsBound {
864                         get {
865                                 return(isbound);
866                         }
867                 }
868                 
869                 public LingerOption LingerState {
870                         get {
871                                 if (disposed && closed) {
872                                         throw new ObjectDisposedException (GetType ().ToString ());
873                                 }
874
875                                 return((LingerOption)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Linger));
876                         }
877                         set {
878                                 if (disposed && closed) {
879                                         throw new ObjectDisposedException (GetType ().ToString ());
880                                 }
881                                 
882                                 SetSocketOption (SocketOptionLevel.Socket,
883                                                  SocketOptionName.Linger,
884                                                  value);
885                         }
886                 }
887                 
888                 public bool MulticastLoopback {
889                         get {
890                                 if (disposed && closed) {
891                                         throw new ObjectDisposedException (GetType ().ToString ());
892                                 }
893
894                                 /* Even though this option can be set
895                                  * for TCP sockets on Linux, throw
896                                  * this exception anyway to be
897                                  * compatible (the MSDN docs say
898                                  * "Setting this property on a
899                                  * Transmission Control Protocol (TCP)
900                                  * socket will have no effect." but
901                                  * the MS runtime throws the
902                                  * exception...)
903                                  */
904                                 if (protocol_type == ProtocolType.Tcp) {
905                                         throw new SocketException ((int)SocketError.ProtocolOption);
906                                 }
907                                 
908                                 bool multicastloopback;
909                                 
910                                 if (address_family == AddressFamily.InterNetwork) {
911                                         multicastloopback = (int)(GetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastLoopback)) != 0;
912                                 } else if (address_family == AddressFamily.InterNetworkV6) {
913                                         multicastloopback = (int)(GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback)) != 0;
914                                 } else {
915                                         throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
916                                 }
917                                 
918                                 return(multicastloopback);
919                         }
920                         set {
921                                 if (disposed && closed) {
922                                         throw new ObjectDisposedException (GetType ().ToString ());
923                                 }
924
925                                 /* Even though this option can be set
926                                  * for TCP sockets on Linux, throw
927                                  * this exception anyway to be
928                                  * compatible (the MSDN docs say
929                                  * "Setting this property on a
930                                  * Transmission Control Protocol (TCP)
931                                  * socket will have no effect." but
932                                  * the MS runtime throws the
933                                  * exception...)
934                                  */
935                                 if (protocol_type == ProtocolType.Tcp) {
936                                         throw new SocketException ((int)SocketError.ProtocolOption);
937                                 }
938                                 
939                                 if (address_family == AddressFamily.InterNetwork) {
940                                         SetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastLoopback, value?1:0);
941                                 } else if (address_family == AddressFamily.InterNetworkV6) {
942                                         SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback, value?1:0);
943                                 } else {
944                                         throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
945                                 }
946                         }
947                 }
948                 
949                 
950                 [MonoTODO ("This doesn't do anything on Mono yet")]
951                 public bool UseOnlyOverlappedIO {
952                         get {
953                                 return(useoverlappedIO);
954                         }
955                         set {
956                                 useoverlappedIO = value;
957                         }
958                 }
959 #endif
960
961                 public IntPtr Handle {
962                         get {
963                                 return(socket);
964                         }
965                 }
966
967 #if !TARGET_JVM
968                 // Returns the local endpoint details in addr and port
969                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
970                 private extern static SocketAddress LocalEndPoint_internal(IntPtr socket, out int error);
971 #endif
972
973                 // Wish:  support non-IP endpoints.
974                 public EndPoint LocalEndPoint {
975                         get {
976                                 if (disposed && closed)
977                                         throw new ObjectDisposedException (GetType ().ToString ());
978                                 
979                                 /*
980                                  * If the seed EndPoint is null, Connect, Bind,
981                                  * etc has not yet been called. MS returns null
982                                  * in this case.
983                                  */
984                                 if (seed_endpoint == null)
985                                         return null;
986                                 
987                                 SocketAddress sa;
988                                 int error;
989                                 
990                                 sa=LocalEndPoint_internal(socket, out error);
991
992                                 if (error != 0)
993                                         throw new SocketException (error);
994
995                                 return seed_endpoint.Create (sa);
996                         }
997                 }
998
999                 public SocketType SocketType {
1000                         get {
1001                                 return(socket_type);
1002                         }
1003                 }
1004
1005 #if NET_2_0
1006                 public int SendTimeout {
1007                         get {
1008                                 if (disposed && closed)
1009                                         throw new ObjectDisposedException (GetType ().ToString ());
1010
1011                                 return (int)GetSocketOption(
1012                                         SocketOptionLevel.Socket,
1013                                         SocketOptionName.SendTimeout);
1014                         }
1015                         set {
1016                                 if (disposed && closed)
1017                                         throw new ObjectDisposedException (GetType ().ToString ());
1018
1019                                 if (value < -1)
1020                                         throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than -1");
1021
1022                                 /* According to the MSDN docs we
1023                                  * should adjust values between 1 and
1024                                  * 499 to 500, but the MS runtime
1025                                  * doesn't do this.
1026                                  */
1027                                 if (value == -1)
1028                                         value = 0;
1029
1030                                 SetSocketOption(
1031                                         SocketOptionLevel.Socket,
1032                                         SocketOptionName.SendTimeout, value);
1033                         }
1034                 }
1035
1036                 public int ReceiveTimeout {
1037                         get {
1038                                 if (disposed && closed)
1039                                         throw new ObjectDisposedException (GetType ().ToString ());
1040
1041                                 return (int)GetSocketOption(
1042                                         SocketOptionLevel.Socket,
1043                                         SocketOptionName.ReceiveTimeout);
1044                         }
1045                         set {
1046                                 if (disposed && closed)
1047                                         throw new ObjectDisposedException (GetType ().ToString ());
1048
1049                                 if (value < -1)
1050                                         throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than -1");
1051
1052                                 if (value == -1) {
1053                                         value = 0;
1054                                 }
1055                                 
1056                                 SetSocketOption(
1057                                         SocketOptionLevel.Socket,
1058                                         SocketOptionName.ReceiveTimeout, value);
1059                         }
1060                 }
1061
1062                 public bool AcceptAsync (SocketAsyncEventArgs e)
1063                 {
1064                         // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1065                         
1066                         if (disposed && closed)
1067                                 throw new ObjectDisposedException (GetType ().ToString ());
1068                         if (!IsBound)
1069                                 throw new InvalidOperationException ("You must call the Bind method before performing this operation.");
1070                         if (!islistening)
1071                                 throw new InvalidOperationException ("You must call the Listen method before performing this operation.");
1072                         if (e.BufferList != null)
1073                                 throw new ArgumentException ("Multiple buffers cannot be used with this method.");
1074                         if (e.Count < 0)
1075                                 throw new ArgumentOutOfRangeException ("e.Count");
1076                         
1077                         Socket acceptSocket = e.AcceptSocket;
1078                         if (acceptSocket != null) {
1079                                 if (acceptSocket.IsBound || acceptSocket.Connected)
1080                                         throw new InvalidOperationException ("AcceptSocket: The socket must not be bound or connected.");
1081                         } else
1082                                 e.AcceptSocket = new Socket (AddressFamily, SocketType, ProtocolType);
1083
1084                         try {
1085                                 e.DoOperation (SocketAsyncOperation.Accept, this);
1086                         } catch {
1087                                 ((IDisposable)e).Dispose ();
1088                                 throw;
1089                         }
1090
1091                         // We always return true for now
1092                         return true;
1093                 }
1094 #endif
1095                 
1096                 // Creates a new system socket, returning the handle
1097                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1098                 private extern static IntPtr Accept_internal(IntPtr sock, out int error, bool blocking);
1099
1100                 public Socket Accept() {
1101                         if (disposed && closed)
1102                                 throw new ObjectDisposedException (GetType ().ToString ());
1103
1104                         int error = 0;
1105                         IntPtr sock = (IntPtr) (-1);
1106                         blocking_thread = Thread.CurrentThread;
1107                         try {
1108                                 sock = Accept_internal(socket, out error, blocking);
1109                         } catch (ThreadAbortException) {
1110                                 if (disposed) {
1111                                         Thread.ResetAbort ();
1112                                         error = (int) SocketError.Interrupted;
1113                                 }
1114                         } finally {
1115                                 blocking_thread = null;
1116                         }
1117
1118                         if (error != 0)
1119                                 throw new SocketException (error);
1120                         
1121                         Socket accepted = new Socket(this.AddressFamily, this.SocketType,
1122                                 this.ProtocolType, sock);
1123
1124                         accepted.seed_endpoint = this.seed_endpoint;
1125                         accepted.Blocking = this.Blocking;
1126                         return(accepted);
1127                 }
1128
1129                 internal void Accept (Socket acceptSocket)
1130                 {
1131                         if (disposed && closed)
1132                                 throw new ObjectDisposedException (GetType ().ToString ());
1133                         
1134                         int error = 0;
1135                         IntPtr sock = (IntPtr)(-1);
1136                         blocking_thread = Thread.CurrentThread;
1137                         
1138                         try {
1139                                 sock = Accept_internal (socket, out error, blocking);
1140                         } catch (ThreadAbortException) {
1141                                 if (disposed) {
1142                                         Thread.ResetAbort ();
1143                                         error = (int)SocketError.Interrupted;
1144                                 }
1145                         } finally {
1146                                 blocking_thread = null;
1147                         }
1148                         
1149                         if (error != 0)
1150                                 throw new SocketException (error);
1151                         
1152                         acceptSocket.address_family = this.AddressFamily;
1153                         acceptSocket.socket_type = this.SocketType;
1154                         acceptSocket.protocol_type = this.ProtocolType;
1155                         acceptSocket.socket = sock;
1156                         acceptSocket.connected = true;
1157                         acceptSocket.seed_endpoint = this.seed_endpoint;
1158                         acceptSocket.Blocking = this.Blocking;
1159
1160                         /* FIXME: figure out what if anything else
1161                          * needs to be reset
1162                          */
1163                 }
1164
1165                 public IAsyncResult BeginAccept(AsyncCallback callback,
1166                                                 object state)
1167                 {
1168                         if (disposed && closed)
1169                                 throw new ObjectDisposedException (GetType ().ToString ());
1170
1171 #if NET_2_0
1172                         /* FIXME: check the 1.1 docs for this too */
1173                         if (!isbound || !islistening)
1174                                 throw new InvalidOperationException ();
1175 #endif
1176
1177                         SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Accept);
1178                         Worker worker = new Worker (req);
1179                         SocketAsyncCall sac = new SocketAsyncCall (worker.Accept);
1180                         sac.BeginInvoke (null, req);
1181                         return(req);
1182                 }
1183
1184 #if NET_2_0
1185                 public IAsyncResult BeginAccept (int receiveSize,
1186                                                  AsyncCallback callback,
1187                                                  object state)
1188                 {
1189                         if (disposed && closed)
1190                                 throw new ObjectDisposedException (GetType ().ToString ());
1191
1192                         if (receiveSize < 0)
1193                                 throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
1194
1195                         SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.AcceptReceive);
1196                         Worker worker = new Worker (req);
1197                         SocketAsyncCall sac = new SocketAsyncCall (worker.AcceptReceive);
1198                         
1199                         req.Buffer = new byte[receiveSize];
1200                         req.Offset = 0;
1201                         req.Size = receiveSize;
1202                         req.SockFlags = SocketFlags.None;
1203
1204                         sac.BeginInvoke (null, req);
1205                         return(req);
1206                 }
1207
1208                 public IAsyncResult BeginAccept (Socket acceptSocket,
1209                                                  int receiveSize,
1210                                                  AsyncCallback callback,
1211                                                  object state)
1212                 {
1213                         if (disposed && closed)
1214                                 throw new ObjectDisposedException (GetType ().ToString ());
1215
1216                         if (receiveSize < 0)
1217                                 throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
1218
1219                         if (acceptSocket != null) {
1220                                 if (acceptSocket.disposed && acceptSocket.closed)
1221                                         throw new ObjectDisposedException (acceptSocket.GetType ().ToString ());
1222
1223                                 if (acceptSocket.IsBound)
1224                                         throw new InvalidOperationException ();
1225
1226                                 /* For some reason the MS runtime
1227                                  * barfs if the new socket is not TCP,
1228                                  * even though it's just about to blow
1229                                  * away all those parameters
1230                                  */
1231                                 if (acceptSocket.ProtocolType != ProtocolType.Tcp)
1232                                         throw new SocketException ((int)SocketError.InvalidArgument);
1233                         }
1234                         
1235                         SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.AcceptReceive);
1236                         Worker worker = new Worker (req);
1237                         SocketAsyncCall sac = new SocketAsyncCall (worker.AcceptReceive);
1238                         
1239                         req.Buffer = new byte[receiveSize];
1240                         req.Offset = 0;
1241                         req.Size = receiveSize;
1242                         req.SockFlags = SocketFlags.None;
1243                         req.AcceptSocket = acceptSocket;
1244
1245                         sac.BeginInvoke (null, req);
1246                         return(req);
1247                 }
1248 #endif
1249
1250                 public IAsyncResult BeginConnect(EndPoint end_point,
1251                                                  AsyncCallback callback,
1252                                                  object state) {
1253
1254                         if (disposed && closed)
1255                                 throw new ObjectDisposedException (GetType ().ToString ());
1256
1257                         if (end_point == null)
1258                                 throw new ArgumentNullException ("end_point");
1259
1260                         SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Connect);
1261                         req.EndPoint = end_point;
1262
1263                         // Bug #75154: Connect() should not succeed for .Any addresses.
1264                         if (end_point is IPEndPoint) {
1265                                 IPEndPoint ep = (IPEndPoint) end_point;
1266                                 if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)) {
1267                                         req.Complete (new SocketException ((int) SocketError.AddressNotAvailable), true);
1268                                         return req;
1269                                 }
1270                         }
1271
1272                         int error = 0;
1273                         if (!blocking) {
1274                                 SocketAddress serial = end_point.Serialize ();
1275                                 Connect_internal (socket, serial, out error);
1276                                 if (error == 0) {
1277                                         // succeeded synch
1278                                         connected = true;
1279                                         req.Complete (true);
1280                                 } else if (error != (int) SocketError.InProgress && error != (int) SocketError.WouldBlock) {
1281                                         // error synch
1282                                         connected = false;
1283                                         req.Complete (new SocketException (error), true);
1284                                 }
1285                         }
1286
1287                         if (blocking || error == (int) SocketError.InProgress || error == (int) SocketError.WouldBlock) {
1288                                 // continue asynch
1289                                 connected = false;
1290                                 Worker worker = new Worker (req);
1291                                 SocketAsyncCall sac = new SocketAsyncCall (worker.Connect);
1292                                 sac.BeginInvoke (null, req);
1293                         }
1294
1295                         return(req);
1296                 }
1297
1298 #if NET_2_0
1299                 public IAsyncResult BeginConnect (IPAddress address, int port,
1300                                                   AsyncCallback callback,
1301                                                   object state)
1302                 {
1303                         if (disposed && closed)
1304                                 throw new ObjectDisposedException (GetType ().ToString ());
1305
1306                         if (address == null)
1307                                 throw new ArgumentNullException ("address");
1308
1309                         if (address.ToString ().Length == 0)
1310                                 throw new ArgumentException ("The length of the IP address is zero");
1311
1312                         if (islistening)
1313                                 throw new InvalidOperationException ();
1314
1315                         IPEndPoint iep = new IPEndPoint (address, port);
1316                         return(BeginConnect (iep, callback, state));
1317                 }
1318
1319                 public IAsyncResult BeginConnect (IPAddress[] addresses,
1320                                                   int port,
1321                                                   AsyncCallback callback,
1322                                                   object state)
1323                 {
1324                         if (disposed && closed)
1325                                 throw new ObjectDisposedException (GetType ().ToString ());
1326
1327                         if (addresses == null)
1328                                 throw new ArgumentNullException ("addresses");
1329
1330                         if (this.AddressFamily != AddressFamily.InterNetwork &&
1331                                 this.AddressFamily != AddressFamily.InterNetworkV6)
1332                                 throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
1333
1334                         if (islistening)
1335                                 throw new InvalidOperationException ();
1336
1337                         SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Connect);
1338                         req.Addresses = addresses;
1339                         req.Port = port;
1340                         
1341                         connected = false;
1342                         Worker worker = new Worker (req);
1343                         SocketAsyncCall sac = new SocketAsyncCall (worker.Connect);
1344                         sac.BeginInvoke (null, req);
1345                         
1346                         return(req);
1347                 }
1348
1349                 public IAsyncResult BeginConnect (string host, int port,
1350                                                   AsyncCallback callback,
1351                                                   object state)
1352                 {
1353                         if (disposed && closed)
1354                                 throw new ObjectDisposedException (GetType ().ToString ());
1355
1356                         if (host == null)
1357                                 throw new ArgumentNullException ("host");
1358
1359                         if (address_family != AddressFamily.InterNetwork &&
1360                                 address_family != AddressFamily.InterNetworkV6)
1361                                 throw new NotSupportedException ("This method is valid only for sockets in the InterNetwork and InterNetworkV6 families");
1362
1363                         if (islistening)
1364                                 throw new InvalidOperationException ();
1365
1366                         IPAddress [] addresses = Dns.GetHostAddresses (host);
1367                         return (BeginConnect (addresses, port, callback, state));
1368                 }
1369
1370                 public IAsyncResult BeginDisconnect (bool reuseSocket,
1371                                                      AsyncCallback callback,
1372                                                      object state)
1373                 {
1374                         if (disposed && closed)
1375                                 throw new ObjectDisposedException (GetType ().ToString ());
1376
1377                         SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Disconnect);
1378                         req.ReuseSocket = reuseSocket;
1379                         
1380                         Worker worker = new Worker (req);
1381                         SocketAsyncCall sac = new SocketAsyncCall (worker.Disconnect);
1382                         sac.BeginInvoke (null, req);
1383                         
1384                         return(req);
1385                 }
1386 #endif
1387                 
1388                 public IAsyncResult BeginReceive(byte[] buffer, int offset,
1389                                                  int size,
1390                                                  SocketFlags socket_flags,
1391                                                  AsyncCallback callback,
1392                                                  object state) {
1393
1394                         if (disposed && closed)
1395                                 throw new ObjectDisposedException (GetType ().ToString ());
1396
1397                         if (buffer == null)
1398                                 throw new ArgumentNullException ("buffer");
1399
1400                         if (offset < 0 || offset > buffer.Length)
1401                                 throw new ArgumentOutOfRangeException ("offset");
1402
1403                         if (size < 0 || offset + size > buffer.Length)
1404                                 throw new ArgumentOutOfRangeException ("size");
1405
1406                         SocketAsyncResult req;
1407                         lock (readQ) {
1408                                 req = new SocketAsyncResult (this, state, callback, SocketOperation.Receive);
1409                                 req.Buffer = buffer;
1410                                 req.Offset = offset;
1411                                 req.Size = size;
1412                                 req.SockFlags = socket_flags;
1413                                 readQ.Enqueue (req);
1414                                 if (readQ.Count == 1) {
1415                                         Worker worker = new Worker (req);
1416                                         SocketAsyncCall sac = new SocketAsyncCall (worker.Receive);
1417                                         sac.BeginInvoke (null, req);
1418                                 }
1419                         }
1420
1421                         return req;
1422                 }
1423 #if NET_2_0
1424                 public IAsyncResult BeginReceive (byte[] buffer, int offset,
1425                                                   int size, SocketFlags flags,
1426                                                   out SocketError error,
1427                                                   AsyncCallback callback,
1428                                                   object state)
1429                 {
1430                         /* As far as I can tell from the docs and from
1431                          * experimentation, a pointer to the
1432                          * SocketError parameter is not supposed to be
1433                          * saved for the async parts.  And as we don't
1434                          * set any socket errors in the setup code, we
1435                          * just have to set it to Success.
1436                          */
1437                         error = SocketError.Success;
1438                         return (BeginReceive (buffer, offset, size, flags, callback, state));
1439                 }
1440
1441                 [CLSCompliant (false)]
1442                 public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers,
1443                                                   SocketFlags socketFlags,
1444                                                   AsyncCallback callback,
1445                                                   object state)
1446                 {
1447                         if (disposed && closed)
1448                                 throw new ObjectDisposedException (GetType ().ToString ());
1449
1450                         if (buffers == null)
1451                                 throw new ArgumentNullException ("buffers");
1452
1453                         SocketAsyncResult req;
1454                         lock(readQ) {
1455                                 req = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveGeneric);
1456                                 req.Buffers = buffers;
1457                                 req.SockFlags = socketFlags;
1458                                 readQ.Enqueue (req);
1459                                 if (readQ.Count == 1) {
1460                                         Worker worker = new Worker (req);
1461                                         SocketAsyncCall sac = new SocketAsyncCall (worker.ReceiveGeneric);
1462                                         sac.BeginInvoke (null, req);
1463                                 }
1464                         }
1465                         
1466                         return(req);
1467                 }
1468                 
1469                 [CLSCompliant (false)]
1470                 public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers,
1471                                                   SocketFlags socketFlags,
1472                                                   out SocketError errorCode,
1473                                                   AsyncCallback callback,
1474                                                   object state)
1475                 {
1476                         /* I assume the same SocketError semantics as
1477                          * above
1478                          */
1479                         errorCode = SocketError.Success;
1480                         return (BeginReceive (buffers, socketFlags, callback, state));
1481                 }
1482 #endif
1483
1484                 public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset,
1485                                                      int size,
1486                                                      SocketFlags socket_flags,
1487                                                      ref EndPoint remote_end,
1488                                                      AsyncCallback callback,
1489                                                      object state) {
1490                         if (disposed && closed)
1491                                 throw new ObjectDisposedException (GetType ().ToString ());
1492
1493                         if (buffer == null)
1494                                 throw new ArgumentNullException ("buffer");
1495
1496                         if (offset < 0)
1497                                 throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
1498
1499                         if (size < 0)
1500                                 throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
1501
1502                         if (offset + size > buffer.Length)
1503                                 throw new ArgumentOutOfRangeException ("offset, size", "offset + size exceeds the buffer length");
1504
1505                         SocketAsyncResult req;
1506                         lock (readQ) {
1507                                 req = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveFrom);
1508                                 req.Buffer = buffer;
1509                                 req.Offset = offset;
1510                                 req.Size = size;
1511                                 req.SockFlags = socket_flags;
1512                                 req.EndPoint = remote_end;
1513                                 readQ.Enqueue (req);
1514                                 if (readQ.Count == 1) {
1515                                         Worker worker = new Worker (req);
1516                                         SocketAsyncCall sac = new SocketAsyncCall (worker.ReceiveFrom);
1517                                         sac.BeginInvoke (null, req);
1518                                 }
1519                         }
1520                         return req;
1521                 }
1522
1523 #if NET_2_0
1524                 [MonoTODO]
1525                 public IAsyncResult BeginReceiveMessageFrom (
1526                         byte[] buffer, int offset, int size,
1527                         SocketFlags socketFlags, ref EndPoint remoteEP,
1528                         AsyncCallback callback, object state)
1529                 {
1530                         if (disposed && closed)
1531                                 throw new ObjectDisposedException (GetType ().ToString ());
1532
1533                         if (buffer == null)
1534                                 throw new ArgumentNullException ("buffer");
1535
1536                         if (remoteEP == null)
1537                                 throw new ArgumentNullException ("remoteEP");
1538
1539                         if (offset < 0 || offset > buffer.Length)
1540                                 throw new ArgumentOutOfRangeException ("offset");
1541
1542                         if (size < 0 || offset + size > buffer.Length)
1543                                 throw new ArgumentOutOfRangeException ("size");
1544
1545                         throw new NotImplementedException ();
1546                 }
1547 #endif
1548
1549                 public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socket_flags,
1550                                                AsyncCallback callback, object state)
1551                 {
1552                         if (disposed && closed)
1553                                 throw new ObjectDisposedException (GetType ().ToString ());
1554
1555                         if (buffer == null)
1556                                 throw new ArgumentNullException ("buffer");
1557
1558                         if (offset < 0)
1559                                 throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
1560
1561                         if (size < 0)
1562                                 throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
1563
1564                         if (offset + size > buffer.Length)
1565                                 throw new ArgumentOutOfRangeException ("offset, size", "offset + size exceeds the buffer length");
1566
1567 #if NET_2_0
1568                         /* TODO: Check this exception in the 1.1 profile */
1569                         if (!connected)
1570                                 throw new SocketException ((int)SocketError.NotConnected);
1571 #endif
1572
1573                         SocketAsyncResult req;
1574                         lock (writeQ) {
1575                                 req = new SocketAsyncResult (this, state, callback, SocketOperation.Send);
1576                                 req.Buffer = buffer;
1577                                 req.Offset = offset;
1578                                 req.Size = size;
1579                                 req.SockFlags = socket_flags;
1580                                 writeQ.Enqueue (req);
1581                                 if (writeQ.Count == 1) {
1582                                         Worker worker = new Worker (req);
1583                                         SocketAsyncCall sac = new SocketAsyncCall (worker.Send);
1584                                         sac.BeginInvoke (null, req);
1585                                 }
1586                         }
1587                         return req;
1588                 }
1589
1590 #if NET_2_0
1591                 public IAsyncResult BeginSend (byte[] buffer, int offset,
1592                                                int size,
1593                                                SocketFlags socketFlags,
1594                                                out SocketError errorCode,
1595                                                AsyncCallback callback,
1596                                                object state)
1597                 {
1598                         if (!connected) {
1599                                 errorCode = SocketError.NotConnected;
1600                                 throw new SocketException ((int)errorCode);
1601                         }
1602                         
1603                         errorCode = SocketError.Success;
1604                         
1605                         return (BeginSend (buffer, offset, size, socketFlags, callback,
1606                                 state));
1607                 }
1608
1609                 public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers,
1610                                                SocketFlags socketFlags,
1611                                                AsyncCallback callback,
1612                                                object state)
1613                 {
1614                         if (disposed && closed)
1615                                 throw new ObjectDisposedException (GetType ().ToString ());
1616
1617                         if (buffers == null)
1618                                 throw new ArgumentNullException ("buffers");
1619
1620                         if (!connected)
1621                                 throw new SocketException ((int)SocketError.NotConnected);
1622
1623                         SocketAsyncResult req;
1624                         lock (writeQ) {
1625                                 req = new SocketAsyncResult (this, state, callback, SocketOperation.SendGeneric);
1626                                 req.Buffers = buffers;
1627                                 req.SockFlags = socketFlags;
1628                                 writeQ.Enqueue (req);
1629                                 if (writeQ.Count == 1) {
1630                                         Worker worker = new Worker (req);
1631                                         SocketAsyncCall sac = new SocketAsyncCall (worker.SendGeneric);
1632                                         sac.BeginInvoke (null, req);
1633                                 }
1634                         }
1635                         
1636                         return(req);
1637                 }
1638
1639                 [CLSCompliant (false)]
1640                 public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers,
1641                                                SocketFlags socketFlags,
1642                                                out SocketError errorCode,
1643                                                AsyncCallback callback,
1644                                                object state)
1645                 {
1646                         if (!connected) {
1647                                 errorCode = SocketError.NotConnected;
1648                                 throw new SocketException ((int)errorCode);
1649                         }
1650                         
1651                         errorCode = SocketError.Success;
1652                         return (BeginSend (buffers, socketFlags, callback, state));
1653                 }
1654
1655                 delegate void SendFileHandler (string fileName, byte [] preBuffer, byte [] postBuffer, TransmitFileOptions flags);
1656
1657                 sealed class SendFileAsyncResult : IAsyncResult {
1658                         IAsyncResult ares;
1659                         SendFileHandler d;
1660
1661                         public SendFileAsyncResult (SendFileHandler d, IAsyncResult ares)
1662                         {
1663                                 this.d = d;
1664                                 this.ares = ares;
1665                         }
1666
1667                         public object AsyncState {
1668                                 get { return ares.AsyncState; }
1669                         }
1670
1671                         public WaitHandle AsyncWaitHandle {
1672                                 get { return ares.AsyncWaitHandle; }
1673                         }
1674
1675                         public bool CompletedSynchronously {
1676                                 get { return ares.CompletedSynchronously; }
1677                         }
1678
1679                         public bool IsCompleted {
1680                                 get { return ares.IsCompleted; }
1681                         }
1682
1683                         public SendFileHandler Delegate {
1684                                 get { return d; }
1685                         }
1686
1687                         public IAsyncResult Original {
1688                                 get { return ares; }
1689                         }
1690                 }
1691
1692                 public IAsyncResult BeginSendFile (string fileName,
1693                                                    AsyncCallback callback,
1694                                                    object state)
1695                 {
1696                         if (disposed && closed)
1697                                 throw new ObjectDisposedException (GetType ().ToString ());
1698
1699                         if (!connected)
1700                                 throw new NotSupportedException ();
1701
1702                         if (!File.Exists (fileName))
1703                                 throw new FileNotFoundException ();
1704
1705                         return BeginSendFile (fileName, null, null, 0, callback, state);
1706                 }
1707
1708                 public IAsyncResult BeginSendFile (string fileName,
1709                                                    byte[] preBuffer,
1710                                                    byte[] postBuffer,
1711                                                    TransmitFileOptions flags,
1712                                                    AsyncCallback callback,
1713                                                    object state)
1714                 {
1715                         if (disposed && closed)
1716                                 throw new ObjectDisposedException (GetType ().ToString ());
1717
1718                         if (!connected)
1719                                 throw new NotSupportedException ();
1720
1721                         if (!File.Exists (fileName))
1722                                 throw new FileNotFoundException ();
1723
1724                         SendFileHandler d = new SendFileHandler (SendFile);
1725                         return new SendFileAsyncResult (d, d.BeginInvoke (fileName, preBuffer, postBuffer, flags, callback, state));
1726                 }
1727 #endif
1728
1729                 public IAsyncResult BeginSendTo(byte[] buffer, int offset,
1730                                                 int size,
1731                                                 SocketFlags socket_flags,
1732                                                 EndPoint remote_end,
1733                                                 AsyncCallback callback,
1734                                                 object state) {
1735                         if (disposed && closed)
1736                                 throw new ObjectDisposedException (GetType ().ToString ());
1737
1738                         if (buffer == null)
1739                                 throw new ArgumentNullException ("buffer");
1740
1741                         if (offset < 0)
1742                                 throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
1743
1744                         if (size < 0)
1745                                 throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
1746
1747                         if (offset + size > buffer.Length)
1748                                 throw new ArgumentOutOfRangeException ("offset, size", "offset + size exceeds the buffer length");
1749
1750                         SocketAsyncResult req;
1751                         lock (writeQ) {
1752                                 req = new SocketAsyncResult (this, state, callback, SocketOperation.SendTo);
1753                                 req.Buffer = buffer;
1754                                 req.Offset = offset;
1755                                 req.Size = size;
1756                                 req.SockFlags = socket_flags;
1757                                 req.EndPoint = remote_end;
1758                                 writeQ.Enqueue (req);
1759                                 if (writeQ.Count == 1) {
1760                                         Worker worker = new Worker (req);
1761                                         SocketAsyncCall sac = new SocketAsyncCall (worker.SendTo);
1762                                         sac.BeginInvoke (null, req);
1763                                 }
1764                         }
1765                         return req;
1766                 }
1767
1768                 // Creates a new system socket, returning the handle
1769                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1770                 private extern static void Bind_internal(IntPtr sock,
1771                                                          SocketAddress sa,
1772                                                          out int error);
1773
1774                 public void Bind(EndPoint local_end) {
1775                         if (disposed && closed)
1776                                 throw new ObjectDisposedException (GetType ().ToString ());
1777
1778                         if (local_end == null)
1779                                 throw new ArgumentNullException("local_end");
1780                         
1781                         int error;
1782                         
1783                         Bind_internal(socket, local_end.Serialize(), out error);
1784                         if (error != 0)
1785                                 throw new SocketException (error);
1786 #if NET_2_0
1787                         if (error == 0)
1788                                 isbound = true;
1789 #endif
1790                         
1791                         seed_endpoint = local_end;
1792                 }
1793
1794 #if !MOONLIGHT
1795                 public bool ConnectAsync (SocketAsyncEventArgs e)
1796                 {
1797                         // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1798                         
1799                         if (disposed && closed)
1800                                 throw new ObjectDisposedException (GetType ().ToString ());
1801                         if (islistening)
1802                                 throw new InvalidOperationException ("You may not perform this operation after calling the Listen method.");
1803                         if (e.RemoteEndPoint == null)
1804                                 throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
1805                         if (e.BufferList != null)
1806                                 throw new ArgumentException ("Multiple buffers cannot be used with this method.");
1807
1808                         e.DoOperation (SocketAsyncOperation.Connect, this);
1809
1810                         // We always return true for now
1811                         return true;
1812                 }
1813 #endif
1814                 
1815 #if NET_2_0
1816                 public void Connect (IPAddress address, int port)
1817                 {
1818                         Connect (new IPEndPoint (address, port));
1819                 }
1820                 
1821                 public void Connect (IPAddress[] addresses, int port)
1822                 {
1823                         if (disposed && closed)
1824                                 throw new ObjectDisposedException (GetType ().ToString ());
1825
1826                         if (addresses == null)
1827                                 throw new ArgumentNullException ("addresses");
1828
1829                         if (this.AddressFamily != AddressFamily.InterNetwork &&
1830                                 this.AddressFamily != AddressFamily.InterNetworkV6)
1831                                 throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
1832
1833                         if (islistening)
1834                                 throw new InvalidOperationException ();
1835
1836                         /* FIXME: do non-blocking sockets Poll here? */
1837                         int error = 0;
1838                         foreach (IPAddress address in addresses) {
1839                                 IPEndPoint iep = new IPEndPoint (address, port);
1840                                 SocketAddress serial = iep.Serialize ();
1841                                 
1842                                 Connect_internal (socket, serial, out error);
1843                                 if (error == 0) {
1844                                         connected = true;
1845                                         seed_endpoint = iep;
1846                                         return;
1847                                 } else if (error != (int)SocketError.InProgress &&
1848                                            error != (int)SocketError.WouldBlock) {
1849                                         continue;
1850                                 }
1851                                 
1852                                 if (!blocking) {
1853                                         Poll (-1, SelectMode.SelectWrite);
1854                                         error = (int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
1855                                         if (error == 0) {
1856                                                 connected = true;
1857                                                 seed_endpoint = iep;
1858                                                 return;
1859                                         }
1860                                 }
1861                         }
1862                         if (error != 0)
1863                                 throw new SocketException (error);
1864                 }
1865
1866                 public void Connect (string host, int port)
1867                 {
1868                         IPAddress [] addresses = Dns.GetHostAddresses (host);
1869                         Connect (addresses, port);
1870                 }
1871
1872 #if NET_2_0
1873                 public bool DisconnectAsync (SocketAsyncEventArgs e)
1874                 {
1875                         // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1876                         if (disposed && closed)
1877                                 throw new ObjectDisposedException (GetType ().ToString ());
1878
1879                         e.DoOperation (SocketAsyncOperation.Disconnect, this);
1880
1881                         return true;
1882                 }
1883 #endif
1884                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1885                 private extern static void Disconnect_internal(IntPtr sock,
1886                                                                bool reuse,
1887                                                                out int error);
1888
1889                 /* According to the docs, the MS runtime will throw
1890                  * PlatformNotSupportedException if the platform is
1891                  * newer than w2k.  We should be able to cope...
1892                  */
1893                 public void Disconnect (bool reuseSocket)
1894                 {
1895                         if (disposed && closed)
1896                                 throw new ObjectDisposedException (GetType ().ToString ());
1897
1898                         int error = 0;
1899                         
1900                         Disconnect_internal (socket, reuseSocket, out error);
1901
1902                         if (error != 0) {
1903                                 if (error == 50) {
1904                                         /* ERROR_NOT_SUPPORTED */
1905                                         throw new PlatformNotSupportedException ();
1906                                 } else {
1907                                         throw new SocketException (error);
1908                                 }
1909                         }
1910
1911                         connected = false;
1912                         
1913                         if (reuseSocket) {
1914                                 /* Do managed housekeeping here... */
1915                         }
1916                 }
1917
1918                 [MonoTODO ("Not implemented")]
1919                 public SocketInformation DuplicateAndClose (int targetProcessId)
1920                 {
1921                         /* Need to serialize this socket into a
1922                          * SocketInformation struct, but must study
1923                          * the MS implementation harder to figure out
1924                          * behaviour as documentation is lacking
1925                          */
1926                         throw new NotImplementedException ();
1927                 }
1928 #endif
1929                 
1930                 public Socket EndAccept (IAsyncResult result)
1931                 {
1932                         int bytes;
1933                         byte[] buffer;
1934                         
1935                         return(EndAccept (out buffer, out bytes, result));
1936                 }
1937
1938 #if NET_2_0
1939                 public Socket EndAccept (out byte[] buffer,
1940                                          IAsyncResult asyncResult)
1941                 {
1942                         int bytes;
1943                         
1944                         return(EndAccept (out buffer, out bytes, asyncResult));
1945                 }
1946 #endif
1947
1948 #if NET_2_0
1949                 public
1950 #else
1951                 private
1952 #endif
1953                 Socket EndAccept (out byte[] buffer, out int bytesTransferred,
1954                                   IAsyncResult asyncResult)
1955                 {
1956                         if (disposed && closed)
1957                                 throw new ObjectDisposedException (GetType ().ToString ());
1958
1959                         if (asyncResult == null)
1960                                 throw new ArgumentNullException ("asyncResult");
1961                         
1962                         SocketAsyncResult req = asyncResult as SocketAsyncResult;
1963                         if (req == null)
1964                                 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
1965
1966                         if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
1967                                 throw InvalidAsyncOp ("EndAccept");
1968                         if (!asyncResult.IsCompleted)
1969                                 asyncResult.AsyncWaitHandle.WaitOne ();
1970
1971                         req.CheckIfThrowDelayedException ();
1972                         
1973                         buffer = req.Buffer;
1974                         bytesTransferred = req.Total;
1975                         
1976                         return(req.Socket);
1977                 }
1978
1979                 public void EndConnect (IAsyncResult result)
1980                 {
1981                         if (disposed && closed)
1982                                 throw new ObjectDisposedException (GetType ().ToString ());
1983
1984                         if (result == null)
1985                                 throw new ArgumentNullException ("result");
1986
1987                         SocketAsyncResult req = result as SocketAsyncResult;
1988                         if (req == null)
1989                                 throw new ArgumentException ("Invalid IAsyncResult", "result");
1990
1991                         if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
1992                                 throw InvalidAsyncOp ("EndConnect");
1993                         if (!result.IsCompleted)
1994                                 result.AsyncWaitHandle.WaitOne();
1995
1996                         req.CheckIfThrowDelayedException();
1997                 }
1998
1999 #if NET_2_0
2000                 public void EndDisconnect (IAsyncResult asyncResult)
2001                 {
2002                         if (disposed && closed)
2003                                 throw new ObjectDisposedException (GetType ().ToString ());
2004
2005                         if (asyncResult == null)
2006                                 throw new ArgumentNullException ("asyncResult");
2007
2008                         SocketAsyncResult req = asyncResult as SocketAsyncResult;
2009                         if (req == null)
2010                                 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
2011
2012                         if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
2013                                 throw InvalidAsyncOp ("EndDisconnect");
2014                         if (!asyncResult.IsCompleted)
2015                                 asyncResult.AsyncWaitHandle.WaitOne ();
2016
2017                         req.CheckIfThrowDelayedException ();
2018                 }
2019 #endif
2020
2021                 public int EndReceive (IAsyncResult result)
2022                 {
2023                         SocketError error;
2024                         
2025                         return (EndReceive (result, out error));
2026                 }
2027
2028 #if NET_2_0
2029                 public
2030 #else
2031                 private
2032 #endif
2033                 int EndReceive (IAsyncResult asyncResult, out SocketError errorCode)
2034                 {
2035                         if (disposed && closed)
2036                                 throw new ObjectDisposedException (GetType ().ToString ());
2037
2038                         if (asyncResult == null)
2039                                 throw new ArgumentNullException ("asyncResult");
2040
2041                         SocketAsyncResult req = asyncResult as SocketAsyncResult;
2042                         if (req == null)
2043                                 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
2044
2045                         if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
2046                                 throw InvalidAsyncOp ("EndReceive");
2047                         if (!asyncResult.IsCompleted)
2048                                 asyncResult.AsyncWaitHandle.WaitOne ();
2049
2050                         errorCode = req.ErrorCode;
2051                         req.CheckIfThrowDelayedException ();
2052                         
2053                         return(req.Total);
2054                 }
2055
2056                 public int EndReceiveFrom(IAsyncResult result, ref EndPoint end_point)
2057                 {
2058                         if (disposed && closed)
2059                                 throw new ObjectDisposedException (GetType ().ToString ());
2060
2061                         if (result == null)
2062                                 throw new ArgumentNullException ("result");
2063
2064                         SocketAsyncResult req = result as SocketAsyncResult;
2065                         if (req == null)
2066                                 throw new ArgumentException ("Invalid IAsyncResult", "result");
2067
2068                         if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
2069                                 throw InvalidAsyncOp ("EndReceiveFrom");
2070                         if (!result.IsCompleted)
2071                                 result.AsyncWaitHandle.WaitOne();
2072
2073                         req.CheckIfThrowDelayedException();
2074                         end_point = req.EndPoint;
2075                         return req.Total;
2076                 }
2077
2078 #if NET_2_0
2079                 [MonoTODO]
2080                 public int EndReceiveMessageFrom (IAsyncResult asyncResult,
2081                                                   ref SocketFlags socketFlags,
2082                                                   ref EndPoint endPoint,
2083                                                   out IPPacketInformation ipPacketInformation)
2084                 {
2085                         if (disposed && closed)
2086                                 throw new ObjectDisposedException (GetType ().ToString ());
2087
2088                         if (asyncResult == null)
2089                                 throw new ArgumentNullException ("asyncResult");
2090
2091                         if (endPoint == null)
2092                                 throw new ArgumentNullException ("endPoint");
2093
2094                         SocketAsyncResult req = asyncResult as SocketAsyncResult;
2095                         if (req == null)
2096                                 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
2097
2098                         if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
2099                                 throw InvalidAsyncOp ("EndReceiveMessageFrom");
2100                         throw new NotImplementedException ();
2101                 }
2102 #endif
2103
2104                 public int EndSend (IAsyncResult result)
2105                 {
2106                         SocketError error;
2107                         
2108                         return(EndSend (result, out error));
2109                 }
2110
2111 #if NET_2_0
2112                 public
2113 #else
2114                 private
2115 #endif
2116                 int EndSend (IAsyncResult asyncResult, out SocketError errorCode)
2117                 {
2118                         if (disposed && closed)
2119                                 throw new ObjectDisposedException (GetType ().ToString ());
2120
2121                         if (asyncResult == null)
2122                                 throw new ArgumentNullException ("asyncResult");
2123                         
2124                         SocketAsyncResult req = asyncResult as SocketAsyncResult;
2125                         if (req == null)
2126                                 throw new ArgumentException ("Invalid IAsyncResult", "result");
2127
2128                         if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
2129                                 throw InvalidAsyncOp ("EndSend");
2130                         if (!asyncResult.IsCompleted)
2131                                 asyncResult.AsyncWaitHandle.WaitOne ();
2132
2133                         errorCode = req.ErrorCode;
2134                         req.CheckIfThrowDelayedException ();
2135                         
2136                         return(req.Total);
2137                 }
2138
2139 #if NET_2_0
2140                 public void EndSendFile (IAsyncResult asyncResult)
2141                 {
2142                         if (disposed && closed)
2143                                 throw new ObjectDisposedException (GetType ().ToString ());
2144
2145                         if (asyncResult == null)
2146                                 throw new ArgumentNullException ("asyncResult");
2147
2148                         SendFileAsyncResult ares = asyncResult as SendFileAsyncResult;
2149                         if (ares == null)
2150                                 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
2151
2152                         ares.Delegate.EndInvoke (ares.Original);
2153                 }
2154 #endif
2155
2156                 Exception InvalidAsyncOp (string method)
2157                 {
2158                         return new InvalidOperationException (method + " can only be called once per asynchronous operation");
2159                 }
2160
2161                 public int EndSendTo (IAsyncResult result)
2162                 {
2163                         if (disposed && closed)
2164                                 throw new ObjectDisposedException (GetType ().ToString ());
2165
2166                         if (result == null)
2167                                 throw new ArgumentNullException ("result");
2168
2169                         SocketAsyncResult req = result as SocketAsyncResult;
2170                         if (req == null)
2171                                 throw new ArgumentException ("Invalid IAsyncResult", "result");
2172
2173                         if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
2174                                 throw InvalidAsyncOp ("EndSendTo");
2175                         if (!result.IsCompleted)
2176                                 result.AsyncWaitHandle.WaitOne();
2177
2178                         req.CheckIfThrowDelayedException();
2179                         return req.Total;
2180                 }
2181
2182                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2183                 private extern static void GetSocketOption_arr_internal(IntPtr socket,
2184                         SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val,
2185                         out int error);
2186
2187                 public void GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, byte [] optionValue)
2188                 {
2189                         if (disposed && closed)
2190                                 throw new ObjectDisposedException (GetType ().ToString ());
2191
2192                         if (optionValue == null)
2193                                 throw new SocketException ((int) SocketError.Fault,
2194                                         "Error trying to dereference an invalid pointer");
2195
2196                         int error;
2197
2198                         GetSocketOption_arr_internal (socket, optionLevel, optionName, ref optionValue,
2199                                 out error);
2200                         if (error != 0)
2201                                 throw new SocketException (error);
2202                 }
2203
2204                 public byte [] GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int length)
2205                 {
2206                         if (disposed && closed)
2207                                 throw new ObjectDisposedException (GetType ().ToString ());
2208
2209                         byte[] byte_val=new byte[length];
2210                         int error;
2211
2212                         GetSocketOption_arr_internal (socket, optionLevel, optionName, ref byte_val,
2213                                 out error);
2214                         if (error != 0)
2215                                 throw new SocketException (error);
2216
2217                         return(byte_val);
2218                 }
2219
2220                 // See Socket.IOControl, WSAIoctl documentation in MSDN. The
2221                 // common options between UNIX and Winsock are FIONREAD,
2222                 // FIONBIO and SIOCATMARK. Anything else will depend on the
2223                 // system.
2224                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2225                 extern static int WSAIoctl (IntPtr sock, int ioctl_code, byte [] input,
2226                         byte [] output, out int error);
2227
2228                 public int IOControl (int ioctl_code, byte [] in_value, byte [] out_value)
2229                 {
2230                         if (disposed)
2231                                 throw new ObjectDisposedException (GetType ().ToString ());
2232
2233                         int error;
2234                         int result = WSAIoctl (socket, ioctl_code, in_value, out_value,
2235                                 out error);
2236
2237                         if (error != 0)
2238                                 throw new SocketException (error);
2239                         
2240                         if (result == -1)
2241                                 throw new InvalidOperationException ("Must use Blocking property instead.");
2242
2243                         return result;
2244                 }
2245
2246 #if NET_2_0
2247                 [MonoTODO]
2248                 public int IOControl (IOControlCode ioControlCode,
2249                                       byte[] optionInValue,
2250                                       byte[] optionOutValue)
2251                 {
2252                         /* Probably just needs to mirror the int
2253                          * overload, but more investigation needed.
2254                          */
2255                         throw new NotImplementedException ();
2256                 }
2257 #endif
2258
2259                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2260                 private extern static void Listen_internal(IntPtr sock, int backlog,
2261                         out int error);
2262
2263                 public void Listen (int backlog)
2264                 {
2265                         if (disposed && closed)
2266                                 throw new ObjectDisposedException (GetType ().ToString ());
2267
2268 #if NET_2_0
2269                         /* TODO: check if this should be thrown in the
2270                          * 1.1 profile too
2271                          */
2272                         if (!isbound)
2273                                 throw new SocketException ((int)SocketError.InvalidArgument);
2274 #endif
2275
2276                         int error;
2277                         
2278                         Listen_internal(socket, backlog, out error);
2279
2280                         if (error != 0)
2281                                 throw new SocketException (error);
2282
2283 #if NET_2_0
2284                         islistening = true;
2285 #endif
2286                 }
2287
2288                 public bool Poll (int time_us, SelectMode mode)
2289                 {
2290                         if (disposed && closed)
2291                                 throw new ObjectDisposedException (GetType ().ToString ());
2292
2293                         if (mode != SelectMode.SelectRead &&
2294                             mode != SelectMode.SelectWrite &&
2295                             mode != SelectMode.SelectError)
2296                                 throw new NotSupportedException ("'mode' parameter is not valid.");
2297
2298                         int error;
2299                         bool result = Poll_internal (socket, mode, time_us, out error);
2300                         if (error != 0)
2301                                 throw new SocketException (error);
2302
2303                         if (mode == SelectMode.SelectWrite && result && !connected) {
2304                                 /* Update the connected state; for
2305                                  * non-blocking Connect()s this is
2306                                  * when we can find out that the
2307                                  * connect succeeded.
2308                                  */
2309                                 if ((int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error) == 0) {
2310                                         connected = true;
2311                                 }
2312                         }
2313                         
2314                         return result;
2315                 }
2316
2317                 public int Receive (byte [] buffer)
2318                 {
2319                         if (disposed && closed)
2320                                 throw new ObjectDisposedException (GetType ().ToString ());
2321
2322                         if (buffer == null)
2323                                 throw new ArgumentNullException ("buffer");
2324
2325                         SocketError error;
2326
2327                         int ret = Receive_nochecks (buffer, 0, buffer.Length, SocketFlags.None, out error);
2328                         
2329                         if (error != SocketError.Success)
2330                                 throw new SocketException ((int) error);
2331
2332                         return ret;
2333                 }
2334
2335                 public int Receive (byte [] buffer, SocketFlags flags)
2336                 {
2337                         if (disposed && closed)
2338                                 throw new ObjectDisposedException (GetType ().ToString ());
2339
2340                         if (buffer == null)
2341                                 throw new ArgumentNullException ("buffer");
2342
2343                         SocketError error;
2344
2345                         int ret = Receive_nochecks (buffer, 0, buffer.Length, flags, out error);
2346                         
2347                         if (error != SocketError.Success) {
2348                                 if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
2349                                         throw new SocketException ((int) error, "Operation timed out.");
2350                                 throw new SocketException ((int) error);
2351                         }
2352
2353                         return ret;
2354                 }
2355
2356                 public int Receive (byte [] buffer, int size, SocketFlags flags)
2357                 {
2358                         if (disposed && closed)
2359                                 throw new ObjectDisposedException (GetType ().ToString ());
2360
2361                         if (buffer == null)
2362                                 throw new ArgumentNullException ("buffer");
2363
2364                         if (size < 0 || size > buffer.Length)
2365                                 throw new ArgumentOutOfRangeException ("size");
2366
2367                         SocketError error;
2368
2369                         int ret = Receive_nochecks (buffer, 0, size, flags, out error);
2370                         
2371                         if (error != SocketError.Success) {
2372                                 if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
2373                                         throw new SocketException ((int) error, "Operation timed out.");
2374                                 throw new SocketException ((int) error);
2375                         }
2376
2377                         return ret;
2378                 }
2379
2380                 public int Receive (byte [] buffer, int offset, int size, SocketFlags flags)
2381                 {
2382                         if (disposed && closed)
2383                                 throw new ObjectDisposedException (GetType ().ToString ());
2384
2385                         if (buffer == null)
2386                                 throw new ArgumentNullException ("buffer");
2387
2388                         if (offset < 0 || offset > buffer.Length)
2389                                 throw new ArgumentOutOfRangeException ("offset");
2390
2391                         if (size < 0 || offset + size > buffer.Length)
2392                                 throw new ArgumentOutOfRangeException ("size");
2393                         
2394                         SocketError error;
2395
2396                         int ret = Receive_nochecks (buffer, offset, size, flags, out error);
2397                         
2398                         if (error != SocketError.Success) {
2399                                 if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
2400                                         throw new SocketException ((int) error, "Operation timed out.");
2401                                 throw new SocketException ((int) error);
2402                         }
2403
2404                         return ret;
2405                 }
2406
2407 #if NET_2_0
2408                 public int Receive (byte [] buffer, int offset, int size, SocketFlags flags, out SocketError error)
2409                 {
2410                         if (disposed && closed)
2411                                 throw new ObjectDisposedException (GetType ().ToString ());
2412
2413                         if (buffer == null)
2414                                 throw new ArgumentNullException ("buffer");
2415
2416                         if (offset < 0 || offset > buffer.Length)
2417                                 throw new ArgumentOutOfRangeException ("offset");
2418
2419                         if (size < 0 || offset + size > buffer.Length)
2420                                 throw new ArgumentOutOfRangeException ("size");
2421                         
2422                         return Receive_nochecks (buffer, offset, size, flags, out error);
2423                 }
2424
2425                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
2426                 private extern static int Receive_internal (IntPtr sock,
2427                                                             WSABUF[] bufarray,
2428                                                             SocketFlags flags,
2429                                                             out int error);
2430                 
2431                 public int Receive (IList<ArraySegment<byte>> buffers)
2432                 {
2433                         int ret;
2434                         SocketError error;
2435                         
2436                         ret = Receive (buffers, SocketFlags.None, out error);
2437                         if (error != SocketError.Success) {
2438                                 throw new SocketException ((int)error);
2439                         }
2440                         
2441                         return(ret);
2442                 }
2443                 
2444                 [CLSCompliant (false)]
2445                 public int Receive (IList<ArraySegment<byte>> buffers,
2446                                     SocketFlags socketFlags)
2447                 {
2448                         int ret;
2449                         SocketError error;
2450                         
2451                         ret = Receive (buffers, socketFlags, out error);
2452                         if (error != SocketError.Success) {
2453                                 throw new SocketException ((int)error);
2454                         }
2455                         
2456                         return(ret);
2457                 }
2458
2459                 [CLSCompliant (false)]
2460                 public int Receive (IList<ArraySegment<byte>> buffers,
2461                                     SocketFlags socketFlags,
2462                                     out SocketError errorCode)
2463                 {
2464                         if (disposed && closed)
2465                                 throw new ObjectDisposedException (GetType ().ToString ());
2466
2467                         if (buffers == null ||
2468                             buffers.Count == 0) {
2469                                 throw new ArgumentNullException ("buffers");
2470                         }
2471
2472                         int numsegments = buffers.Count;
2473                         int nativeError;
2474                         int ret;
2475
2476                         /* Only example I can find of sending a byte
2477                          * array reference directly into an internal
2478                          * call is in
2479                          * System.Runtime.Remoting/System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeSocket.cs,
2480                          * so taking a lead from that...
2481                          */
2482                         WSABUF[] bufarray = new WSABUF[numsegments];
2483                         GCHandle[] gch = new GCHandle[numsegments];
2484
2485                         for(int i = 0; i < numsegments; i++) {
2486                                 ArraySegment<byte> segment = buffers[i];
2487                                 gch[i] = GCHandle.Alloc (segment.Array, GCHandleType.Pinned);
2488                                 bufarray[i].len = segment.Count;
2489                                 bufarray[i].buf = Marshal.UnsafeAddrOfPinnedArrayElement (segment.Array, segment.Offset);
2490                         }
2491                         
2492                         try {
2493                                 ret = Receive_internal (socket, bufarray,
2494                                                         socketFlags,
2495                                                         out nativeError);
2496                         } finally {
2497                                 for(int i = 0; i < numsegments; i++) {
2498                                         if (gch[i].IsAllocated) {
2499                                                 gch[i].Free ();
2500                                         }
2501                                 }
2502                         }
2503
2504                         errorCode = (SocketError)nativeError;
2505                         return(ret);
2506                 }
2507 #endif
2508
2509 #if NET_2_0
2510                 public bool ReceiveFromAsync (SocketAsyncEventArgs e)
2511                 {
2512                         if (disposed && closed)
2513                                 throw new ObjectDisposedException (GetType ().ToString ());
2514
2515                         // We do not support recv into multiple buffers yet
2516                         if (e.BufferList != null)
2517                                 throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
2518                         if (e.RemoteEndPoint == null)
2519                                 throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
2520
2521                         e.DoOperation (SocketAsyncOperation.ReceiveFrom, this);
2522
2523                         // We always return true for now
2524                         return true;
2525                 }
2526 #endif
2527
2528                 public int ReceiveFrom (byte [] buffer, ref EndPoint remoteEP)
2529                 {
2530                         if (disposed && closed)
2531                                 throw new ObjectDisposedException (GetType ().ToString ());
2532
2533                         if (buffer == null)
2534                                 throw new ArgumentNullException ("buffer");
2535
2536                         if (remoteEP == null)
2537                                 throw new ArgumentNullException ("remoteEP");
2538
2539                         return ReceiveFrom_nochecks (buffer, 0, buffer.Length, SocketFlags.None, ref remoteEP);
2540                 }
2541
2542                 public int ReceiveFrom (byte [] buffer, SocketFlags flags, ref EndPoint remoteEP)
2543                 {
2544                         if (disposed && closed)
2545                                 throw new ObjectDisposedException (GetType ().ToString ());
2546
2547                         if (buffer == null)
2548                                 throw new ArgumentNullException ("buffer");
2549
2550                         if (remoteEP == null)
2551                                 throw new ArgumentNullException ("remoteEP");
2552
2553                         return ReceiveFrom_nochecks (buffer, 0, buffer.Length, flags, ref remoteEP);
2554                 }
2555
2556                 public int ReceiveFrom (byte [] buffer, int size, SocketFlags flags,
2557                                         ref EndPoint remoteEP)
2558                 {
2559                         if (disposed && closed)
2560                                 throw new ObjectDisposedException (GetType ().ToString ());
2561
2562                         if (buffer == null)
2563                                 throw new ArgumentNullException ("buffer");
2564
2565                         if (remoteEP == null)
2566                                 throw new ArgumentNullException ("remoteEP");
2567
2568                         if (size < 0 || size > buffer.Length)
2569                                 throw new ArgumentOutOfRangeException ("size");
2570
2571                         return ReceiveFrom_nochecks (buffer, 0, size, flags, ref remoteEP);
2572                 }
2573
2574                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2575                 private extern static int RecvFrom_internal(IntPtr sock,
2576                                                             byte[] buffer,
2577                                                             int offset,
2578                                                             int count,
2579                                                             SocketFlags flags,
2580                                                             ref SocketAddress sockaddr,
2581                                                             out int error);
2582
2583                 public int ReceiveFrom (byte [] buffer, int offset, int size, SocketFlags flags,
2584                                         ref EndPoint remoteEP)
2585                 {
2586                         if (disposed && closed)
2587                                 throw new ObjectDisposedException (GetType ().ToString ());
2588
2589                         if (buffer == null)
2590                                 throw new ArgumentNullException ("buffer");
2591
2592                         if (remoteEP == null)
2593                                 throw new ArgumentNullException ("remoteEP");
2594
2595                         if (offset < 0 || offset > buffer.Length)
2596                                 throw new ArgumentOutOfRangeException ("offset");
2597
2598                         if (size < 0 || offset + size > buffer.Length)
2599                                 throw new ArgumentOutOfRangeException ("size");
2600
2601                         return ReceiveFrom_nochecks (buffer, offset, size, flags, ref remoteEP);
2602                 }
2603
2604                 internal int ReceiveFrom_nochecks (byte [] buf, int offset, int size, SocketFlags flags,
2605                                                    ref EndPoint remote_end)
2606                 {
2607                         int error;
2608                         return ReceiveFrom_nochecks_exc (buf, offset, size, flags, ref remote_end, true, out error);
2609                 }
2610
2611                 internal int ReceiveFrom_nochecks_exc (byte [] buf, int offset, int size, SocketFlags flags,
2612                                                    ref EndPoint remote_end, bool throwOnError, out int error)
2613                 {
2614                         SocketAddress sockaddr = remote_end.Serialize();
2615                         int cnt = RecvFrom_internal (socket, buf, offset, size, flags, ref sockaddr, out error);
2616                         SocketError err = (SocketError) error;
2617                         if (err != 0) {
2618                                 if (err != SocketError.WouldBlock && err != SocketError.InProgress)
2619                                         connected = false;
2620                                 else if (err == SocketError.WouldBlock && blocking) { // This might happen when ReceiveTimeout is set
2621                                         if (throwOnError)       
2622                                                 throw new SocketException ((int) SocketError.TimedOut, "Operation timed out");
2623                                         error = (int) SocketError.TimedOut;
2624                                         return 0;
2625                                 }
2626
2627                                 if (throwOnError)
2628                                         throw new SocketException (error);
2629                                 return 0;
2630                         }
2631
2632                         connected = true;
2633
2634 #if NET_2_0
2635                         isbound = true;
2636 #endif
2637
2638                         // If sockaddr is null then we're a connection
2639                         // oriented protocol and should ignore the
2640                         // remote_end parameter (see MSDN
2641                         // documentation for Socket.ReceiveFrom(...) )
2642                         
2643                         if ( sockaddr != null ) {
2644                                 // Stupidly, EndPoint.Create() is an
2645                                 // instance method
2646                                 remote_end = remote_end.Create (sockaddr);
2647                         }
2648                         
2649                         seed_endpoint = remote_end;
2650                         
2651                         return cnt;
2652                 }
2653
2654 #if NET_2_0
2655                 [MonoTODO ("Not implemented")]
2656                 public bool ReceiveMessageFromAsync (SocketAsyncEventArgs e)
2657                 {
2658                         // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
2659                         if (disposed && closed)
2660                                 throw new ObjectDisposedException (GetType ().ToString ());
2661                         
2662                         throw new NotImplementedException ();
2663                 }
2664                 
2665                 [MonoTODO ("Not implemented")]
2666                 public int ReceiveMessageFrom (byte[] buffer, int offset,
2667                                                int size,
2668                                                ref SocketFlags socketFlags,
2669                                                ref EndPoint remoteEP,
2670                                                out IPPacketInformation ipPacketInformation)
2671                 {
2672                         if (disposed && closed)
2673                                 throw new ObjectDisposedException (GetType ().ToString ());
2674
2675                         if (buffer == null)
2676                                 throw new ArgumentNullException ("buffer");
2677
2678                         if (remoteEP == null)
2679                                 throw new ArgumentNullException ("remoteEP");
2680
2681                         if (offset < 0 || offset > buffer.Length)
2682                                 throw new ArgumentOutOfRangeException ("offset");
2683
2684                         if (size < 0 || offset + size > buffer.Length)
2685                                 throw new ArgumentOutOfRangeException ("size");
2686
2687                         /* FIXME: figure out how we get hold of the
2688                          * IPPacketInformation
2689                          */
2690                         throw new NotImplementedException ();
2691                 }
2692
2693                 [MonoTODO ("Not implemented")]
2694                 public bool SendPacketsAsync (SocketAsyncEventArgs e)
2695                 {
2696                         // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
2697                         
2698                         if (disposed && closed)
2699                                 throw new ObjectDisposedException (GetType ().ToString ());
2700                         
2701                         throw new NotImplementedException ();
2702                 }
2703
2704 #endif
2705
2706                 public int Send (byte [] buf)
2707                 {
2708                         if (disposed && closed)
2709                                 throw new ObjectDisposedException (GetType ().ToString ());
2710
2711                         if (buf == null)
2712                                 throw new ArgumentNullException ("buf");
2713
2714                         SocketError error;
2715
2716                         int ret = Send_nochecks (buf, 0, buf.Length, SocketFlags.None, out error);
2717
2718                         if (error != SocketError.Success)
2719                                 throw new SocketException ((int) error);
2720
2721                         return ret;
2722                 }
2723
2724                 public int Send (byte [] buf, SocketFlags flags)
2725                 {
2726                         if (disposed && closed)
2727                                 throw new ObjectDisposedException (GetType ().ToString ());
2728
2729                         if (buf == null)
2730                                 throw new ArgumentNullException ("buf");
2731
2732                         SocketError error;
2733
2734                         int ret = Send_nochecks (buf, 0, buf.Length, flags, out error);
2735
2736                         if (error != SocketError.Success)
2737                                 throw new SocketException ((int) error);
2738
2739                         return ret;
2740                 }
2741
2742                 public int Send (byte [] buf, int size, SocketFlags flags)
2743                 {
2744                         if (disposed && closed)
2745                                 throw new ObjectDisposedException (GetType ().ToString ());
2746
2747                         if (buf == null)
2748                                 throw new ArgumentNullException ("buf");
2749
2750                         if (size < 0 || size > buf.Length)
2751                                 throw new ArgumentOutOfRangeException ("size");
2752
2753                         SocketError error;
2754
2755                         int ret = Send_nochecks (buf, 0, size, flags, out error);
2756
2757                         if (error != SocketError.Success)
2758                                 throw new SocketException ((int) error);
2759
2760                         return ret;
2761                 }
2762
2763                 public int Send (byte [] buf, int offset, int size, SocketFlags flags)
2764                 {
2765                         if (disposed && closed)
2766                                 throw new ObjectDisposedException (GetType ().ToString ());
2767
2768                         if (buf == null)
2769                                 throw new ArgumentNullException ("buffer");
2770
2771                         if (offset < 0 || offset > buf.Length)
2772                                 throw new ArgumentOutOfRangeException ("offset");
2773
2774                         if (size < 0 || offset + size > buf.Length)
2775                                 throw new ArgumentOutOfRangeException ("size");
2776
2777                         SocketError error;
2778
2779                         int ret = Send_nochecks (buf, offset, size, flags, out error);
2780
2781                         if (error != SocketError.Success)
2782                                 throw new SocketException ((int) error);
2783
2784                         return ret;
2785                 }
2786
2787 #if NET_2_0
2788                 public int Send (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
2789                 {
2790                         if (disposed && closed)
2791                                 throw new ObjectDisposedException (GetType ().ToString ());
2792
2793                         if (buf == null)
2794                                 throw new ArgumentNullException ("buffer");
2795
2796                         if (offset < 0 || offset > buf.Length)
2797                                 throw new ArgumentOutOfRangeException ("offset");
2798
2799                         if (size < 0 || offset + size > buf.Length)
2800                                 throw new ArgumentOutOfRangeException ("size");
2801
2802                         return Send_nochecks (buf, offset, size, flags, out error);
2803                 }
2804
2805                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
2806                 private extern static int Send_internal (IntPtr sock,
2807                                                          WSABUF[] bufarray,
2808                                                          SocketFlags flags,
2809                                                          out int error);
2810
2811                 public int Send (IList<ArraySegment<byte>> buffers)
2812                 {
2813                         int ret;
2814                         SocketError error;
2815                         
2816                         ret = Send (buffers, SocketFlags.None, out error);
2817                         if (error != SocketError.Success) {
2818                                 throw new SocketException ((int)error);
2819                         }
2820                         
2821                         return(ret);
2822                 }
2823
2824                 public int Send (IList<ArraySegment<byte>> buffers,
2825                                  SocketFlags socketFlags)
2826                 {
2827                         int ret;
2828                         SocketError error;
2829                         
2830                         ret = Send (buffers, socketFlags, out error);
2831                         if (error != SocketError.Success) {
2832                                 throw new SocketException ((int)error);
2833                         }
2834                         
2835                         return(ret);
2836                 }
2837
2838                 [CLSCompliant (false)]
2839                 public int Send (IList<ArraySegment<byte>> buffers,
2840                                  SocketFlags socketFlags,
2841                                  out SocketError errorCode)
2842                 {
2843                         if (disposed && closed) {
2844                                 throw new ObjectDisposedException (GetType ().ToString ());
2845                         }
2846                         
2847                         if (buffers == null) {
2848                                 throw new ArgumentNullException ("buffers");
2849                         }
2850                         
2851                         if (buffers.Count == 0) {
2852                                 throw new ArgumentException ("Buffer is empty", "buffers");
2853                         }
2854                         
2855                         int numsegments = buffers.Count;
2856                         int nativeError;
2857                         int ret;
2858                         
2859                         WSABUF[] bufarray = new WSABUF[numsegments];
2860                         GCHandle[] gch = new GCHandle[numsegments];
2861                         
2862                         for(int i = 0; i < numsegments; i++) {
2863                                 ArraySegment<byte> segment = buffers[i];
2864                                 gch[i] = GCHandle.Alloc (segment.Array, GCHandleType.Pinned);
2865                                 bufarray[i].len = segment.Count;
2866                                 bufarray[i].buf = Marshal.UnsafeAddrOfPinnedArrayElement (segment.Array, segment.Offset);
2867                         }
2868                         
2869                         try {
2870                                 ret = Send_internal (socket, bufarray,
2871                                                      socketFlags,
2872                                                      out nativeError);
2873                         } finally {
2874                                 for(int i = 0; i < numsegments; i++) {
2875                                         if (gch[i].IsAllocated) {
2876                                                 gch[i].Free ();
2877                                         }
2878                                 }
2879                         }
2880                         
2881                         errorCode = (SocketError)nativeError;
2882                         return(ret);
2883                 }
2884
2885                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2886                 private extern static bool SendFile (IntPtr sock, string filename, byte [] pre_buffer, byte [] post_buffer, TransmitFileOptions flags);
2887
2888                 public void SendFile (string fileName)
2889                 {
2890                         if (disposed && closed)
2891                                 throw new ObjectDisposedException (GetType ().ToString ());
2892
2893                         if (!connected)
2894                                 throw new NotSupportedException ();
2895
2896                         if (!blocking)
2897                                 throw new InvalidOperationException ();
2898
2899                         SendFile (fileName, null, null, 0);
2900                 }
2901
2902                 public void SendFile (string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags)
2903                 {
2904                         if (disposed && closed)
2905                                 throw new ObjectDisposedException (GetType ().ToString ());
2906
2907                         if (!connected)
2908                                 throw new NotSupportedException ();
2909
2910                         if (!blocking)
2911                                 throw new InvalidOperationException ();
2912
2913                         if (!SendFile (socket, fileName, preBuffer, postBuffer, flags)) {
2914                                 SocketException exc = new SocketException ();
2915                                 if (exc.ErrorCode == 2 || exc.ErrorCode == 3)
2916                                         throw new FileNotFoundException ();
2917                                 throw exc;
2918                         }
2919                 }
2920
2921                 public bool SendToAsync (SocketAsyncEventArgs e)
2922                 {
2923                         // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
2924                         
2925                         if (disposed && closed)
2926                                 throw new ObjectDisposedException (GetType ().ToString ());
2927                         if (e.RemoteEndPoint == null)
2928                                 throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
2929                         
2930                         e.DoOperation (SocketAsyncOperation.SendTo, this);
2931
2932                         // We always return true for now
2933                         return true;
2934                 }
2935 #endif
2936                 
2937                 public int SendTo (byte [] buffer, EndPoint remote_end)
2938                 {
2939                         if (disposed && closed)
2940                                 throw new ObjectDisposedException (GetType ().ToString ());
2941
2942                         if (buffer == null)
2943                                 throw new ArgumentNullException ("buffer");
2944
2945                         if (remote_end == null)
2946                                 throw new ArgumentNullException ("remote_end");
2947
2948                         return SendTo_nochecks (buffer, 0, buffer.Length, SocketFlags.None, remote_end);
2949                 }
2950
2951                 public int SendTo (byte [] buffer, SocketFlags flags, EndPoint remote_end)
2952                 {
2953                         if (disposed && closed)
2954                                 throw new ObjectDisposedException (GetType ().ToString ());
2955
2956                         if (buffer == null)
2957                                 throw new ArgumentNullException ("buffer");
2958
2959                         if (remote_end == null)
2960                                 throw new ArgumentNullException ("remote_end");
2961                                 
2962                         return SendTo_nochecks (buffer, 0, buffer.Length, flags, remote_end);
2963                 }
2964
2965                 public int SendTo (byte [] buffer, int size, SocketFlags flags, EndPoint remote_end)
2966                 {
2967                         if (disposed && closed)
2968                                 throw new ObjectDisposedException (GetType ().ToString ());
2969
2970                         if (buffer == null)
2971                                 throw new ArgumentNullException ("buffer");
2972
2973                         if (remote_end == null)
2974                                 throw new ArgumentNullException ("remote_end");
2975
2976                         if (size < 0 || size > buffer.Length)
2977                                 throw new ArgumentOutOfRangeException ("size");
2978
2979                         return SendTo_nochecks (buffer, 0, size, flags, remote_end);
2980                 }
2981
2982                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2983                 private extern static int SendTo_internal(IntPtr sock,
2984                                                           byte[] buffer,
2985                                                           int offset,
2986                                                           int count,
2987                                                           SocketFlags flags,
2988                                                           SocketAddress sa,
2989                                                           out int error);
2990
2991                 public int SendTo (byte [] buffer, int offset, int size, SocketFlags flags,
2992                                    EndPoint remote_end)
2993                 {
2994                         if (disposed && closed)
2995                                 throw new ObjectDisposedException (GetType ().ToString ());
2996
2997                         if (buffer == null)
2998                                 throw new ArgumentNullException ("buffer");
2999
3000                         if (remote_end == null)
3001                                 throw new ArgumentNullException("remote_end");
3002
3003                         if (offset < 0 || offset > buffer.Length)
3004                                 throw new ArgumentOutOfRangeException ("offset");
3005
3006                         if (size < 0 || offset + size > buffer.Length)
3007                                 throw new ArgumentOutOfRangeException ("size");
3008
3009                         return SendTo_nochecks (buffer, offset, size, flags, remote_end);
3010                 }
3011
3012                 internal int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags,
3013                                               EndPoint remote_end)
3014                 {
3015                         SocketAddress sockaddr = remote_end.Serialize ();
3016
3017                         int ret, error;
3018
3019                         ret = SendTo_internal (socket, buffer, offset, size, flags, sockaddr, out error);
3020
3021                         SocketError err = (SocketError) error;
3022                         if (err != 0) {
3023                                 if (err != SocketError.WouldBlock && err != SocketError.InProgress)
3024                                         connected = false;
3025
3026                                 throw new SocketException (error);
3027                         }
3028
3029                         connected = true;
3030
3031 #if NET_2_0
3032                         isbound = true;
3033 #endif
3034                         
3035                         seed_endpoint = remote_end;
3036                         
3037                         return ret;
3038                 }
3039
3040                 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, byte [] optionValue)
3041                 {
3042                         if (disposed && closed)
3043                                 throw new ObjectDisposedException (GetType ().ToString ());
3044
3045                         // I'd throw an ArgumentNullException, but this is what MS does.
3046                         if (optionValue == null)
3047                                 throw new SocketException ((int) SocketError.Fault,
3048                                         "Error trying to dereference an invalid pointer");
3049                         
3050                         int error;
3051
3052                         SetSocketOption_internal (socket, optionLevel, optionName, null,
3053                                                  optionValue, 0, out error);
3054
3055                         if (error != 0) {
3056                                 if (error == (int) SocketError.InvalidArgument)
3057                                         throw new ArgumentException ();
3058                                 throw new SocketException (error);
3059                         }
3060                 }
3061
3062                 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, object optionValue)
3063                 {
3064                         if (disposed && closed)
3065                                 throw new ObjectDisposedException (GetType ().ToString ());
3066
3067                         // NOTE: if a null is passed, the byte[] overload is used instead...
3068                         if (optionValue == null)
3069                                 throw new ArgumentNullException("optionValue");
3070                         
3071                         int error;
3072
3073                         if (optionLevel == SocketOptionLevel.Socket && optionName == SocketOptionName.Linger) {
3074                                 LingerOption linger = optionValue as LingerOption;
3075                                 if (linger == null)
3076 #if NET_2_0
3077                                         throw new ArgumentException ("A 'LingerOption' value must be specified.", "optionValue");
3078 #else
3079                                         throw new ArgumentException ("optionValue");
3080 #endif
3081                                 SetSocketOption_internal (socket, optionLevel, optionName, linger, null, 0, out error);
3082                         } else if (optionLevel == SocketOptionLevel.IP && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
3083                                 MulticastOption multicast = optionValue as MulticastOption;
3084                                 if (multicast == null)
3085 #if NET_2_0
3086                                         throw new ArgumentException ("A 'MulticastOption' value must be specified.", "optionValue");
3087 #else
3088                                         throw new ArgumentException ("optionValue");
3089 #endif
3090                                 SetSocketOption_internal (socket, optionLevel, optionName, multicast, null, 0, out error);
3091                         } else if (optionLevel == SocketOptionLevel.IPv6 && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
3092                                 IPv6MulticastOption multicast = optionValue as IPv6MulticastOption;
3093                                 if (multicast == null)
3094 #if NET_2_0
3095                                         throw new ArgumentException ("A 'IPv6MulticastOption' value must be specified.", "optionValue");
3096 #else
3097                                         throw new ArgumentException ("optionValue");
3098 #endif
3099                                 SetSocketOption_internal (socket, optionLevel, optionName, multicast, null, 0, out error);
3100                         } else {
3101 #if NET_2_0
3102                                 throw new ArgumentException ("Invalid value specified.", "optionValue");
3103 #else
3104                                 throw new ArgumentException ("optionValue");
3105 #endif
3106                         }
3107
3108                         if (error != 0) {
3109                                 if (error == (int) SocketError.InvalidArgument)
3110                                         throw new ArgumentException ();
3111                                 throw new SocketException (error);
3112                         }
3113                 }
3114
3115 #if NET_2_0
3116                 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, bool optionValue)
3117                 {
3118                         if (disposed && closed)
3119                                 throw new ObjectDisposedException (GetType ().ToString ());
3120
3121                         int error;
3122                         int int_val = (optionValue) ? 1 : 0;
3123                         SetSocketOption_internal (socket, optionLevel, optionName, null, null, int_val, out error);
3124                         if (error != 0) {
3125                                 if (error == (int) SocketError.InvalidArgument)
3126                                         throw new ArgumentException ();
3127                                 throw new SocketException (error);
3128                         }
3129                 }
3130 #endif
3131
3132 #if ONLY_1_1
3133                 public override int GetHashCode ()
3134                 {
3135                         // LAMESPEC:
3136                         // The socket is not suitable to serve as a hash code,
3137                         // because it will change during its lifetime, but
3138                         // this is how MS.NET 1.1 implemented this method.
3139                         return (int) socket; 
3140                 }
3141 #endif
3142         }
3143 }