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