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