New test.
[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 //
8 // Copyright (C) 2001, 2002 Phillip Pearson and Ximian, Inc.
9 //    http://www.myelin.co.nz
10 // (c) 2004 Novell, Inc. (http://www.novell.com)
11 //
12
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 // 
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 // 
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 //
33
34 using System;
35 using System.Net;
36 using System.Collections;
37 using System.Runtime.CompilerServices;
38 using System.Runtime.InteropServices;
39 using System.Threading;
40 using System.Reflection;
41 using System.IO;
42 using System.Net.Configuration;
43
44 namespace System.Net.Sockets 
45 {
46         public class Socket : IDisposable 
47         {
48                 enum SocketOperation {
49                         Accept,
50                         Connect,
51                         Receive,
52                         ReceiveFrom,
53                         Send,
54                         SendTo,
55                         UsedInManaged1,
56                         UsedInManaged2,
57                         UsedInProcess,
58                         UsedInConsole2
59                 }
60
61                 [StructLayout (LayoutKind.Sequential)]
62                 private sealed class SocketAsyncResult: IAsyncResult 
63                 {
64                         /* Same structure in the runtime */
65                         public Socket Sock;
66                         public IntPtr handle;
67                         object state;
68                         AsyncCallback callback;
69                         WaitHandle waithandle;
70
71                         Exception delayedException;
72
73                         public EndPoint EndPoint;       // Connect,ReceiveFrom,SendTo
74                         public byte [] Buffer;          // Receive,ReceiveFrom,Send,SendTo
75                         public int Offset;              // Receive,ReceiveFrom,Send,SendTo
76                         public int Size;                // Receive,ReceiveFrom,Send,SendTo
77                         public SocketFlags SockFlags;   // Receive,ReceiveFrom,Send,SendTo
78
79                         // Return values
80                         Socket acc_socket;
81                         int total;
82
83                         bool completed_sync;
84                         bool completed;
85                         public bool blocking;
86                         internal int error;
87                         SocketOperation operation;
88                         public object ares;
89
90                         public SocketAsyncResult (Socket sock, object state, AsyncCallback callback, SocketOperation operation)
91                         {
92                                 this.Sock = sock;
93                                 this.blocking = sock.blocking;
94                                 this.handle = sock.socket;
95                                 this.state = state;
96                                 this.callback = callback;
97                                 this.operation = operation;
98                                 SockFlags = SocketFlags.None;
99                         }
100
101                         public void CheckIfThrowDelayedException ()
102                         {
103                                 if (delayedException != null)
104                                         throw delayedException;
105
106                                 if (error != 0) {
107                                         throw new SocketException (error);
108                                 }
109                         }
110
111                         void CompleteAllOnDispose (Queue queue)
112                         {
113                                 object [] pending = queue.ToArray ();
114                                 queue.Clear ();
115
116                                 WaitCallback cb;
117                                 for (int i = 0; i < pending.Length; i++) {
118                                         SocketAsyncResult ares = (SocketAsyncResult) pending [i];
119                                         cb = new WaitCallback (ares.CompleteDisposed);
120                                         ThreadPool.QueueUserWorkItem (cb, null);
121                                 }
122                         }
123
124                         void CompleteDisposed (object unused)
125                         {
126                                 Complete ();
127                         }
128
129                         public void Complete ()
130                         {
131                                 if (operation != SocketOperation.Receive && Sock.disposed)
132                                         delayedException = new ObjectDisposedException (Sock.GetType ().ToString ());
133
134                                 IsCompleted = true;
135
136                                 Queue queue = null;
137                                 if (operation == SocketOperation.Receive || operation == SocketOperation.ReceiveFrom) {
138                                         queue = Sock.readQ;
139                                 } else if (operation == SocketOperation.Send || operation == SocketOperation.SendTo) {
140                                         queue = Sock.writeQ;
141                                 }
142
143                                 if (queue != null) {
144                                         SocketAsyncCall sac = null;
145                                         SocketAsyncResult req = null;
146                                         lock (queue) {
147                                                 queue.Dequeue (); // remove ourselves
148                                                 if (queue.Count > 0) {
149                                                         req = (SocketAsyncResult) queue.Peek ();
150                                                         if (!Sock.disposed) {
151                                                                 Worker worker = new Worker (req);
152                                                                 sac = GetDelegate (worker, req.operation);
153                                                         } else {
154                                                                 CompleteAllOnDispose (queue);
155                                                         }
156                                                 }
157                                         }
158
159                                         if (sac != null)
160                                                 sac.BeginInvoke (null, req);
161                                 }
162
163                                 if (callback != null)
164                                         callback (this);
165                         }
166
167                         SocketAsyncCall GetDelegate (Worker worker, SocketOperation op)
168                         {
169                                 switch (op) {
170                                 case SocketOperation.Receive:
171                                         return new SocketAsyncCall (worker.Receive);
172                                 case SocketOperation.ReceiveFrom:
173                                         return new SocketAsyncCall (worker.ReceiveFrom);
174                                 case SocketOperation.Send:
175                                         return new SocketAsyncCall (worker.Send);
176                                 case SocketOperation.SendTo:
177                                         return new SocketAsyncCall (worker.SendTo);
178                                 default:
179                                         return null; // never happens
180                                 }
181                         }
182
183                         public void Complete (bool synch)
184                         {
185                                 completed_sync = synch;
186                                 Complete ();
187                         }
188
189                         public void Complete (int total)
190                         {
191                                 this.total = total;
192                                 Complete ();
193                         }
194
195                         public void Complete (Exception e, bool synch)
196                         {
197                                 completed_sync = synch;
198                                 delayedException = e;
199                                 Complete ();
200                         }
201
202                         public void Complete (Exception e)
203                         {
204                                 delayedException = e;
205                                 Complete ();
206                         }
207
208                         public void Complete (Socket s)
209                         {
210                                 acc_socket = s;
211                                 Complete ();
212                         }
213
214                         public object AsyncState {
215                                 get {
216                                         return state;
217                                 }
218                         }
219
220                         public WaitHandle AsyncWaitHandle {
221                                 get {
222                                         lock (this) {
223                                                 if (waithandle == null)
224                                                         waithandle = new ManualResetEvent (completed);
225                                         }
226
227                                         return waithandle;
228                                 }
229                                 set {
230                                         waithandle=value;
231                                 }
232                         }
233
234                         public bool CompletedSynchronously {
235                                 get {
236                                         return(completed_sync);
237                                 }
238                         }
239
240                         public bool IsCompleted {
241                                 get {
242                                         return(completed);
243                                 }
244                                 set {
245                                         completed=value;
246                                         lock (this) {
247                                                 if (waithandle != null && value) {
248                                                         ((ManualResetEvent) waithandle).Set ();
249                                                 }
250                                         }
251                                 }
252                         }
253                         
254                         public Socket Socket {
255                                 get {
256                                         return acc_socket;
257                                 }
258                         }
259
260                         public int Total {
261                                 get { return total; }
262                                 set { total = value; }
263                         }
264                 }
265
266                 private sealed class Worker 
267                 {
268                         SocketAsyncResult result;
269
270                         public Worker (SocketAsyncResult ares)
271                         {
272                                 this.result = ares;
273                         }
274
275                         public void Accept ()
276                         {
277                                 Socket acc_socket = null;
278                                 try {
279                                         acc_socket = result.Sock.Accept ();
280                                 } catch (Exception e) {
281                                         result.Complete (e);
282                                         return;
283                                 }
284
285                                 result.Complete (acc_socket);
286                         }
287
288                         public void Connect ()
289                         {
290                                 try {
291                                         if (!result.Sock.Blocking) {
292                                                 result.Sock.Poll (-1, SelectMode.SelectWrite);
293                                                 int success = (int)result.Sock.GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
294                                                 if (success == 0) {
295                                                         result.Sock.connected = true;
296                                                 } else {
297                                                         result.Complete (new SocketException (success));
298                                                         return;
299                                                 }
300                                         } else {
301                                                 result.Sock.Connect (result.EndPoint);
302                                                 result.Sock.connected = true;
303                                         }
304                                 } catch (Exception e) {
305                                         result.Complete (e);
306                                         return;
307                                 }
308
309                                 result.Complete ();
310                         }
311
312                         public void Receive ()
313                         {
314                                 // Actual recv() done in the runtime
315                                 result.Complete ();
316                         }
317
318                         public void ReceiveFrom ()
319                         {
320                                 int total = 0;
321                                 try {
322                                         total = result.Sock.ReceiveFrom_nochecks (result.Buffer,
323                                                                          result.Offset,
324                                                                          result.Size,
325                                                                          result.SockFlags,
326                                                                          ref result.EndPoint);
327                                 } catch (Exception e) {
328                                         result.Complete (e);
329                                         return;
330                                 }
331
332                                 result.Complete (total);
333                         }
334
335                         int send_so_far;
336
337                         void UpdateSendValues (int last_sent)
338                         {
339                                 if (result.error == 0) {
340                                         send_so_far += last_sent;
341                                         result.Offset += last_sent;
342                                         result.Size -= last_sent;
343                                 }
344                         }
345
346                         public void Send ()
347                         {
348                                 // Actual send() done in the runtime
349                                 if (result.error == 0) {
350                                         UpdateSendValues (result.Total);
351                                         if (result.Sock.disposed) {
352                                                 result.Complete ();
353                                                 return;
354                                         }
355
356                                         if (result.Size > 0) {
357                                                 SocketAsyncCall sac = new SocketAsyncCall (this.Send);
358                                                 sac.BeginInvoke (null, result);
359                                                 return; // Have to finish writing everything. See bug #74475.
360                                         }
361                                         result.Total = send_so_far;
362                                 }
363                                 result.Complete ();
364                         }
365
366                         public void SendTo ()
367                         {
368                                 int total = 0;
369                                 try {
370                                         total = result.Sock.SendTo_nochecks (result.Buffer,
371                                                                     result.Offset,
372                                                                     result.Size,
373                                                                     result.SockFlags,
374                                                                     result.EndPoint);
375
376                                         UpdateSendValues (total);
377                                         if (result.Size > 0) {
378                                                 SocketAsyncCall sac = new SocketAsyncCall (this.SendTo);
379                                                 sac.BeginInvoke (null, result);
380                                                 return; // Have to finish writing everything. See bug #74475.
381                                         }
382                                         result.Total = send_so_far;
383                                 } catch (Exception e) {
384                                         result.Complete (e);
385                                         return;
386                                 }
387
388                                 result.Complete ();
389                         }
390                 }
391                         
392                 /* the field "socket" is looked up by name by the runtime */
393                 private IntPtr socket;
394                 private AddressFamily address_family;
395                 private SocketType socket_type;
396                 private ProtocolType protocol_type;
397                 internal bool blocking=true;
398                 private Queue readQ = new Queue (2);
399                 private Queue writeQ = new Queue (2);
400
401                 delegate void SocketAsyncCall ();
402                 /*
403                  *      These two fields are looked up by name by the runtime, don't change
404                  *  their name without also updating the runtime code.
405                  */
406                 private static int ipv4Supported = -1, ipv6Supported = -1;
407
408                 /* When true, the socket was connected at the time of
409                  * the last IO operation
410                  */
411                 private bool connected=false;
412                 /* true if we called Close_internal */
413                 private bool closed;
414                 internal bool disposed;
415                 
416
417                 /* Used in LocalEndPoint and RemoteEndPoint if the
418                  * Mono.Posix assembly is available
419                  */
420                 private static object unixendpoint=null;
421                 private static Type unixendpointtype=null;
422                 
423
424                 static void AddSockets (ArrayList sockets, IList list, string name)
425                 {
426                         if (list != null) {
427                                 foreach (Socket sock in list) {
428                                         if (sock == null) // MS throws a NullRef
429                                                 throw new ArgumentNullException (name, "Contains a null element");
430                                         sockets.Add (sock);
431                                 }
432                         }
433
434                         sockets.Add (null);
435                 }
436 #if !TARGET_JVM
437                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
438                 private extern static void Select_internal (ref Socket [] sockets,
439                                                         int microSeconds,
440                                                         out int error);
441 #endif
442                 public static void Select (IList checkRead, IList checkWrite, IList checkError, int microSeconds)
443                 {
444                         ArrayList list = new ArrayList ();
445                         AddSockets (list, checkRead, "checkRead");
446                         AddSockets (list, checkWrite, "checkWrite");
447                         AddSockets (list, checkError, "checkError");
448
449                         if (list.Count == 3) {
450                                 throw new ArgumentNullException ("checkRead, checkWrite, checkError",
451                                                                  "All the lists are null or empty.");
452                         }
453
454                         int error;
455                         /*
456                          * The 'sockets' array contains: READ socket 0-n, null,
457                          *                               WRITE socket 0-n, null,
458                          *                               ERROR socket 0-n, null
459                          */
460                         Socket [] sockets = (Socket []) list.ToArray (typeof (Socket));
461                         Select_internal (ref sockets, microSeconds, out error);
462
463                         if (error != 0)
464                                 throw new SocketException (error);
465
466                         if (checkRead != null)
467                                 checkRead.Clear ();
468
469                         if (checkWrite != null)
470                                 checkWrite.Clear ();
471
472                         if (checkError != null)
473                                 checkError.Clear ();
474
475                         if (sockets == null)
476                                 return;
477
478                         int mode = 0;
479                         int count = sockets.Length;
480                         IList currentList = checkRead;
481                         for (int i = 0; i < count; i++) {
482                                 Socket sock = sockets [i];
483                                 if (sock == null) { // separator
484                                         currentList = (mode == 0) ? checkWrite : checkError;
485                                         mode++;
486                                         continue;
487                                 }
488
489                                 if (currentList != null) {
490                                         sock.connected = true;
491                                         currentList.Add (sock);
492                                 }
493                         }
494                 }
495
496                 static Socket() {
497                         Assembly ass;
498                         
499                         try {
500                                 ass = Assembly.Load (Consts.AssemblyMono_Posix);
501                         } catch (FileNotFoundException) {
502                                 return;
503                         }
504                                 
505                         unixendpointtype=ass.GetType("Mono.Posix.UnixEndPoint");
506
507                         /* The endpoint Create() method is an instance
508                          * method :-(
509                          */
510                         Type[] arg_types=new Type[1];
511                         arg_types[0]=typeof(string);
512                         ConstructorInfo cons=unixendpointtype.GetConstructor(arg_types);
513
514                         object[] args=new object[1];
515                         args[0]="nothing";
516
517                         unixendpoint=cons.Invoke(args);
518                 }
519
520                 // private constructor used by Accept, which already
521                 // has a socket handle to use
522                 private Socket(AddressFamily family, SocketType type,
523                                ProtocolType proto, IntPtr sock) {
524                         address_family=family;
525                         socket_type=type;
526                         protocol_type=proto;
527                         
528                         socket=sock;
529                         connected=true;
530                 }
531 #if !TARGET_JVM
532                 // Creates a new system socket, returning the handle
533                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
534                 private extern IntPtr Socket_internal(AddressFamily family,
535                                                       SocketType type,
536                                                       ProtocolType proto,
537                                                       out int error);
538 #endif          
539                 public Socket(AddressFamily family, SocketType type,
540                               ProtocolType proto) {
541                         address_family=family;
542                         socket_type=type;
543                         protocol_type=proto;
544                         
545                         int error;
546                         
547                         socket=Socket_internal(family, type, proto, out error);
548                         if (error != 0) {
549                                 throw new SocketException (error);
550                         }
551                 }
552
553                 public AddressFamily AddressFamily {
554                         get {
555                                 return(address_family);
556                         }
557                 }
558 #if !TARGET_JVM
559                 // Returns the amount of data waiting to be read on socket
560                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
561                 private extern static int Available_internal(IntPtr socket,
562                                                              out int error);
563 #endif
564                 
565                 public int Available {
566                         get {
567                                 if (disposed && closed)
568                                         throw new ObjectDisposedException (GetType ().ToString ());
569
570                                 int ret, error;
571                                 
572                                 ret = Available_internal(socket, out error);
573
574                                 if (error != 0) {
575                                         throw new SocketException (error);
576                                 }
577
578                                 return(ret);
579                         }
580                 }
581 #if !TARGET_JVM
582                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
583                 private extern static void Blocking_internal(IntPtr socket,
584                                                              bool block,
585                                                              out int error);
586 #endif
587                 public bool Blocking {
588                         get {
589                                 return(blocking);
590                         }
591                         set {
592                                 if (disposed && closed)
593                                         throw new ObjectDisposedException (GetType ().ToString ());
594
595                                 int error;
596                                 
597                                 Blocking_internal(socket, value, out error);
598
599                                 if (error != 0) {
600                                         throw new SocketException (error);
601                                 }
602                                 
603                                 blocking=value;
604                         }
605                 }
606
607                 public bool Connected {
608                         get {
609                                 return(connected);
610                         }
611                 }
612
613                 public IntPtr Handle {
614                         get {
615                                 return(socket);
616                         }
617                 }
618 #if !TARGET_JVM
619                 // Returns the local endpoint details in addr and port
620                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
621                 private extern static SocketAddress LocalEndPoint_internal(IntPtr socket, out int error);
622 #endif
623                 [MonoTODO("Support non-IP endpoints")]
624                 public EndPoint LocalEndPoint {
625                         get {
626                                 if (disposed && closed)
627                                         throw new ObjectDisposedException (GetType ().ToString ());
628
629                                 SocketAddress sa;
630                                 int error;
631                                 
632                                 sa=LocalEndPoint_internal(socket, out error);
633
634                                 if (error != 0) {
635                                         throw new SocketException (error);
636                                 }
637
638                                 if(sa.Family==AddressFamily.InterNetwork || sa.Family==AddressFamily.InterNetworkV6) {
639                                         // Stupidly, EndPoint.Create() is an
640                                         // instance method
641                                         return new IPEndPoint(0, 0).Create(sa);
642                                 } else if (sa.Family==AddressFamily.Unix &&
643                                            unixendpoint!=null) {
644                                         return((EndPoint)unixendpointtype.InvokeMember("Create", BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public, null, unixendpoint, new object[] {sa}));
645                                 } else {
646                                         throw new NotImplementedException();
647                                 }
648                         }
649                 }
650
651                 public ProtocolType ProtocolType {
652                         get {
653                                 return(protocol_type);
654                         }
655                 }
656
657                 // Returns the remote endpoint details in addr and port
658                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
659                 private extern static SocketAddress RemoteEndPoint_internal(IntPtr socket, out int error);
660
661                 [MonoTODO("Support non-IP endpoints")]
662                 public EndPoint RemoteEndPoint {
663                         get {
664                                 if (disposed && closed)
665                                         throw new ObjectDisposedException (GetType ().ToString ());
666
667                                 SocketAddress sa;
668                                 int error;
669                                 
670                                 sa=RemoteEndPoint_internal(socket, out error);
671
672                                 if (error != 0) {
673                                         throw new SocketException (error);
674                                 }
675
676                                 if(sa.Family==AddressFamily.InterNetwork || sa.Family==AddressFamily.InterNetworkV6 ) {
677                                         // Stupidly, EndPoint.Create() is an
678                                         // instance method
679                                         return new IPEndPoint(0, 0).Create(sa);
680                                 } else if (sa.Family==AddressFamily.Unix &&
681                                            unixendpoint!=null) {
682                                         return((EndPoint)unixendpointtype.InvokeMember("Create", BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.Public, null, unixendpoint, new object[] {sa}));
683                                 } else {
684                                         throw new NotImplementedException();
685                                 }
686                         }
687                 }
688
689                 public SocketType SocketType {
690                         get {
691                                 return(socket_type);
692                         }
693                 }
694
695                 public static bool SupportsIPv4 {
696                         get {
697                                 CheckProtocolSupport();
698                                 return ipv4Supported == 1;
699                         }
700                 }
701
702                 public static bool SupportsIPv6 {
703                         get {
704                                 CheckProtocolSupport();
705                                 return ipv6Supported == 1;
706                         }
707                 }
708
709 #if NET_2_0
710                 public int SendTimeout {
711                         get {
712                                 return (int)GetSocketOption(
713                                         SocketOptionLevel.Socket,
714                                         SocketOptionName.SendTimeout);
715                         }
716                         set {
717                                 SetSocketOption(
718                                         SocketOptionLevel.Socket,
719                                         SocketOptionName.SendTimeout, value);
720                         }
721                 }
722
723                 public int ReceiveTimeout {
724                         get {
725                                 return (int)GetSocketOption(
726                                         SocketOptionLevel.Socket,
727                                         SocketOptionName.ReceiveTimeout);
728                         }
729                         set {
730                                 SetSocketOption(
731                                         SocketOptionLevel.Socket,
732                                         SocketOptionName.ReceiveTimeout, value);
733                         }
734                 }
735
736                 public bool NoDelay {
737                         get {
738                                 return (int)(GetSocketOption (
739                                         SocketOptionLevel.Tcp,
740                                         SocketOptionName.NoDelay)) != 0;
741                         }
742
743                         set {
744                                 SetSocketOption (
745                                         SocketOptionLevel.Tcp,
746                                         SocketOptionName.NoDelay, value ? 1 : 0);
747                         }
748                 }
749 #endif
750
751                 internal static void CheckProtocolSupport()
752                 {
753                         if(ipv4Supported == -1) {
754                                 try  {
755                                         Socket tmp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
756                                         tmp.Close();
757
758                                         ipv4Supported = 1;
759                                 }
760                                 catch {
761                                         ipv4Supported = 0;
762                                 }
763                         }
764
765                         if(ipv6Supported == -1) {
766 #if NET_2_0 && CONFIGURATION_DEP
767                                 SettingsSection config;
768                                 config = (SettingsSection) System.Configuration.ConfigurationManager.GetSection ("system.net/settings");
769                                 if (config != null)
770                                         ipv6Supported = config.Ipv6.Enabled ? -1 : 0;
771 #else
772                                 NetConfig config = (NetConfig)System.Configuration.ConfigurationSettings.GetConfig("system.net/settings");
773
774                                 if(config != null)
775                                         ipv6Supported = config.ipv6Enabled?-1:0;
776 #endif
777                                 if(ipv6Supported != 0) {
778                                         try {
779                                                 Socket tmp = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
780                                                 tmp.Close();
781
782                                                 ipv6Supported = 1;
783                                         }
784                                         catch { }
785                                 }
786                         }
787                 }
788
789                 // Creates a new system socket, returning the handle
790                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
791                 private extern static IntPtr Accept_internal(IntPtr sock,
792                                                              out int error);
793
794                 Thread blocking_thread;
795                 public Socket Accept() {
796                         if (disposed && closed)
797                                 throw new ObjectDisposedException (GetType ().ToString ());
798
799                         int error = 0;
800                         IntPtr sock = (IntPtr) (-1);
801                         blocking_thread = Thread.CurrentThread;
802                         try {
803                                 sock = Accept_internal(socket, out error);
804                         } catch (ThreadAbortException) {
805                                 if (disposed) {
806                                         Thread.ResetAbort ();
807                                         error = (int) SocketError.Interrupted;
808                                 }
809                         } finally {
810                                 blocking_thread = null;
811                         }
812
813                         if (error != 0) {
814                                 throw new SocketException (error);
815                         }
816                         
817                         Socket accepted = new Socket(this.AddressFamily,
818                                                      this.SocketType,
819                                                      this.ProtocolType, sock);
820
821                         accepted.Blocking = this.Blocking;
822                         return(accepted);
823                 }
824
825                 public IAsyncResult BeginAccept(AsyncCallback callback,
826                                                 object state) {
827
828                         if (disposed && closed)
829                                 throw new ObjectDisposedException (GetType ().ToString ());
830
831                         SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Accept);
832                         Worker worker = new Worker (req);
833                         SocketAsyncCall sac = new SocketAsyncCall (worker.Accept);
834                         sac.BeginInvoke (null, req);
835                         return(req);
836                 }
837
838                 public IAsyncResult BeginConnect(EndPoint end_point,
839                                                  AsyncCallback callback,
840                                                  object state) {
841
842                         if (disposed && closed)
843                                 throw new ObjectDisposedException (GetType ().ToString ());
844
845                         if (end_point == null)
846                                 throw new ArgumentNullException ("end_point");
847
848                         SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Connect);
849                         req.EndPoint = end_point;
850
851                         // Bug #75154: Connect() should not succeed for .Any addresses.
852                         if (end_point is IPEndPoint) {
853                                 IPEndPoint ep = (IPEndPoint) end_point;
854                                 if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)) {
855                                         req.Complete (new SocketException ((int) SocketError.AddressNotAvailable), true);
856                                         return req;
857                                 }
858                         }
859
860                         int error = 0;
861                         if (!blocking) {
862                                 SocketAddress serial = end_point.Serialize ();
863                                 Connect_internal (socket, serial, out error);
864                                 if (error == 0) {
865                                         // succeeded synch
866                                         connected = true;
867                                         req.Complete (true);
868                                 } else if (error != (int) SocketError.InProgress && error != (int) SocketError.WouldBlock) {
869                                         // error synch
870                                         connected = false;
871                                         req.Complete (new SocketException (error), true);
872                                 }
873                         }
874
875                         if (blocking || error == (int) SocketError.InProgress || error == (int) SocketError.WouldBlock) {
876                                 // continue asynch
877                                 connected = false;
878                                 Worker worker = new Worker (req);
879                                 SocketAsyncCall sac = new SocketAsyncCall (worker.Connect);
880                                 sac.BeginInvoke (null, req);
881                         }
882
883                         return(req);
884                 }
885
886                 public IAsyncResult BeginReceive(byte[] buffer, int offset,
887                                                  int size,
888                                                  SocketFlags socket_flags,
889                                                  AsyncCallback callback,
890                                                  object state) {
891
892                         if (disposed && closed)
893                                 throw new ObjectDisposedException (GetType ().ToString ());
894
895                         if (buffer == null)
896                                 throw new ArgumentNullException ("buffer");
897
898                         if (offset < 0 || offset > buffer.Length)
899                                 throw new ArgumentOutOfRangeException ("offset");
900
901                         if (size < 0 || offset + size > buffer.Length)
902                                 throw new ArgumentOutOfRangeException ("size");
903
904                         SocketAsyncResult req;
905                         lock (readQ) {
906                                 req = new SocketAsyncResult (this, state, callback, SocketOperation.Receive);
907                                 req.Buffer = buffer;
908                                 req.Offset = offset;
909                                 req.Size = size;
910                                 req.SockFlags = socket_flags;
911                                 readQ.Enqueue (req);
912                                 if (readQ.Count == 1) {
913                                         Worker worker = new Worker (req);
914                                         SocketAsyncCall sac = new SocketAsyncCall (worker.Receive);
915                                         sac.BeginInvoke (null, req);
916                                 }
917                         }
918
919                         return req;
920                 }
921
922                 public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset,
923                                                      int size,
924                                                      SocketFlags socket_flags,
925                                                      ref EndPoint remote_end,
926                                                      AsyncCallback callback,
927                                                      object state) {
928                         if (disposed && closed)
929                                 throw new ObjectDisposedException (GetType ().ToString ());
930
931                         if (buffer == null)
932                                 throw new ArgumentNullException ("buffer");
933
934                         if (offset < 0)
935                                 throw new ArgumentOutOfRangeException ("offset must be >= 0");
936
937                         if (size < 0)
938                                 throw new ArgumentOutOfRangeException ("size must be >= 0");
939
940                         if (offset + size > buffer.Length)
941                                 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
942
943                         SocketAsyncResult req;
944                         lock (readQ) {
945                                 req = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveFrom);
946                                 req.Buffer = buffer;
947                                 req.Offset = offset;
948                                 req.Size = size;
949                                 req.SockFlags = socket_flags;
950                                 req.EndPoint = remote_end;
951                                 readQ.Enqueue (req);
952                                 if (readQ.Count == 1) {
953                                         Worker worker = new Worker (req);
954                                         SocketAsyncCall sac = new SocketAsyncCall (worker.ReceiveFrom);
955                                         sac.BeginInvoke (null, req);
956                                 }
957                         }
958                         return req;
959                 }
960
961                 public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socket_flags,
962                                                AsyncCallback callback, object state)
963                 {
964                         if (disposed && closed)
965                                 throw new ObjectDisposedException (GetType ().ToString ());
966
967                         if (buffer == null)
968                                 throw new ArgumentNullException ("buffer");
969
970                         if (offset < 0)
971                                 throw new ArgumentOutOfRangeException ("offset must be >= 0");
972
973                         if (size < 0)
974                                 throw new ArgumentOutOfRangeException ("size must be >= 0");
975
976                         if (offset + size > buffer.Length)
977                                 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
978
979                         SocketAsyncResult req;
980                         lock (writeQ) {
981                                 req = new SocketAsyncResult (this, state, callback, SocketOperation.Send);
982                                 req.Buffer = buffer;
983                                 req.Offset = offset;
984                                 req.Size = size;
985                                 req.SockFlags = socket_flags;
986                                 writeQ.Enqueue (req);
987                                 if (writeQ.Count == 1) {
988                                         Worker worker = new Worker (req);
989                                         SocketAsyncCall sac = new SocketAsyncCall (worker.Send);
990                                         sac.BeginInvoke (null, req);
991                                 }
992                         }
993                         return req;
994                 }
995
996                 public IAsyncResult BeginSendTo(byte[] buffer, int offset,
997                                                 int size,
998                                                 SocketFlags socket_flags,
999                                                 EndPoint remote_end,
1000                                                 AsyncCallback callback,
1001                                                 object state) {
1002                         if (disposed && closed)
1003                                 throw new ObjectDisposedException (GetType ().ToString ());
1004
1005                         if (buffer == null)
1006                                 throw new ArgumentNullException ("buffer");
1007
1008                         if (offset < 0)
1009                                 throw new ArgumentOutOfRangeException ("offset must be >= 0");
1010
1011                         if (size < 0)
1012                                 throw new ArgumentOutOfRangeException ("size must be >= 0");
1013
1014                         if (offset + size > buffer.Length)
1015                                 throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
1016
1017                         SocketAsyncResult req;
1018                         lock (writeQ) {
1019                                 req = new SocketAsyncResult (this, state, callback, SocketOperation.SendTo);
1020                                 req.Buffer = buffer;
1021                                 req.Offset = offset;
1022                                 req.Size = size;
1023                                 req.SockFlags = socket_flags;
1024                                 req.EndPoint = remote_end;
1025                                 writeQ.Enqueue (req);
1026                                 if (writeQ.Count == 1) {
1027                                         Worker worker = new Worker (req);
1028                                         SocketAsyncCall sac = new SocketAsyncCall (worker.SendTo);
1029                                         sac.BeginInvoke (null, req);
1030                                 }
1031                         }
1032                         return req;
1033                 }
1034
1035                 // Creates a new system socket, returning the handle
1036                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1037                 private extern static void Bind_internal(IntPtr sock,
1038                                                          SocketAddress sa,
1039                                                          out int error);
1040
1041                 public void Bind(EndPoint local_end) {
1042                         if (disposed && closed)
1043                                 throw new ObjectDisposedException (GetType ().ToString ());
1044
1045                         if(local_end==null) {
1046                                 throw new ArgumentNullException("local_end");
1047                         }
1048                         
1049                         int error;
1050                         
1051                         Bind_internal(socket, local_end.Serialize(),
1052                                       out error);
1053
1054                         if (error != 0) {
1055                                 throw new SocketException (error);
1056                         }
1057                 }
1058
1059                 // Closes the socket
1060                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1061                 private extern static void Close_internal(IntPtr socket,
1062                                                           out int error);
1063                 
1064                 public void Close() {
1065                         ((IDisposable) this).Dispose ();
1066                 }
1067
1068                 // Connects to the remote address
1069                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1070                 private extern static void Connect_internal(IntPtr sock,
1071                                                             SocketAddress sa,
1072                                                             out int error);
1073
1074                 public void Connect(EndPoint remote_end) {
1075                         if (disposed && closed)
1076                                 throw new ObjectDisposedException (GetType ().ToString ());
1077
1078                         if(remote_end==null) {
1079                                 throw new ArgumentNullException("remote_end");
1080                         }
1081
1082                         if (remote_end is IPEndPoint) {
1083                                 IPEndPoint ep = (IPEndPoint) remote_end;
1084                                 if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any))
1085                                         throw new SocketException ((int) SocketError.AddressNotAvailable);
1086                         }
1087
1088                         SocketAddress serial = remote_end.Serialize ();
1089                         int error = 0;
1090
1091                         blocking_thread = Thread.CurrentThread;
1092                         try {
1093                                 Connect_internal (socket, serial, out error);
1094                         } catch (ThreadAbortException) {
1095                                 if (disposed) {
1096                                         Thread.ResetAbort ();
1097                                         error = (int) SocketError.Interrupted;
1098                                 }
1099                         } finally {
1100                                 blocking_thread = null;
1101                         }
1102
1103                         if (error != 0) {
1104                                 throw new SocketException (error);
1105                         }
1106                         
1107                         connected=true;
1108                 }
1109                 
1110                 public Socket EndAccept(IAsyncResult result) {
1111                         if (disposed && closed)
1112                                 throw new ObjectDisposedException (GetType ().ToString ());
1113
1114                         if (result == null)
1115                                 throw new ArgumentNullException ("result");
1116
1117                         SocketAsyncResult req = result as SocketAsyncResult;
1118                         if (req == null)
1119                                 throw new ArgumentException ("Invalid IAsyncResult", "result");
1120
1121                         if (!result.IsCompleted)
1122                                 result.AsyncWaitHandle.WaitOne();
1123
1124                         req.CheckIfThrowDelayedException();
1125                         return req.Socket;
1126                 }
1127
1128                 public void EndConnect(IAsyncResult result) {
1129                         if (disposed && closed)
1130                                 throw new ObjectDisposedException (GetType ().ToString ());
1131
1132                         if (result == null)
1133                                 throw new ArgumentNullException ("result");
1134
1135                         SocketAsyncResult req = result as SocketAsyncResult;
1136                         if (req == null)
1137                                 throw new ArgumentException ("Invalid IAsyncResult", "result");
1138
1139                         if (!result.IsCompleted)
1140                                 result.AsyncWaitHandle.WaitOne();
1141
1142                         req.CheckIfThrowDelayedException();
1143                 }
1144
1145                 public int EndReceive(IAsyncResult result) {
1146                         if (disposed && closed)
1147                                 throw new ObjectDisposedException (GetType ().ToString ());
1148
1149                         if (result == null)
1150                                 throw new ArgumentNullException ("result");
1151
1152                         SocketAsyncResult req = result as SocketAsyncResult;
1153                         if (req == null)
1154                                 throw new ArgumentException ("Invalid IAsyncResult", "result");
1155
1156                         if (!result.IsCompleted)
1157                                 result.AsyncWaitHandle.WaitOne();
1158
1159                         req.CheckIfThrowDelayedException();
1160                         return req.Total;
1161                 }
1162
1163                 public int EndReceiveFrom(IAsyncResult result,
1164                                           ref EndPoint end_point) {
1165                         if (disposed && closed)
1166                                 throw new ObjectDisposedException (GetType ().ToString ());
1167
1168                         if (result == null)
1169                                 throw new ArgumentNullException ("result");
1170
1171                         SocketAsyncResult req = result as SocketAsyncResult;
1172                         if (req == null)
1173                                 throw new ArgumentException ("Invalid IAsyncResult", "result");
1174
1175                         if (!result.IsCompleted)
1176                                 result.AsyncWaitHandle.WaitOne();
1177
1178                         req.CheckIfThrowDelayedException();
1179                         end_point = req.EndPoint;
1180                         return req.Total;
1181                 }
1182
1183                 public int EndSend(IAsyncResult result) {
1184                         if (disposed && closed)
1185                                 throw new ObjectDisposedException (GetType ().ToString ());
1186
1187                         if (result == null)
1188                                 throw new ArgumentNullException ("result");
1189
1190                         SocketAsyncResult req = result as SocketAsyncResult;
1191                         if (req == null)
1192                                 throw new ArgumentException ("Invalid IAsyncResult", "result");
1193
1194                         if (!result.IsCompleted)
1195                                 result.AsyncWaitHandle.WaitOne();
1196
1197                         req.CheckIfThrowDelayedException();
1198                         return req.Total;
1199                 }
1200
1201                 public int EndSendTo(IAsyncResult result) {
1202                         if (disposed && closed)
1203                                 throw new ObjectDisposedException (GetType ().ToString ());
1204
1205                         if (result == null)
1206                                 throw new ArgumentNullException ("result");
1207
1208                         SocketAsyncResult req = result as SocketAsyncResult;
1209                         if (req == null)
1210                                 throw new ArgumentException ("Invalid IAsyncResult", "result");
1211
1212                         if (!result.IsCompleted)
1213                                 result.AsyncWaitHandle.WaitOne();
1214
1215                         req.CheckIfThrowDelayedException();
1216                         return req.Total;
1217                 }
1218
1219                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1220                 private extern static void GetSocketOption_obj_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, out object obj_val, out int error);
1221                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1222                 private extern static void GetSocketOption_arr_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val, out int error);
1223
1224                 public object GetSocketOption (SocketOptionLevel level, SocketOptionName name)
1225                 {
1226                         if (disposed && closed)
1227                                 throw new ObjectDisposedException (GetType ().ToString ());
1228
1229                         object obj_val;
1230                         int error;
1231                         
1232                         GetSocketOption_obj_internal(socket, level, name,
1233                                                      out obj_val, out error);
1234
1235                         if (error != 0) {
1236                                 throw new SocketException (error);
1237                         }
1238                         
1239                         if(name==SocketOptionName.Linger) {
1240                                 return((LingerOption)obj_val);
1241                         } else if (name==SocketOptionName.AddMembership ||
1242                                    name==SocketOptionName.DropMembership) {
1243                                 return((MulticastOption)obj_val);
1244                         } else if (obj_val is int) {
1245                                 return((int)obj_val);
1246                         } else {
1247                                 return(obj_val);
1248                         }
1249                 }
1250
1251                 public void GetSocketOption (SocketOptionLevel level, SocketOptionName name, byte [] opt_value)
1252                 {
1253                         if (disposed && closed)
1254                                 throw new ObjectDisposedException (GetType ().ToString ());
1255
1256                         int error;
1257                         
1258                         GetSocketOption_arr_internal(socket, level, name,
1259                                                      ref opt_value, out error);
1260
1261                         if (error != 0) {
1262                                 throw new SocketException (error);
1263                         }
1264                 }
1265
1266                 public byte [] GetSocketOption (SocketOptionLevel level, SocketOptionName name, int length)
1267                 {
1268                         if (disposed && closed)
1269                                 throw new ObjectDisposedException (GetType ().ToString ());
1270
1271                         byte[] byte_val=new byte[length];
1272                         int error;
1273                         
1274                         GetSocketOption_arr_internal(socket, level, name,
1275                                                      ref byte_val, out error);
1276
1277                         if (error != 0) {
1278                                 throw new SocketException (error);
1279                         }
1280
1281                         return(byte_val);
1282                 }
1283
1284                 // See Socket.IOControl, WSAIoctl documentation in MSDN. The
1285                 // common options between UNIX and Winsock are FIONREAD,
1286                 // FIONBIO and SIOCATMARK. Anything else will depend on the
1287                 // system.
1288                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1289                 extern static int WSAIoctl (IntPtr sock, int ioctl_code,
1290                                             byte [] input, byte [] output,
1291                                             out int error);
1292
1293                 public int IOControl (int ioctl_code, byte [] in_value, byte [] out_value)
1294                 {
1295                         if (disposed)
1296                                 throw new ObjectDisposedException (GetType ().ToString ());
1297
1298                         int error;
1299                         int result = WSAIoctl (socket, ioctl_code, in_value,
1300                                                out_value, out error);
1301
1302                         if (error != 0) {
1303                                 throw new SocketException (error);
1304                         }
1305                         
1306                         if (result == -1)
1307                                 throw new InvalidOperationException ("Must use Blocking property instead.");
1308
1309                         return result;
1310                 }
1311
1312                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1313                 private extern static void Listen_internal(IntPtr sock,
1314                                                            int backlog,
1315                                                            out int error);
1316
1317                 public void Listen (int backlog)
1318                 {
1319                         if (disposed && closed)
1320                                 throw new ObjectDisposedException (GetType ().ToString ());
1321
1322                         int error;
1323                         
1324                         Listen_internal(socket, backlog, out error);
1325
1326                         if (error != 0) {
1327                                 throw new SocketException (error);
1328                         }
1329                 }
1330
1331                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1332                 extern static bool Poll_internal (IntPtr socket, SelectMode mode, int timeout, out int error);
1333
1334                 public bool Poll (int time_us, SelectMode mode)
1335                 {
1336                         if (disposed && closed)
1337                                 throw new ObjectDisposedException (GetType ().ToString ());
1338
1339                         if (mode != SelectMode.SelectRead &&
1340                             mode != SelectMode.SelectWrite &&
1341                             mode != SelectMode.SelectError)
1342                                 throw new NotSupportedException ("'mode' parameter is not valid.");
1343
1344                         int error;
1345                         bool result = Poll_internal (socket, mode, time_us, out error);
1346                         if (error != 0)
1347                                 throw new SocketException (error);
1348
1349                         if (result == true) {
1350                                 /* Update the connected state; for
1351                                  * non-blocking Connect()s this is
1352                                  * when we can find out that the
1353                                  * connect succeeded.
1354                                  */
1355                                 connected = true;
1356                         }
1357                         
1358                         return result;
1359                 }
1360                 
1361                 public int Receive (byte [] buf)
1362                 {
1363                         if (disposed && closed)
1364                                 throw new ObjectDisposedException (GetType ().ToString ());
1365
1366                         if (buf == null)
1367                                 throw new ArgumentNullException ("buf");
1368
1369                         SocketError error;
1370
1371                         int ret = Receive_nochecks (buf, 0, buf.Length, SocketFlags.None, out error);
1372                         
1373                         if (error != SocketError.Success)
1374                                 throw new SocketException ((int) error);
1375
1376                         return ret;
1377                 }
1378
1379                 public int Receive (byte [] buf, SocketFlags flags)
1380                 {
1381                         if (disposed && closed)
1382                                 throw new ObjectDisposedException (GetType ().ToString ());
1383
1384                         if (buf == null)
1385                                 throw new ArgumentNullException ("buf");
1386
1387                         SocketError error;
1388
1389                         int ret = Receive_nochecks (buf, 0, buf.Length, flags, out error);
1390                         
1391                         if (error != SocketError.Success) {
1392                                 if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
1393                                         throw new SocketException ((int) error, "Operation timed out.");
1394                                 throw new SocketException ((int) error);
1395                         }
1396
1397                         return ret;
1398                 }
1399
1400                 public int Receive (byte [] buf, int size, SocketFlags flags)
1401                 {
1402                         if (disposed && closed)
1403                                 throw new ObjectDisposedException (GetType ().ToString ());
1404
1405                         if (buf == null)
1406                                 throw new ArgumentNullException ("buf");
1407
1408                         if (size < 0 || size > buf.Length)
1409                                 throw new ArgumentOutOfRangeException ("size");
1410
1411                         SocketError error;
1412
1413                         int ret = Receive_nochecks (buf, 0, size, flags, out error);
1414                         
1415                         if (error != SocketError.Success) {
1416                                 if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
1417                                         throw new SocketException ((int) error, "Operation timed out.");
1418                                 throw new SocketException ((int) error);
1419                         }
1420
1421                         return ret;
1422                 }
1423
1424                 public int Receive (byte [] buf, int offset, int size, SocketFlags flags)
1425                 {
1426                         if (disposed && closed)
1427                                 throw new ObjectDisposedException (GetType ().ToString ());
1428
1429                         if (buf == null)
1430                                 throw new ArgumentNullException ("buf");
1431
1432                         if (offset < 0 || offset > buf.Length)
1433                                 throw new ArgumentOutOfRangeException ("offset");
1434
1435                         if (size < 0 || offset + size > buf.Length)
1436                                 throw new ArgumentOutOfRangeException ("size");
1437                         
1438                         SocketError error;
1439
1440                         int ret = Receive_nochecks (buf, offset, size, flags, out error);
1441                         
1442                         if (error != SocketError.Success) {
1443                                 if (error == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
1444                                         throw new SocketException ((int) error, "Operation timed out.");
1445                                 throw new SocketException ((int) error);
1446                         }
1447
1448                         return ret;
1449                 }
1450
1451 #if NET_2_0
1452                 public int Receive (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
1453                 {
1454                         if (disposed && closed)
1455                                 throw new ObjectDisposedException (GetType ().ToString ());
1456
1457                         if (buf == null)
1458                                 throw new ArgumentNullException ("buf");
1459
1460                         if (offset < 0 || offset > buf.Length)
1461                                 throw new ArgumentOutOfRangeException ("offset");
1462
1463                         if (size < 0 || offset + size > buf.Length)
1464                                 throw new ArgumentOutOfRangeException ("size");
1465                         
1466                         return Receive_nochecks (buf, offset, size, flags, out error);
1467                 }
1468 #endif
1469
1470                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1471                 private extern static int Receive_internal(IntPtr sock,
1472                                                            byte[] buffer,
1473                                                            int offset,
1474                                                            int count,
1475                                                            SocketFlags flags,
1476                                                            out int error);
1477
1478                 int Receive_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
1479                 {
1480                         int nativeError;
1481                         int ret = Receive_internal (socket, buf, offset, size, flags, out nativeError);
1482                         error = (SocketError) nativeError;
1483                         if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress)
1484                                 connected = false;
1485                         else
1486                                 connected = true;
1487                         
1488                         return ret;
1489                 }
1490                 
1491                 public int ReceiveFrom (byte [] buf, ref EndPoint remote_end)
1492                 {
1493                         if (disposed && closed)
1494                                 throw new ObjectDisposedException (GetType ().ToString ());
1495
1496                         if (buf == null)
1497                                 throw new ArgumentNullException ("buf");
1498
1499                         if (remote_end == null)
1500                                 throw new ArgumentNullException ("remote_end");
1501
1502                         return ReceiveFrom_nochecks (buf, 0, buf.Length, SocketFlags.None, ref remote_end);
1503                 }
1504
1505                 public int ReceiveFrom (byte [] buf, SocketFlags flags, ref EndPoint remote_end)
1506                 {
1507                         if (disposed && closed)
1508                                 throw new ObjectDisposedException (GetType ().ToString ());
1509
1510                         if (buf == null)
1511                                 throw new ArgumentNullException ("buf");
1512
1513                         if (remote_end == null)
1514                                 throw new ArgumentNullException ("remote_end");
1515
1516
1517                         return ReceiveFrom_nochecks (buf, 0, buf.Length, flags, ref remote_end);
1518                 }
1519
1520                 public int ReceiveFrom (byte [] buf, int size, SocketFlags flags,
1521                                         ref EndPoint remote_end)
1522                 {
1523                         if (disposed && closed)
1524                                 throw new ObjectDisposedException (GetType ().ToString ());
1525
1526                         if (buf == null)
1527                                 throw new ArgumentNullException ("buf");
1528
1529                         if (remote_end == null)
1530                                 throw new ArgumentNullException ("remote_end");
1531
1532                         if (size < 0 || size > buf.Length)
1533                                 throw new ArgumentOutOfRangeException ("size");
1534
1535                         return ReceiveFrom_nochecks (buf, 0, size, flags, ref remote_end);
1536                 }
1537
1538
1539                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1540                 private extern static int RecvFrom_internal(IntPtr sock,
1541                                                             byte[] buffer,
1542                                                             int offset,
1543                                                             int count,
1544                                                             SocketFlags flags,
1545                                                             ref SocketAddress sockaddr,
1546                                                             out int error);
1547
1548                 public int ReceiveFrom (byte [] buf, int offset, int size, SocketFlags flags,
1549                                         ref EndPoint remote_end)
1550                 {
1551                         if (disposed && closed)
1552                                 throw new ObjectDisposedException (GetType ().ToString ());
1553
1554                         if (buf == null)
1555                                 throw new ArgumentNullException ("buf");
1556
1557                         if (remote_end == null)
1558                                 throw new ArgumentNullException ("remote_end");
1559
1560                         if (offset < 0 || offset > buf.Length)
1561                                 throw new ArgumentOutOfRangeException ("offset");
1562
1563                         if (size < 0 || offset + size > buf.Length)
1564                                 throw new ArgumentOutOfRangeException ("size");
1565
1566                         return ReceiveFrom_nochecks (buf, offset, size, flags, ref remote_end);
1567                 }
1568
1569                 int ReceiveFrom_nochecks (byte [] buf, int offset, int size, SocketFlags flags,
1570                                           ref EndPoint remote_end)
1571                 {
1572                         SocketAddress sockaddr = remote_end.Serialize();
1573                         int cnt, error;
1574
1575                         cnt = RecvFrom_internal (socket, buf, offset, size, flags, ref sockaddr, out error);
1576
1577                         SocketError err = (SocketError) error;
1578                         if (err != 0) {
1579                                 if (err != SocketError.WouldBlock && err != SocketError.InProgress)
1580                                         connected = false;
1581                                 else if (err == SocketError.WouldBlock && blocking) // This might happen when ReceiveTimeout is set
1582                                         throw new SocketException (error, "Operation timed out.");
1583
1584                                 throw new SocketException (error);
1585                         }
1586
1587                         connected = true;
1588
1589                         // If sockaddr is null then we're a connection
1590                         // oriented protocol and should ignore the
1591                         // remote_end parameter (see MSDN
1592                         // documentation for Socket.ReceiveFrom(...) )
1593                         
1594                         if ( sockaddr != null ) {
1595                                 // Stupidly, EndPoint.Create() is an
1596                                 // instance method
1597                                 remote_end = remote_end.Create (sockaddr);
1598                         }
1599
1600                         return cnt;
1601                 }
1602
1603                 public int Send (byte [] buf)
1604                 {
1605                         if (disposed && closed)
1606                                 throw new ObjectDisposedException (GetType ().ToString ());
1607
1608                         if (buf == null)
1609                                 throw new ArgumentNullException ("buf");
1610
1611                         SocketError error;
1612
1613                         int ret = Send_nochecks (buf, 0, buf.Length, SocketFlags.None, out error);
1614
1615                         if (error != SocketError.Success)
1616                                 throw new SocketException ((int) error);
1617
1618                         return ret;
1619                 }
1620
1621                 public int Send (byte [] buf, SocketFlags flags)
1622                 {
1623                         if (disposed && closed)
1624                                 throw new ObjectDisposedException (GetType ().ToString ());
1625
1626                         if (buf == null)
1627                                 throw new ArgumentNullException ("buf");
1628
1629                         SocketError error;
1630
1631                         int ret = Send_nochecks (buf, 0, buf.Length, flags, out error);
1632
1633                         if (error != SocketError.Success)
1634                                 throw new SocketException ((int) error);
1635
1636                         return ret;
1637                 }
1638
1639                 public int Send (byte [] buf, int size, SocketFlags flags)
1640                 {
1641                         if (disposed && closed)
1642                                 throw new ObjectDisposedException (GetType ().ToString ());
1643
1644                         if (buf == null)
1645                                 throw new ArgumentNullException ("buf");
1646
1647                         if (size < 0 || size > buf.Length)
1648                                 throw new ArgumentOutOfRangeException ("size");
1649
1650                         SocketError error;
1651
1652                         int ret = Send_nochecks (buf, 0, size, flags, out error);
1653
1654                         if (error != SocketError.Success)
1655                                 throw new SocketException ((int) error);
1656
1657                         return ret;
1658                 }
1659
1660                 public int Send (byte [] buf, int offset, int size, SocketFlags flags)
1661                 {
1662                         if (disposed && closed)
1663                                 throw new ObjectDisposedException (GetType ().ToString ());
1664
1665                         if (buf == null)
1666                                 throw new ArgumentNullException ("buffer");
1667
1668                         if (offset < 0 || offset > buf.Length)
1669                                 throw new ArgumentOutOfRangeException ("offset");
1670
1671                         if (size < 0 || offset + size > buf.Length)
1672                                 throw new ArgumentOutOfRangeException ("size");
1673
1674                         SocketError error;
1675
1676                         int ret = Send_nochecks (buf, offset, size, flags, out error);
1677
1678                         if (error != SocketError.Success)
1679                                 throw new SocketException ((int) error);
1680
1681                         return ret;
1682                 }
1683
1684 #if NET_2_0
1685                 public int Send (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
1686                 {
1687                         if (disposed && closed)
1688                                 throw new ObjectDisposedException (GetType ().ToString ());
1689
1690                         if (buf == null)
1691                                 throw new ArgumentNullException ("buffer");
1692
1693                         if (offset < 0 || offset > buf.Length)
1694                                 throw new ArgumentOutOfRangeException ("offset");
1695
1696                         if (size < 0 || offset + size > buf.Length)
1697                                 throw new ArgumentOutOfRangeException ("size");
1698
1699                         return Send_nochecks (buf, offset, size, flags, out error);
1700                 }
1701 #endif
1702
1703                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1704                 private extern static int Send_internal(IntPtr sock,
1705                                                         byte[] buf, int offset,
1706                                                         int count,
1707                                                         SocketFlags flags,
1708                                                         out int error);
1709
1710                 int Send_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
1711                 {
1712                         if (size == 0) {
1713                                 error = SocketError.Success;
1714                                 return 0;
1715                         }
1716
1717                         int nativeError;
1718
1719                         int ret = Send_internal (socket, buf, offset, size, flags, out nativeError);
1720
1721                         error = (SocketError)nativeError;
1722
1723                         if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress)
1724                                 connected = false;
1725                         else
1726                                 connected = true;
1727
1728                         return ret;
1729                 }
1730
1731                 public int SendTo (byte [] buffer, EndPoint remote_end)
1732                 {
1733                         if (disposed && closed)
1734                                 throw new ObjectDisposedException (GetType ().ToString ());
1735
1736                         if (buffer == null)
1737                                 throw new ArgumentNullException ("buffer");
1738
1739                         if (remote_end == null)
1740                                 throw new ArgumentNullException ("remote_end");
1741
1742                         return SendTo_nochecks (buffer, 0, buffer.Length, SocketFlags.None, remote_end);
1743                 }
1744
1745                 public int SendTo (byte [] buffer, SocketFlags flags, EndPoint remote_end)
1746                 {
1747                         if (disposed && closed)
1748                                 throw new ObjectDisposedException (GetType ().ToString ());
1749
1750                         if (buffer == null)
1751                                 throw new ArgumentNullException ("buffer");
1752
1753                         if (remote_end == null)
1754                                 throw new ArgumentNullException ("remote_end");
1755                                 
1756                         return SendTo_nochecks (buffer, 0, buffer.Length, flags, remote_end);
1757                 }
1758
1759                 public int SendTo (byte [] buffer, int size, SocketFlags flags, EndPoint remote_end)
1760                 {
1761                         if (disposed && closed)
1762                                 throw new ObjectDisposedException (GetType ().ToString ());
1763
1764                         if (buffer == null)
1765                                 throw new ArgumentNullException ("buffer");
1766
1767                         if (remote_end == null)
1768                                 throw new ArgumentNullException ("remote_end");
1769
1770                         if (size < 0 || size > buffer.Length)
1771                                 throw new ArgumentOutOfRangeException ("size");
1772
1773                         return SendTo_nochecks (buffer, 0, size, flags, remote_end);
1774                 }
1775
1776                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1777                 private extern static int SendTo_internal(IntPtr sock,
1778                                                           byte[] buffer,
1779                                                           int offset,
1780                                                           int count,
1781                                                           SocketFlags flags,
1782                                                           SocketAddress sa,
1783                                                           out int error);
1784
1785                 public int SendTo (byte [] buffer, int offset, int size, SocketFlags flags,
1786                                    EndPoint remote_end)
1787                 {
1788                         if (disposed && closed)
1789                                 throw new ObjectDisposedException (GetType ().ToString ());
1790
1791                         if (buffer == null)
1792                                 throw new ArgumentNullException ("buffer");
1793
1794                         if (remote_end == null)
1795                                 throw new ArgumentNullException("remote_end");
1796
1797                         if (offset < 0 || offset > buffer.Length)
1798                                 throw new ArgumentOutOfRangeException ("offset");
1799
1800                         if (size < 0 || offset + size > buffer.Length)
1801                                 throw new ArgumentOutOfRangeException ("size");
1802
1803                         return SendTo_nochecks (buffer, offset, size, flags, remote_end);
1804                 }
1805
1806                 int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags,
1807                                    EndPoint remote_end)
1808                 {
1809                         SocketAddress sockaddr = remote_end.Serialize ();
1810
1811                         int ret, error;
1812
1813                         ret = SendTo_internal (socket, buffer, offset, size, flags, sockaddr, out error);
1814
1815                         SocketError err = (SocketError) error;
1816                         if (err != 0) {
1817                                 if (err != SocketError.WouldBlock && err != SocketError.InProgress)
1818                                         connected = false;
1819
1820                                 throw new SocketException (error);
1821                         }
1822
1823                         connected = true;
1824
1825                         return ret;
1826                 }
1827
1828                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1829                 private extern static void SetSocketOption_internal (IntPtr socket, SocketOptionLevel level,
1830                                                                      SocketOptionName name, object obj_val,
1831                                                                      byte [] byte_val, int int_val,
1832                                                                      out int error);
1833
1834                 public void SetSocketOption (SocketOptionLevel level, SocketOptionName name, byte[] opt_value)
1835                 {
1836                         if (disposed && closed)
1837                                 throw new ObjectDisposedException (GetType ().ToString ());
1838
1839                         int error;
1840                         
1841                         SetSocketOption_internal(socket, level, name, null,
1842                                                  opt_value, 0, out error);
1843
1844                         if (error != 0) {
1845                                 throw new SocketException (error);
1846                         }
1847                 }
1848
1849                 public void SetSocketOption (SocketOptionLevel level, SocketOptionName name, int opt_value)
1850                 {
1851                         if (disposed && closed)
1852                                 throw new ObjectDisposedException (GetType ().ToString ());
1853
1854                         int error;
1855                         
1856                         SetSocketOption_internal(socket, level, name, null,
1857                                                  null, opt_value, out error);
1858
1859                         if (error != 0) {
1860                                 throw new SocketException (error);
1861                         }
1862                 }
1863
1864                 public void SetSocketOption (SocketOptionLevel level, SocketOptionName name, object opt_value)
1865                 {
1866
1867                         if (disposed && closed)
1868                                 throw new ObjectDisposedException (GetType ().ToString ());
1869
1870                         if(opt_value==null) {
1871                                 throw new ArgumentNullException();
1872                         }
1873                         
1874                         int error;
1875                         /* From MS documentation on SetSocketOption: "For an
1876                          * option with a Boolean data type, specify a nonzero
1877                          * value to enable the option, and a zero value to
1878                          * disable the option."
1879                          * Booleans are only handled in 2.0
1880                          */
1881
1882                         if (opt_value is System.Boolean) {
1883 #if NET_2_0
1884                                 bool bool_val = (bool) opt_value;
1885                                 int int_val = (bool_val) ? 1 : 0;
1886
1887                                 SetSocketOption_internal (socket, level, name, null, null, int_val, out error);
1888 #else
1889                                 throw new ArgumentException ("Use an integer 1 (true) or 0 (false) instead of a boolean.", "opt_value");
1890 #endif
1891                         } else {
1892                                 SetSocketOption_internal (socket, level, name, opt_value, null, 0, out error);
1893                         }
1894
1895                         if (error != 0)
1896                                 throw new SocketException (error);
1897                 }
1898
1899 #if NET_2_0
1900                 public void SetSocketOption (SocketOptionLevel level, SocketOptionName name, bool optionValue)
1901                 {
1902                         if (disposed && closed)
1903                                 throw new ObjectDisposedException (GetType ().ToString ());
1904
1905                         int error;
1906                         int int_val = (optionValue) ? 1 : 0;
1907                         SetSocketOption_internal (socket, level, name, null, null, int_val, out error);
1908                         if (error != 0)
1909                                 throw new SocketException (error);
1910                 }
1911 #endif
1912                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1913                 private extern static void Shutdown_internal(IntPtr socket, SocketShutdown how, out int error);
1914                 
1915                 public void Shutdown (SocketShutdown how)
1916                 {
1917                         if (disposed && closed)
1918                                 throw new ObjectDisposedException (GetType ().ToString ());
1919
1920                         int error;
1921                         
1922                         Shutdown_internal(socket, how, out error);
1923
1924                         if (error != 0) {
1925                                 throw new SocketException (error);
1926                         }
1927                 }
1928
1929                 public override int GetHashCode ()
1930                 { 
1931                         return (int) socket; 
1932                 }
1933
1934                 protected virtual void Dispose (bool explicitDisposing)
1935                 {
1936                         if (disposed)
1937                                 return;
1938
1939                         disposed = true;
1940                         connected = false;
1941                         if ((int) socket != -1) {
1942                                 int error;
1943                                 closed = true;
1944                                 IntPtr x = socket;
1945                                 socket = (IntPtr) (-1);
1946                                 Close_internal (x, out error);
1947                                 if (blocking_thread != null) {
1948                                         blocking_thread.Abort ();
1949                                         blocking_thread = null;
1950                                 }
1951
1952                                 if (error != 0)
1953                                         throw new SocketException (error);
1954                         }
1955                 }
1956
1957                 void IDisposable.Dispose ()
1958                 {
1959                         Dispose (true);
1960                         GC.SuppressFinalize (this);
1961                 }
1962                 
1963                 ~Socket () {
1964                         Dispose(false);
1965                 }
1966         }
1967 }
1968