* System_test.dll.sources: Added IPv6MulticastOptionTest.cs and
[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                                         int error = (int) SocketError.InProgress; // why?
433                                         foreach(IPAddress address in result.Addresses) {
434                                                 IPEndPoint iep = new IPEndPoint (address, result.Port);
435                                                 SocketAddress serial = iep.Serialize ();
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 (error));
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                         IPAddress [] addresses = Dns.GetHostAddresses (host);
1375                         return (BeginConnect (addresses, 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                         IPAddress [] addresses = Dns.GetHostAddresses (host);
1854                         Connect (addresses, 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                         if (opt_value == null)
2181                                 throw new SocketException ((int) SocketError.Fault,
2182                                         "Error trying to dereference an invalid pointer");
2183
2184                         int error;
2185                         
2186                         GetSocketOption_arr_internal(socket, level, name, ref opt_value,
2187                                 out error);
2188                         if (error != 0)
2189                                 throw new SocketException (error);
2190                 }
2191
2192                 public byte [] GetSocketOption (SocketOptionLevel level, SocketOptionName name, int length)
2193                 {
2194                         if (disposed && closed)
2195                                 throw new ObjectDisposedException (GetType ().ToString ());
2196
2197                         byte[] byte_val=new byte[length];
2198                         int error;
2199                         
2200                         GetSocketOption_arr_internal(socket, level, name, ref byte_val,
2201                                 out error);
2202                         if (error != 0)
2203                                 throw new SocketException (error);
2204
2205                         return(byte_val);
2206                 }
2207
2208                 // See Socket.IOControl, WSAIoctl documentation in MSDN. The
2209                 // common options between UNIX and Winsock are FIONREAD,
2210                 // FIONBIO and SIOCATMARK. Anything else will depend on the
2211                 // system.
2212                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2213                 extern static int WSAIoctl (IntPtr sock, int ioctl_code, byte [] input,
2214                         byte [] output, out int error);
2215
2216                 public int IOControl (int ioctl_code, byte [] in_value, byte [] out_value)
2217                 {
2218                         if (disposed)
2219                                 throw new ObjectDisposedException (GetType ().ToString ());
2220
2221                         int error;
2222                         int result = WSAIoctl (socket, ioctl_code, in_value, out_value,
2223                                 out error);
2224
2225                         if (error != 0)
2226                                 throw new SocketException (error);
2227                         
2228                         if (result == -1)
2229                                 throw new InvalidOperationException ("Must use Blocking property instead.");
2230
2231                         return result;
2232                 }
2233
2234 #if NET_2_0
2235                 [MonoTODO]
2236                 public int IOControl (IOControlCode ioControlCode,
2237                                       byte[] optionInValue,
2238                                       byte[] optionOutValue)
2239                 {
2240                         /* Probably just needs to mirror the int
2241                          * overload, but more investigation needed.
2242                          */
2243                         throw new NotImplementedException ();
2244                 }
2245 #endif
2246
2247                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2248                 private extern static void Listen_internal(IntPtr sock, int backlog,
2249                         out int error);
2250
2251                 public void Listen (int backlog)
2252                 {
2253                         if (disposed && closed)
2254                                 throw new ObjectDisposedException (GetType ().ToString ());
2255
2256 #if NET_2_0
2257                         /* TODO: check if this should be thrown in the
2258                          * 1.1 profile too
2259                          */
2260                         if (!isbound)
2261                                 throw new SocketException ((int)SocketError.InvalidArgument);
2262 #endif
2263
2264                         int error;
2265                         
2266                         Listen_internal(socket, backlog, out error);
2267
2268                         if (error != 0)
2269                                 throw new SocketException (error);
2270
2271 #if NET_2_0
2272                         islistening = true;
2273 #endif
2274                 }
2275
2276                 public bool Poll (int time_us, SelectMode mode)
2277                 {
2278                         if (disposed && closed)
2279                                 throw new ObjectDisposedException (GetType ().ToString ());
2280
2281                         if (mode != SelectMode.SelectRead &&
2282                             mode != SelectMode.SelectWrite &&
2283                             mode != SelectMode.SelectError)
2284                                 throw new NotSupportedException ("'mode' parameter is not valid.");
2285
2286                         int error;
2287                         bool result = Poll_internal (socket, mode, time_us, out error);
2288                         if (error != 0)
2289                                 throw new SocketException (error);
2290
2291                         if (mode == SelectMode.SelectWrite && result && !connected) {
2292                                 /* Update the connected state; for
2293                                  * non-blocking Connect()s this is
2294                                  * when we can find out that the
2295                                  * connect succeeded.
2296                                  */
2297                                 if ((int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error) == 0) {
2298                                         connected = true;
2299                                 }
2300                         }
2301                         
2302                         return result;
2303                 }
2304
2305                 public int Receive (byte [] buf)
2306                 {
2307                         if (disposed && closed)
2308                                 throw new ObjectDisposedException (GetType ().ToString ());
2309
2310                         if (buf == null)
2311                                 throw new ArgumentNullException ("buf");
2312
2313                         SocketError error;
2314
2315                         int ret = Receive_nochecks (buf, 0, buf.Length, SocketFlags.None, out error);
2316                         
2317                         if (error != SocketError.Success)
2318                                 throw new SocketException ((int) error);
2319
2320                         return ret;
2321                 }
2322
2323                 public int Receive (byte [] buf, SocketFlags flags)
2324                 {
2325                         if (disposed && closed)
2326                                 throw new ObjectDisposedException (GetType ().ToString ());
2327
2328                         if (buf == null)
2329                                 throw new ArgumentNullException ("buf");
2330
2331                         SocketError error;
2332
2333                         int ret = Receive_nochecks (buf, 0, buf.Length, flags, out error);
2334                         
2335                         if (error != SocketError.Success) {
2336                                 if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
2337                                         throw new SocketException ((int) error, "Operation timed out.");
2338                                 throw new SocketException ((int) error);
2339                         }
2340
2341                         return ret;
2342                 }
2343
2344                 public int Receive (byte [] buf, int size, SocketFlags flags)
2345                 {
2346                         if (disposed && closed)
2347                                 throw new ObjectDisposedException (GetType ().ToString ());
2348
2349                         if (buf == null)
2350                                 throw new ArgumentNullException ("buf");
2351
2352                         if (size < 0 || size > buf.Length)
2353                                 throw new ArgumentOutOfRangeException ("size");
2354
2355                         SocketError error;
2356
2357                         int ret = Receive_nochecks (buf, 0, size, flags, out error);
2358                         
2359                         if (error != SocketError.Success) {
2360                                 if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
2361                                         throw new SocketException ((int) error, "Operation timed out.");
2362                                 throw new SocketException ((int) error);
2363                         }
2364
2365                         return ret;
2366                 }
2367
2368                 public int Receive (byte [] buf, int offset, int size, SocketFlags flags)
2369                 {
2370                         if (disposed && closed)
2371                                 throw new ObjectDisposedException (GetType ().ToString ());
2372
2373                         if (buf == null)
2374                                 throw new ArgumentNullException ("buf");
2375
2376                         if (offset < 0 || offset > buf.Length)
2377                                 throw new ArgumentOutOfRangeException ("offset");
2378
2379                         if (size < 0 || offset + size > buf.Length)
2380                                 throw new ArgumentOutOfRangeException ("size");
2381                         
2382                         SocketError error;
2383
2384                         int ret = Receive_nochecks (buf, offset, size, flags, out error);
2385                         
2386                         if (error != SocketError.Success) {
2387                                 if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
2388                                         throw new SocketException ((int) error, "Operation timed out.");
2389                                 throw new SocketException ((int) error);
2390                         }
2391
2392                         return ret;
2393                 }
2394
2395 #if NET_2_0
2396                 public int Receive (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
2397                 {
2398                         if (disposed && closed)
2399                                 throw new ObjectDisposedException (GetType ().ToString ());
2400
2401                         if (buf == null)
2402                                 throw new ArgumentNullException ("buf");
2403
2404                         if (offset < 0 || offset > buf.Length)
2405                                 throw new ArgumentOutOfRangeException ("offset");
2406
2407                         if (size < 0 || offset + size > buf.Length)
2408                                 throw new ArgumentOutOfRangeException ("size");
2409                         
2410                         return Receive_nochecks (buf, offset, size, flags, out error);
2411                 }
2412
2413                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
2414                 private extern static int Receive_internal (IntPtr sock,
2415                                                             WSABUF[] bufarray,
2416                                                             SocketFlags flags,
2417                                                             out int error);
2418                 
2419                 public int Receive (IList<ArraySegment<byte>> buffers)
2420                 {
2421                         int ret;
2422                         SocketError error;
2423                         
2424                         ret = Receive (buffers, SocketFlags.None, out error);
2425                         if (error != SocketError.Success) {
2426                                 throw new SocketException ((int)error);
2427                         }
2428                         
2429                         return(ret);
2430                 }
2431                 
2432                 [CLSCompliant (false)]
2433                 public int Receive (IList<ArraySegment<byte>> buffers,
2434                                     SocketFlags socketFlags)
2435                 {
2436                         int ret;
2437                         SocketError error;
2438                         
2439                         ret = Receive (buffers, socketFlags, out error);
2440                         if (error != SocketError.Success) {
2441                                 throw new SocketException ((int)error);
2442                         }
2443                         
2444                         return(ret);
2445                 }
2446
2447                 [CLSCompliant (false)]
2448                 public int Receive (IList<ArraySegment<byte>> buffers,
2449                                     SocketFlags socketFlags,
2450                                     out SocketError errorCode)
2451                 {
2452                         if (buffers == null ||
2453                             buffers.Count == 0) {
2454                                 throw new ArgumentNullException ("buffers");
2455                         }
2456                         
2457                         if (disposed && closed) {
2458                                 throw new ObjectDisposedException (GetType ().ToString ());
2459                         }
2460
2461                         int numsegments = buffers.Count;
2462                         int nativeError;
2463                         int ret;                        
2464
2465                         /* Only example I can find of sending a byte
2466                          * array reference directly into an internal
2467                          * call is in
2468                          * System.Runtime.Remoting/System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeSocket.cs,
2469                          * so taking a lead from that...
2470                          */
2471                         WSABUF[] bufarray = new WSABUF[numsegments];
2472                         GCHandle[] gch = new GCHandle[numsegments];
2473
2474                         for(int i = 0; i < numsegments; i++) {
2475                                 ArraySegment<byte> segment = buffers[i];
2476                                 gch[i] = GCHandle.Alloc (segment.Array, GCHandleType.Pinned);
2477                                 bufarray[i].len = segment.Count;
2478                                 bufarray[i].buf = Marshal.UnsafeAddrOfPinnedArrayElement (segment.Array, segment.Offset);
2479                         }
2480                         
2481                         try {
2482                                 ret = Receive_internal (socket, bufarray,
2483                                                         socketFlags,
2484                                                         out nativeError);
2485                         } finally {
2486                                 for(int i = 0; i < numsegments; i++) {
2487                                         if (gch[i].IsAllocated) {
2488                                                 gch[i].Free ();
2489                                         }
2490                                 }
2491                         }
2492
2493                         errorCode = (SocketError)nativeError;
2494                         return(ret);
2495                 }
2496 #endif
2497
2498 #if NET_2_0
2499                 public bool ReceiveFromAsync (SocketAsyncEventArgs e)
2500                 {
2501                         if (disposed && closed)
2502                                 throw new ObjectDisposedException (GetType ().ToString ());
2503
2504                         // We do not support recv into multiple buffers yet
2505                         if (e.BufferList != null)
2506                                 throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
2507                         if (e.RemoteEndPoint == null)
2508                                 throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
2509
2510                         e.DoOperation (SocketAsyncOperation.ReceiveFrom, this);
2511
2512                         // We always return true for now
2513                         return true;
2514                 }
2515 #endif
2516                 
2517                 public int ReceiveFrom (byte [] buf, ref EndPoint remote_end)
2518                 {
2519                         if (disposed && closed)
2520                                 throw new ObjectDisposedException (GetType ().ToString ());
2521
2522                         if (buf == null)
2523                                 throw new ArgumentNullException ("buf");
2524
2525                         if (remote_end == null)
2526                                 throw new ArgumentNullException ("remote_end");
2527
2528                         return ReceiveFrom_nochecks (buf, 0, buf.Length, SocketFlags.None, ref remote_end);
2529                 }
2530
2531                 public int ReceiveFrom (byte [] buf, SocketFlags flags, ref EndPoint remote_end)
2532                 {
2533                         if (disposed && closed)
2534                                 throw new ObjectDisposedException (GetType ().ToString ());
2535
2536                         if (buf == null)
2537                                 throw new ArgumentNullException ("buf");
2538
2539                         if (remote_end == null)
2540                                 throw new ArgumentNullException ("remote_end");
2541
2542                         return ReceiveFrom_nochecks (buf, 0, buf.Length, flags, ref remote_end);
2543                 }
2544
2545                 public int ReceiveFrom (byte [] buf, int size, SocketFlags flags,
2546                                         ref EndPoint remote_end)
2547                 {
2548                         if (disposed && closed)
2549                                 throw new ObjectDisposedException (GetType ().ToString ());
2550
2551                         if (buf == null)
2552                                 throw new ArgumentNullException ("buf");
2553
2554                         if (remote_end == null)
2555                                 throw new ArgumentNullException ("remote_end");
2556
2557                         if (size < 0 || size > buf.Length)
2558                                 throw new ArgumentOutOfRangeException ("size");
2559
2560                         return ReceiveFrom_nochecks (buf, 0, size, flags, ref remote_end);
2561                 }
2562
2563                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2564                 private extern static int RecvFrom_internal(IntPtr sock,
2565                                                             byte[] buffer,
2566                                                             int offset,
2567                                                             int count,
2568                                                             SocketFlags flags,
2569                                                             ref SocketAddress sockaddr,
2570                                                             out int error);
2571
2572                 public int ReceiveFrom (byte [] buf, int offset, int size, SocketFlags flags,
2573                                         ref EndPoint remote_end)
2574                 {
2575                         if (disposed && closed)
2576                                 throw new ObjectDisposedException (GetType ().ToString ());
2577
2578                         if (buf == null)
2579                                 throw new ArgumentNullException ("buf");
2580
2581                         if (remote_end == null)
2582                                 throw new ArgumentNullException ("remote_end");
2583
2584                         if (offset < 0 || offset > buf.Length)
2585                                 throw new ArgumentOutOfRangeException ("offset");
2586
2587                         if (size < 0 || offset + size > buf.Length)
2588                                 throw new ArgumentOutOfRangeException ("size");
2589
2590                         return ReceiveFrom_nochecks (buf, offset, size, flags, ref remote_end);
2591                 }
2592
2593                 internal int ReceiveFrom_nochecks (byte [] buf, int offset, int size, SocketFlags flags,
2594                                                    ref EndPoint remote_end)
2595                 {
2596                         int error;
2597                         return ReceiveFrom_nochecks_exc (buf, offset, size, flags, ref remote_end, true, out error);
2598                 }
2599
2600                 internal int ReceiveFrom_nochecks_exc (byte [] buf, int offset, int size, SocketFlags flags,
2601                                                    ref EndPoint remote_end, bool throwOnError, out int error)
2602                 {
2603                         SocketAddress sockaddr = remote_end.Serialize();
2604                         int cnt = RecvFrom_internal (socket, buf, offset, size, flags, ref sockaddr, out error);
2605                         SocketError err = (SocketError) error;
2606                         if (err != 0) {
2607                                 if (err != SocketError.WouldBlock && err != SocketError.InProgress)
2608                                         connected = false;
2609                                 else if (err == SocketError.WouldBlock && blocking) { // This might happen when ReceiveTimeout is set
2610                                         if (throwOnError)       
2611                                                 throw new SocketException ((int) SocketError.TimedOut, "Operation timed out");
2612                                         error = (int) SocketError.TimedOut;
2613                                         return 0;
2614                                 }
2615
2616                                 if (throwOnError)
2617                                         throw new SocketException (error);
2618                                 return 0;
2619                         }
2620
2621                         connected = true;
2622
2623 #if NET_2_0
2624                         isbound = true;
2625 #endif
2626
2627                         // If sockaddr is null then we're a connection
2628                         // oriented protocol and should ignore the
2629                         // remote_end parameter (see MSDN
2630                         // documentation for Socket.ReceiveFrom(...) )
2631                         
2632                         if ( sockaddr != null ) {
2633                                 // Stupidly, EndPoint.Create() is an
2634                                 // instance method
2635                                 remote_end = remote_end.Create (sockaddr);
2636                         }
2637                         
2638                         seed_endpoint = remote_end;
2639                         
2640                         return cnt;
2641                 }
2642
2643 #if NET_2_0
2644                 [MonoTODO ("Not implemented")]
2645                 public bool ReceiveMessageFromAsync (SocketAsyncEventArgs e)
2646                 {
2647                         // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
2648                         if (disposed && closed)
2649                                 throw new ObjectDisposedException (GetType ().ToString ());
2650                         
2651                         throw new NotImplementedException ();
2652                 }
2653                 
2654                 [MonoTODO ("Not implemented")]
2655                 public int ReceiveMessageFrom (byte[] buffer, int offset,
2656                                                int size,
2657                                                ref SocketFlags socketFlags,
2658                                                ref EndPoint remoteEP,
2659                                                out IPPacketInformation ipPacketInformation)
2660                 {
2661                         if (disposed && closed)
2662                                 throw new ObjectDisposedException (GetType ().ToString ());
2663
2664                         if (buffer == null)
2665                                 throw new ArgumentNullException ("buffer");
2666
2667                         if (remoteEP == null)
2668                                 throw new ArgumentNullException ("remoteEP");
2669
2670                         if (offset < 0 || offset > buffer.Length)
2671                                 throw new ArgumentOutOfRangeException ("offset");
2672
2673                         if (size < 0 || offset + size > buffer.Length)
2674                                 throw new ArgumentOutOfRangeException ("size");
2675
2676                         /* FIXME: figure out how we get hold of the
2677                          * IPPacketInformation
2678                          */
2679                         throw new NotImplementedException ();
2680                 }
2681
2682                 [MonoTODO ("Not implemented")]
2683                 public bool SendPacketsAsync (SocketAsyncEventArgs e)
2684                 {
2685                         // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
2686                         
2687                         if (disposed && closed)
2688                                 throw new ObjectDisposedException (GetType ().ToString ());
2689                         
2690                         throw new NotImplementedException ();
2691                 }
2692
2693 #endif
2694
2695                 public int Send (byte [] buf)
2696                 {
2697                         if (disposed && closed)
2698                                 throw new ObjectDisposedException (GetType ().ToString ());
2699
2700                         if (buf == null)
2701                                 throw new ArgumentNullException ("buf");
2702
2703                         SocketError error;
2704
2705                         int ret = Send_nochecks (buf, 0, buf.Length, SocketFlags.None, out error);
2706
2707                         if (error != SocketError.Success)
2708                                 throw new SocketException ((int) error);
2709
2710                         return ret;
2711                 }
2712
2713                 public int Send (byte [] buf, SocketFlags flags)
2714                 {
2715                         if (disposed && closed)
2716                                 throw new ObjectDisposedException (GetType ().ToString ());
2717
2718                         if (buf == null)
2719                                 throw new ArgumentNullException ("buf");
2720
2721                         SocketError error;
2722
2723                         int ret = Send_nochecks (buf, 0, buf.Length, flags, out error);
2724
2725                         if (error != SocketError.Success)
2726                                 throw new SocketException ((int) error);
2727
2728                         return ret;
2729                 }
2730
2731                 public int Send (byte [] buf, int size, SocketFlags flags)
2732                 {
2733                         if (disposed && closed)
2734                                 throw new ObjectDisposedException (GetType ().ToString ());
2735
2736                         if (buf == null)
2737                                 throw new ArgumentNullException ("buf");
2738
2739                         if (size < 0 || size > buf.Length)
2740                                 throw new ArgumentOutOfRangeException ("size");
2741
2742                         SocketError error;
2743
2744                         int ret = Send_nochecks (buf, 0, size, flags, out error);
2745
2746                         if (error != SocketError.Success)
2747                                 throw new SocketException ((int) error);
2748
2749                         return ret;
2750                 }
2751
2752                 public int Send (byte [] buf, int offset, int size, SocketFlags flags)
2753                 {
2754                         if (disposed && closed)
2755                                 throw new ObjectDisposedException (GetType ().ToString ());
2756
2757                         if (buf == null)
2758                                 throw new ArgumentNullException ("buffer");
2759
2760                         if (offset < 0 || offset > buf.Length)
2761                                 throw new ArgumentOutOfRangeException ("offset");
2762
2763                         if (size < 0 || offset + size > buf.Length)
2764                                 throw new ArgumentOutOfRangeException ("size");
2765
2766                         SocketError error;
2767
2768                         int ret = Send_nochecks (buf, offset, size, flags, out error);
2769
2770                         if (error != SocketError.Success)
2771                                 throw new SocketException ((int) error);
2772
2773                         return ret;
2774                 }
2775
2776 #if NET_2_0
2777                 public int Send (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
2778                 {
2779                         if (disposed && closed)
2780                                 throw new ObjectDisposedException (GetType ().ToString ());
2781
2782                         if (buf == null)
2783                                 throw new ArgumentNullException ("buffer");
2784
2785                         if (offset < 0 || offset > buf.Length)
2786                                 throw new ArgumentOutOfRangeException ("offset");
2787
2788                         if (size < 0 || offset + size > buf.Length)
2789                                 throw new ArgumentOutOfRangeException ("size");
2790
2791                         return Send_nochecks (buf, offset, size, flags, out error);
2792                 }
2793
2794                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
2795                 private extern static int Send_internal (IntPtr sock,
2796                                                          WSABUF[] bufarray,
2797                                                          SocketFlags flags,
2798                                                          out int error);
2799
2800                 public int Send (IList<ArraySegment<byte>> buffers)
2801                 {
2802                         int ret;
2803                         SocketError error;
2804                         
2805                         ret = Send (buffers, SocketFlags.None, out error);
2806                         if (error != SocketError.Success) {
2807                                 throw new SocketException ((int)error);
2808                         }
2809                         
2810                         return(ret);
2811                 }
2812
2813                 public int Send (IList<ArraySegment<byte>> buffers,
2814                                  SocketFlags socketFlags)
2815                 {
2816                         int ret;
2817                         SocketError error;
2818                         
2819                         ret = Send (buffers, socketFlags, out error);
2820                         if (error != SocketError.Success) {
2821                                 throw new SocketException ((int)error);
2822                         }
2823                         
2824                         return(ret);
2825                 }
2826
2827                 [CLSCompliant (false)]
2828                 public int Send (IList<ArraySegment<byte>> buffers,
2829                                  SocketFlags socketFlags,
2830                                  out SocketError errorCode)
2831                 {
2832                         if (disposed && closed) {
2833                                 throw new ObjectDisposedException (GetType ().ToString ());
2834                         }
2835                         
2836                         if (buffers == null) {
2837                                 throw new ArgumentNullException ("buffers");
2838                         }
2839                         
2840                         if (buffers.Count == 0) {
2841                                 throw new ArgumentException ("Buffer is empty", "buffers");
2842                         }
2843                         
2844                         int numsegments = buffers.Count;
2845                         int nativeError;
2846                         int ret;
2847                         
2848                         WSABUF[] bufarray = new WSABUF[numsegments];
2849                         GCHandle[] gch = new GCHandle[numsegments];
2850                         
2851                         for(int i = 0; i < numsegments; i++) {
2852                                 ArraySegment<byte> segment = buffers[i];
2853                                 gch[i] = GCHandle.Alloc (segment.Array, GCHandleType.Pinned);
2854                                 bufarray[i].len = segment.Count;
2855                                 bufarray[i].buf = Marshal.UnsafeAddrOfPinnedArrayElement (segment.Array, segment.Offset);
2856                         }
2857                         
2858                         try {
2859                                 ret = Send_internal (socket, bufarray,
2860                                                      socketFlags,
2861                                                      out nativeError);
2862                         } finally {
2863                                 for(int i = 0; i < numsegments; i++) {
2864                                         if (gch[i].IsAllocated) {
2865                                                 gch[i].Free ();
2866                                         }
2867                                 }
2868                         }
2869                         
2870                         errorCode = (SocketError)nativeError;
2871                         return(ret);
2872                 }
2873
2874                 [MonoTODO ("Not implemented")]
2875                 public void SendFile (string fileName)
2876                 {
2877                         if (disposed && closed)
2878                                 throw new ObjectDisposedException (GetType ().ToString ());
2879
2880                         if (!connected)
2881                                 throw new NotSupportedException ();
2882
2883                         if (!blocking)
2884                                 throw new InvalidOperationException ();
2885
2886                         if (!File.Exists (fileName))
2887                                 throw new FileNotFoundException ();
2888
2889                         /* FIXME: Implement TransmitFile */
2890                         throw new NotImplementedException ();
2891                 }
2892
2893                 [MonoTODO ("Not implemented")]
2894                 public void SendFile (string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags)
2895                 {
2896                         if (disposed && closed)
2897                                 throw new ObjectDisposedException (GetType ().ToString ());
2898
2899                         if (!connected)
2900                                 throw new NotSupportedException ();
2901
2902                         if (!blocking)
2903                                 throw new InvalidOperationException ();
2904
2905                         if (!File.Exists (fileName))
2906                                 throw new FileNotFoundException ();
2907
2908                         /* FIXME: Implement TransmitFile */
2909                         throw new NotImplementedException ();
2910                 }
2911
2912                 public bool SendToAsync (SocketAsyncEventArgs e)
2913                 {
2914                         // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
2915                         
2916                         if (disposed && closed)
2917                                 throw new ObjectDisposedException (GetType ().ToString ());
2918                         if (e.RemoteEndPoint == null)
2919                                 throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
2920                         
2921                         e.DoOperation (SocketAsyncOperation.SendTo, this);
2922
2923                         // We always return true for now
2924                         return true;
2925                 }
2926 #endif
2927                 
2928                 public int SendTo (byte [] buffer, EndPoint remote_end)
2929                 {
2930                         if (disposed && closed)
2931                                 throw new ObjectDisposedException (GetType ().ToString ());
2932
2933                         if (buffer == null)
2934                                 throw new ArgumentNullException ("buffer");
2935
2936                         if (remote_end == null)
2937                                 throw new ArgumentNullException ("remote_end");
2938
2939                         return SendTo_nochecks (buffer, 0, buffer.Length, SocketFlags.None, remote_end);
2940                 }
2941
2942                 public int SendTo (byte [] buffer, SocketFlags flags, EndPoint remote_end)
2943                 {
2944                         if (disposed && closed)
2945                                 throw new ObjectDisposedException (GetType ().ToString ());
2946
2947                         if (buffer == null)
2948                                 throw new ArgumentNullException ("buffer");
2949
2950                         if (remote_end == null)
2951                                 throw new ArgumentNullException ("remote_end");
2952                                 
2953                         return SendTo_nochecks (buffer, 0, buffer.Length, flags, remote_end);
2954                 }
2955
2956                 public int SendTo (byte [] buffer, int size, SocketFlags flags, EndPoint remote_end)
2957                 {
2958                         if (disposed && closed)
2959                                 throw new ObjectDisposedException (GetType ().ToString ());
2960
2961                         if (buffer == null)
2962                                 throw new ArgumentNullException ("buffer");
2963
2964                         if (remote_end == null)
2965                                 throw new ArgumentNullException ("remote_end");
2966
2967                         if (size < 0 || size > buffer.Length)
2968                                 throw new ArgumentOutOfRangeException ("size");
2969
2970                         return SendTo_nochecks (buffer, 0, size, flags, remote_end);
2971                 }
2972
2973                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2974                 private extern static int SendTo_internal(IntPtr sock,
2975                                                           byte[] buffer,
2976                                                           int offset,
2977                                                           int count,
2978                                                           SocketFlags flags,
2979                                                           SocketAddress sa,
2980                                                           out int error);
2981
2982                 public int SendTo (byte [] buffer, int offset, int size, SocketFlags flags,
2983                                    EndPoint remote_end)
2984                 {
2985                         if (disposed && closed)
2986                                 throw new ObjectDisposedException (GetType ().ToString ());
2987
2988                         if (buffer == null)
2989                                 throw new ArgumentNullException ("buffer");
2990
2991                         if (remote_end == null)
2992                                 throw new ArgumentNullException("remote_end");
2993
2994                         if (offset < 0 || offset > buffer.Length)
2995                                 throw new ArgumentOutOfRangeException ("offset");
2996
2997                         if (size < 0 || offset + size > buffer.Length)
2998                                 throw new ArgumentOutOfRangeException ("size");
2999
3000                         return SendTo_nochecks (buffer, offset, size, flags, remote_end);
3001                 }
3002
3003                 internal int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags,
3004                                               EndPoint remote_end)
3005                 {
3006                         SocketAddress sockaddr = remote_end.Serialize ();
3007
3008                         int ret, error;
3009
3010                         ret = SendTo_internal (socket, buffer, offset, size, flags, sockaddr, out error);
3011
3012                         SocketError err = (SocketError) error;
3013                         if (err != 0) {
3014                                 if (err != SocketError.WouldBlock && err != SocketError.InProgress)
3015                                         connected = false;
3016
3017                                 throw new SocketException (error);
3018                         }
3019
3020                         connected = true;
3021
3022 #if NET_2_0
3023                         isbound = true;
3024 #endif
3025                         
3026                         seed_endpoint = remote_end;
3027                         
3028                         return ret;
3029                 }
3030
3031                 public void SetSocketOption (SocketOptionLevel level, SocketOptionName name, byte[] opt_value)
3032                 {
3033                         if (disposed && closed)
3034                                 throw new ObjectDisposedException (GetType ().ToString ());
3035
3036                         // I'd throw an ArgumentNullException, but this is what MS does.
3037                         if (opt_value == null)
3038                                 throw new SocketException ((int) SocketError.Fault,
3039                                         "Error trying to dereference an invalid pointer");
3040                         
3041                         int error;
3042                         
3043                         SetSocketOption_internal(socket, level, name, null,
3044                                                  opt_value, 0, out error);
3045
3046                         if (error != 0) {
3047                                 if (error == 10022) // WSAEINVAL
3048                                         throw new ArgumentException ();
3049                                 throw new SocketException (error);
3050                         }
3051                 }
3052
3053                 public void SetSocketOption (SocketOptionLevel level, SocketOptionName name, object opt_value)
3054                 {
3055
3056                         if (disposed && closed)
3057                                 throw new ObjectDisposedException (GetType ().ToString ());
3058
3059                         if (opt_value == null)
3060                                 throw new ArgumentNullException("optionValue");
3061                         
3062                         int error;
3063
3064                         if (level == SocketOptionLevel.Socket && name == SocketOptionName.Linger) {
3065                                 LingerOption linger = opt_value as LingerOption;
3066                                 if (linger == null)
3067 #if NET_2_0
3068                                         throw new ArgumentException ("A 'LingerOption' value must be specified.", "optionValue");
3069 #else
3070                                         throw new ArgumentException ("optionValue");
3071 #endif
3072                                 SetSocketOption_internal (socket, level, name, linger, null, 0, out error);
3073                         } else if (level == SocketOptionLevel.IP && (name == SocketOptionName.AddMembership || name == SocketOptionName.DropMembership)) {
3074                                 MulticastOption multicast = opt_value as MulticastOption;
3075                                 if (multicast == null)
3076 #if NET_2_0
3077                                         throw new ArgumentException ("A 'MulticastOption' value must be specified.", "optionValue");
3078 #else
3079                                         throw new ArgumentException ("optionValue");
3080 #endif
3081                                 SetSocketOption_internal (socket, level, name, multicast, null, 0, out error);
3082                         } else if (level == SocketOptionLevel.IPv6 && (name == SocketOptionName.AddMembership || name == SocketOptionName.DropMembership)) {
3083                                 IPv6MulticastOption multicast = opt_value as IPv6MulticastOption;
3084                                 if (multicast == null)
3085 #if NET_2_0
3086                                         throw new ArgumentException ("A 'IPv6MulticastOption' value must be specified.", "optionValue");
3087 #else
3088                                         throw new ArgumentException ("optionValue");
3089 #endif
3090                                 SetSocketOption_internal (socket, level, name, multicast, null, 0, out error);
3091                         } else {
3092 #if NET_2_0
3093                                 throw new ArgumentException ("Invalid value specified.", "optionValue");
3094 #else
3095                                 throw new ArgumentException ("optionValue");
3096 #endif
3097                         }
3098
3099                         if (error != 0)
3100                                 if (error == 10022) // WSAEINVAL
3101                                         throw new ArgumentException ();
3102                                 throw new SocketException (error);
3103                         }
3104                 }
3105
3106 #if NET_2_0
3107                 public void SetSocketOption (SocketOptionLevel level, SocketOptionName name, bool optionValue)
3108                 {
3109                         if (disposed && closed)
3110                                 throw new ObjectDisposedException (GetType ().ToString ());
3111
3112                         int error;
3113                         int int_val = (optionValue) ? 1 : 0;
3114                         SetSocketOption_internal (socket, level, name, null, null, int_val, out error);
3115                         if (error != 0) {
3116                                 if (error == 10022) // WSAEINVAL
3117                                         throw new ArgumentException ();
3118                                 throw new SocketException (error);
3119                         }
3120                 }
3121 #endif
3122
3123 #if ONLY_1_1
3124                 public override int GetHashCode ()
3125                 {
3126                         // LAMESPEC:
3127                         // The socket is not suitable to serve as a hash code,
3128                         // because it will change during its lifetime, but
3129                         // this is how MS.NET 1.1 implemented this method.
3130                         return (int) socket; 
3131                 }
3132 #endif
3133         }
3134 }