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