SocketTest.ConnectMultiple() for Mac OS.
[mono.git] / mcs / class / System / System.Net.Sockets / Socket_2_1.cs
1 // System.Net.Sockets.Socket.cs
2 //
3 // Authors:
4 //      Phillip Pearson (pp@myelin.co.nz)
5 //      Dick Porter <dick@ximian.com>
6 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 //      Sridhar Kulkarni (sridharkulkarni@gmail.com)
8 //      Brian Nickel (brian.nickel@gmail.com)
9 //
10 // Copyright (C) 2001, 2002 Phillip Pearson and Ximian, Inc.
11 //    http://www.myelin.co.nz
12 // (c) 2004-2011 Novell, Inc. (http://www.novell.com)
13 //
14
15 //
16 // Permission is hereby granted, free of charge, to any person obtaining
17 // a copy of this software and associated documentation files (the
18 // "Software"), to deal in the Software without restriction, including
19 // without limitation the rights to use, copy, modify, merge, publish,
20 // distribute, sublicense, and/or sell copies of the Software, and to
21 // permit persons to whom the Software is furnished to do so, subject to
22 // the following conditions:
23 // 
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
26 // 
27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 //
35
36 using System;
37 using System.Net;
38 using System.Collections;
39 using System.Collections.Generic;
40 using System.Runtime.CompilerServices;
41 using System.Runtime.InteropServices;
42 using System.Threading;
43 using System.IO;
44 using System.Security;
45 using System.Text;
46
47 #if !NET_2_1
48 using System.Net.Configuration;
49 using System.Net.NetworkInformation;
50 #endif
51 #if MOONLIGHT && !INSIDE_SYSTEM
52 using System.Net.Policy;
53 #endif
54
55 namespace System.Net.Sockets {
56
57         public partial class Socket : IDisposable {
58                 [StructLayout (LayoutKind.Sequential)]
59                 struct WSABUF {
60                         public int len;
61                         public IntPtr buf;
62                 }
63
64                 // Used by the runtime
65                 internal enum SocketOperation {
66                         Accept,
67                         Connect,
68                         Receive,
69                         ReceiveFrom,
70                         Send,
71                         SendTo,
72                         RecvJustCallback,
73                         SendJustCallback,
74                         UsedInProcess,
75                         UsedInConsole2,
76                         Disconnect,
77                         AcceptReceive,
78                         ReceiveGeneric,
79                         SendGeneric
80                 }
81
82                 [StructLayout (LayoutKind.Sequential)]
83                 internal sealed class SocketAsyncResult: IAsyncResult
84                 {
85                         /* Same structure in the runtime */
86                         /*
87                           Keep this in sync with MonoSocketAsyncResult in
88                           metadata/socket-io.h and ProcessAsyncReader
89                           in System.Diagnostics/Process.cs.
90                         */
91
92                         public Socket Sock;
93                         public IntPtr handle;
94                         object state;
95                         AsyncCallback callback; // used from the runtime
96                         WaitHandle waithandle;
97
98                         Exception delayedException;
99
100                         public EndPoint EndPoint;       // Connect,ReceiveFrom,SendTo
101                         public byte [] Buffer;          // Receive,ReceiveFrom,Send,SendTo
102                         public int Offset;              // Receive,ReceiveFrom,Send,SendTo
103                         public int Size;                // Receive,ReceiveFrom,Send,SendTo
104                         public SocketFlags SockFlags;   // Receive,ReceiveFrom,Send,SendTo
105                         public Socket AcceptSocket;     // AcceptReceive
106                         public IPAddress[] Addresses;   // Connect
107                         public int Port;                // Connect
108                         public IList<ArraySegment<byte>> Buffers;       // Receive, Send
109                         public bool ReuseSocket;        // Disconnect
110
111                         // Return values
112                         Socket acc_socket;
113                         int total;
114
115                         bool completed_sync;
116                         bool completed;
117                         public bool blocking;
118                         internal int error;
119                         public SocketOperation operation;
120                         public object ares;
121                         public int EndCalled;
122
123                         // These fields are not in MonoSocketAsyncResult
124                         public Worker Worker;
125                         public int CurrentAddress; // Connect
126
127                         public SocketAsyncResult ()
128                         {
129                         }
130
131                         public void Init (Socket sock, object state, AsyncCallback callback, SocketOperation operation)
132                         {
133                                 this.Sock = sock;
134                                 if (sock != null) {
135                                         this.blocking = sock.blocking;
136                                         this.handle = sock.socket;
137                                 } else {
138                                         this.blocking = true;
139                                         this.handle = IntPtr.Zero;
140                                 }
141                                 this.state = state;
142                                 this.callback = callback;
143                                 GC.KeepAlive (this.callback);
144                                 this.operation = operation;
145                                 SockFlags = SocketFlags.None;
146                                 if (waithandle != null)
147                                         ((ManualResetEvent) waithandle).Reset ();
148
149                                 delayedException = null;
150
151                                 EndPoint = null;
152                                 Buffer = null;
153                                 Offset = 0;
154                                 Size = 0;
155                                 SockFlags = 0;
156                                 AcceptSocket = null;
157                                 Addresses = null;
158                                 Port = 0;
159                                 Buffers = null;
160                                 ReuseSocket = false;
161                                 acc_socket = null;
162                                 total = 0;
163
164                                 completed_sync = false;
165                                 completed = false;
166                                 blocking = false;
167                                 error = 0;
168                                 ares = null;
169                                 EndCalled = 0;
170                                 Worker = null;
171                         }
172
173                         public void DoMConnectCallback ()
174                         {
175                                 if (callback == null)
176                                         return;
177 #if MOONLIGHT
178                                 ThreadPool.QueueUserWorkItem (_ => { callback (this); }, null);
179 #else
180                                 ThreadPool.UnsafeQueueUserWorkItem (_ => { callback (this); }, null);
181 #endif
182                         }
183
184                         public void Dispose ()
185                         {
186                                 Init (null, null, null, 0);
187                                 if (waithandle != null) {
188                                         waithandle.Close ();
189                                         waithandle = null;
190                                 }
191                         }
192
193                         public SocketAsyncResult (Socket sock, object state, AsyncCallback callback, SocketOperation operation)
194                         {
195                                 this.Sock = sock;
196                                 this.blocking = sock.blocking;
197                                 this.handle = sock.socket;
198                                 this.state = state;
199                                 this.callback = callback;
200                                 GC.KeepAlive (this.callback);
201                                 this.operation = operation;
202                                 SockFlags = SocketFlags.None;
203                                 Worker = new Worker (this);
204                         }
205
206                         public void CheckIfThrowDelayedException ()
207                         {
208                                 if (delayedException != null) {
209                                         Sock.connected = false;
210                                         throw delayedException;
211                                 }
212
213                                 if (error != 0) {
214                                         Sock.connected = false;
215                                         throw new SocketException (error);
216                                 }
217                         }
218
219                         void CompleteAllOnDispose (Queue queue)
220                         {
221                                 object [] pending = queue.ToArray ();
222                                 queue.Clear ();
223
224                                 WaitCallback cb;
225                                 for (int i = 0; i < pending.Length; i++) {
226                                         Worker worker = (Worker) pending [i];
227                                         SocketAsyncResult ares = worker.result;
228                                         cb = new WaitCallback (ares.CompleteDisposed);
229 #if MOONLIGHT
230                                         ThreadPool.QueueUserWorkItem (cb, null);
231 #else
232                                         ThreadPool.UnsafeQueueUserWorkItem (cb, null);
233 #endif
234                                 }
235                         }
236
237                         void CompleteDisposed (object unused)
238                         {
239                                 Complete ();
240                         }
241
242                         public void Complete ()
243                         {
244                                 if (operation != SocketOperation.Receive && Sock.disposed)
245                                         delayedException = new ObjectDisposedException (Sock.GetType ().ToString ());
246
247                                 IsCompleted = true;
248
249                                 Queue queue = null;
250                                 if (operation == SocketOperation.Receive ||
251                                     operation == SocketOperation.ReceiveFrom ||
252                                     operation == SocketOperation.ReceiveGeneric ||
253                                     operation == SocketOperation.Accept) {
254                                         queue = Sock.readQ;
255                                 } else if (operation == SocketOperation.Send ||
256                                            operation == SocketOperation.SendTo ||
257                                            operation == SocketOperation.SendGeneric) {
258
259                                         queue = Sock.writeQ;
260                                 }
261
262                                 if (queue != null) {
263                                         Worker worker = null;
264                                         SocketAsyncCall sac = null;
265                                         lock (queue) {
266                                                 // queue.Count will only be 0 if the socket is closed while receive/send/accept
267                                                 // operation(s) are pending and at least one call to this method is
268                                                 // waiting on the lock while another one calls CompleteAllOnDispose()
269                                                 if (queue.Count > 0)
270                                                         queue.Dequeue (); // remove ourselves
271                                                 if (queue.Count > 0) {
272                                                         worker = (Worker) queue.Peek ();
273                                                         if (!Sock.disposed) {
274                                                                 sac = Worker.Dispatcher;
275                                                         } else {
276                                                                 CompleteAllOnDispose (queue);
277                                                         }
278                                                 }
279                                         }
280
281                                         if (sac != null)
282                                                 Socket.socket_pool_queue (sac, worker.result);
283                                 }
284                                 // IMPORTANT: 'callback', if any is scheduled from unmanaged code
285                         }
286
287                         public void Complete (bool synch)
288                         {
289                                 completed_sync = synch;
290                                 Complete ();
291                         }
292
293                         public void Complete (int total)
294                         {
295                                 this.total = total;
296                                 Complete ();
297                         }
298
299                         public void Complete (Exception e, bool synch)
300                         {
301                                 completed_sync = synch;
302                                 delayedException = e;
303                                 Complete ();
304                         }
305
306                         public void Complete (Exception e)
307                         {
308                                 delayedException = e;
309                                 Complete ();
310                         }
311
312                         public void Complete (Socket s)
313                         {
314                                 acc_socket = s;
315                                 Complete ();
316                         }
317
318                         public void Complete (Socket s, int total)
319                         {
320                                 acc_socket = s;
321                                 this.total = total;
322                                 Complete ();
323                         }
324
325                         public object AsyncState {
326                                 get {
327                                         return state;
328                                 }
329                         }
330
331                         public WaitHandle AsyncWaitHandle {
332                                 get {
333                                         lock (this) {
334                                                 if (waithandle == null)
335                                                         waithandle = new ManualResetEvent (completed);
336                                         }
337
338                                         return waithandle;
339                                 }
340                                 set {
341                                         waithandle=value;
342                                 }
343                         }
344
345                         public bool CompletedSynchronously {
346                                 get {
347                                         return(completed_sync);
348                                 }
349                         }
350
351                         public bool IsCompleted {
352                                 get {
353                                         return(completed);
354                                 }
355                                 set {
356                                         completed=value;
357                                         lock (this) {
358                                                 if (waithandle != null && value) {
359                                                         ((ManualResetEvent) waithandle).Set ();
360                                                 }
361                                         }
362                                 }
363                         }
364
365                         public Socket Socket {
366                                 get {
367                                         return acc_socket;
368                                 }
369                         }
370
371                         public int Total {
372                                 get { return total; }
373                                 set { total = value; }
374                         }
375
376                         public SocketError ErrorCode {
377                                 get {
378                                         SocketException ex = delayedException as SocketException;
379                                         if (ex != null)
380                                                 return(ex.SocketErrorCode);
381
382                                         if (error != 0)
383                                                 return((SocketError)error);
384
385                                         return(SocketError.Success);
386                                 }
387                         }
388                 }
389
390                 internal sealed class Worker
391                 {
392                         public SocketAsyncResult result;
393                         SocketAsyncEventArgs args;
394
395                         public Worker (SocketAsyncEventArgs args)
396                         {
397                                 this.args = args;
398                                 result = new SocketAsyncResult ();
399                                 result.Worker = this;
400                         }
401
402                         public Worker (SocketAsyncResult ares)
403                         {
404                                 this.result = ares;
405                         }
406
407                         public void Dispose ()
408                         {
409                                 if (result != null) {
410                                         result.Dispose ();
411                                         result = null;
412                                         args = null;
413                                 }
414                         }
415
416                         public static SocketAsyncCall Dispatcher = new SocketAsyncCall (DispatcherCB);
417
418                         static void DispatcherCB (SocketAsyncResult sar)
419                         {
420                                 SocketOperation op = sar.operation;
421                                 if (op == Socket.SocketOperation.Receive || op == Socket.SocketOperation.ReceiveGeneric ||
422                                         op == Socket.SocketOperation.RecvJustCallback)
423                                         sar.Worker.Receive ();
424                                 else if (op == Socket.SocketOperation.Send || op == Socket.SocketOperation.SendGeneric ||
425                                         op == Socket.SocketOperation.SendJustCallback)
426                                         sar.Worker.Send ();
427 #if !MOONLIGHT
428                                 else if (op == Socket.SocketOperation.ReceiveFrom)
429                                         sar.Worker.ReceiveFrom ();
430                                 else if (op == Socket.SocketOperation.SendTo)
431                                         sar.Worker.SendTo ();
432 #endif
433                                 else if (op == Socket.SocketOperation.Connect)
434                                         sar.Worker.Connect ();
435 #if !MOONLIGHT
436                                 else if (op == Socket.SocketOperation.Accept)
437                                         sar.Worker.Accept ();
438                                 else if (op == Socket.SocketOperation.AcceptReceive)
439                                         sar.Worker.AcceptReceive ();
440                                 else if (op == Socket.SocketOperation.Disconnect)
441                                         sar.Worker.Disconnect ();
442
443                                 // SendPackets and ReceiveMessageFrom are not implemented yet
444                                 /*
445                                 else if (op == Socket.SocketOperation.ReceiveMessageFrom)
446                                         async_op = SocketAsyncOperation.ReceiveMessageFrom;
447                                 else if (op == Socket.SocketOperation.SendPackets)
448                                         async_op = SocketAsyncOperation.SendPackets;
449                                 */
450 #endif
451                                 else
452                                         throw new NotImplementedException (String.Format ("Operation {0} is not implemented", op));
453                         }
454
455                         /* This is called when reusing a SocketAsyncEventArgs */
456                         public void Init (Socket sock, SocketAsyncEventArgs args, SocketOperation op)
457                         {
458                                 result.Init (sock, args, SocketAsyncEventArgs.Dispatcher, op);
459                                 result.Worker = this;
460                                 SocketAsyncOperation async_op;
461
462                                 // Notes;
463                                 //      -SocketOperation.AcceptReceive not used in SocketAsyncEventArgs
464                                 //      -SendPackets and ReceiveMessageFrom are not implemented yet
465                                 if (op == Socket.SocketOperation.Connect)
466                                         async_op = SocketAsyncOperation.Connect;
467 #if !MOONLIGHT
468                                 else if (op == Socket.SocketOperation.Accept)
469                                         async_op = SocketAsyncOperation.Accept;
470                                 else if (op == Socket.SocketOperation.Disconnect)
471                                         async_op = SocketAsyncOperation.Disconnect;
472 #endif
473                                 else if (op == Socket.SocketOperation.Receive || op == Socket.SocketOperation.ReceiveGeneric)
474                                         async_op = SocketAsyncOperation.Receive;
475 #if !MOONLIGHT
476                                 else if (op == Socket.SocketOperation.ReceiveFrom)
477                                         async_op = SocketAsyncOperation.ReceiveFrom;
478 #endif
479                                 /*
480                                 else if (op == Socket.SocketOperation.ReceiveMessageFrom)
481                                         async_op = SocketAsyncOperation.ReceiveMessageFrom;
482                                 */
483                                 else if (op == Socket.SocketOperation.Send || op == Socket.SocketOperation.SendGeneric)
484                                         async_op = SocketAsyncOperation.Send;
485 #if !MOONLIGHT
486                                 /*
487                                 else if (op == Socket.SocketOperation.SendPackets)
488                                         async_op = SocketAsyncOperation.SendPackets;
489                                 */
490                                 else if (op == Socket.SocketOperation.SendTo)
491                                         async_op = SocketAsyncOperation.SendTo;
492 #endif
493                                 else
494                                         throw new NotImplementedException (String.Format ("Operation {0} is not implemented", op));
495
496                                 args.SetLastOperation (async_op);
497                                 args.SocketError = SocketError.Success;
498                                 args.BytesTransferred = 0;
499                         }
500
501                         public void Accept ()
502                         {
503 #if !MOONLIGHT
504                                 Socket acc_socket = null;
505                                 try {
506                                         if (args != null && args.AcceptSocket != null) {
507                                                 result.Sock.Accept (args.AcceptSocket);
508                                                 acc_socket = args.AcceptSocket;
509                                         } else {
510                                                 acc_socket = result.Sock.Accept ();
511                                                 if (args != null)
512                                                         args.AcceptSocket = acc_socket;
513                                         }
514                                 } catch (Exception e) {
515                                         result.Complete (e);
516                                         return;
517                                 }
518
519                                 result.Complete (acc_socket);
520 #endif
521                         }
522
523                         /* only used in 2.0 profile and newer, but
524                          * leave in older profiles to keep interface
525                          * to runtime consistent
526                          */
527                         public void AcceptReceive ()
528                         {
529 #if !MOONLIGHT
530                                 Socket acc_socket = null;
531                                 try {
532                                         if (result.AcceptSocket == null) {
533                                                 acc_socket = result.Sock.Accept ();
534                                         } else {
535                                                 acc_socket = result.AcceptSocket;
536                                                 result.Sock.Accept (acc_socket);
537                                         }
538                                 } catch (Exception e) {
539                                         result.Complete (e);
540                                         return;
541                                 }
542
543                                 /* It seems the MS runtime
544                                  * special-cases 0-length requested
545                                  * receive data.  See bug 464201.
546                                  */
547                                 int total = 0;
548                                 if (result.Size > 0) {
549                                         try {
550                                                 SocketError error;
551                                                 total = acc_socket.Receive_nochecks (result.Buffer,
552                                                                                      result.Offset,
553                                                                                      result.Size,
554                                                                                      result.SockFlags,
555                                                                                      out error);
556                                                 if (error != 0) {
557                                                         result.Complete (new SocketException ((int) error));
558                                                         return;
559                                                 }
560                                         } catch (Exception e) {
561                                                 result.Complete (e);
562                                                 return;
563                                         }
564                                 }
565
566                                 result.Complete (acc_socket, total);
567 #endif
568                         }
569
570                         public void Connect ()
571                         {
572                                 if (result.EndPoint == null) {
573                                         result.Complete (new SocketException ((int)SocketError.AddressNotAvailable));
574                                         return;
575                                 }
576
577                                 SocketAsyncResult mconnect = result.AsyncState as SocketAsyncResult;
578 #if !MOONLIGHT
579                                 bool is_mconnect = (mconnect != null && mconnect.Addresses != null);
580 #else
581                                 if (result.ErrorCode == SocketError.AccessDenied) {
582                                         result.Complete ();
583                                         result.DoMConnectCallback ();
584                                         return;
585                                 }
586                                 bool is_mconnect = false;
587 #endif
588                                 try {
589                                         int error_code;
590                                         EndPoint ep = result.EndPoint;
591                                         error_code = (int) result.Sock.GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
592                                         if (error_code == 0) {
593                                                 if (is_mconnect)
594                                                         result = mconnect;
595                                                 result.Sock.seed_endpoint = ep;
596                                                 result.Sock.connected = true;
597                                                 result.Sock.isbound = true;
598                                                 result.Sock.connect_in_progress = false;
599                                                 result.error = 0;
600                                                 result.Complete ();
601                                                 if (is_mconnect)
602                                                         result.DoMConnectCallback ();
603                                                 return;
604                                         }
605
606                                         if (!is_mconnect) {
607                                                 result.Sock.connect_in_progress = false;
608                                                 result.Complete (new SocketException (error_code));
609                                                 return;
610                                         }
611
612                                         if (mconnect.CurrentAddress >= mconnect.Addresses.Length) {
613                                                 mconnect.Complete (new SocketException (error_code));
614                                                 if (is_mconnect)
615                                                         mconnect.DoMConnectCallback ();
616                                                 return;
617                                         }
618                                         mconnect.Sock.BeginMConnect (mconnect);
619                                 } catch (Exception e) {
620                                         result.Sock.connect_in_progress = false;
621                                         if (is_mconnect)
622                                                 result = mconnect;
623                                         result.Complete (e);
624                                         if (is_mconnect)
625                                                 result.DoMConnectCallback ();
626                                         return;
627                                 }
628                         }
629
630                         /* Also only used in 2.0 profile and newer */
631                         public void Disconnect ()
632                         {
633 #if !MOONLIGHT
634                                 try {
635                                         if (args != null)
636                                                 result.ReuseSocket = args.DisconnectReuseSocket;
637                                         result.Sock.Disconnect (result.ReuseSocket);
638                                 } catch (Exception e) {
639                                         result.Complete (e);
640                                         return;
641                                 }
642                                 result.Complete ();
643 #endif
644                         }
645
646                         public void Receive ()
647                         {
648                                 if (result.operation == SocketOperation.ReceiveGeneric) {
649                                         ReceiveGeneric ();
650                                         return;
651                                 }
652                                 // Actual recv() done in the runtime
653                                 result.Complete ();
654                         }
655
656                         public void ReceiveFrom ()
657                         {
658 #if !MOONLIGHT
659                                 int total = 0;
660                                 try {
661                                         total = result.Sock.ReceiveFrom_nochecks (result.Buffer,
662                                                                          result.Offset,
663                                                                          result.Size,
664                                                                          result.SockFlags,
665                                                                          ref result.EndPoint);
666                                 } catch (Exception e) {
667                                         result.Complete (e);
668                                         return;
669                                 }
670
671                                 result.Complete (total);
672 #endif
673                         }
674
675                         public void ReceiveGeneric ()
676                         {
677                                 int total = 0;
678                                 try {
679                                         total = result.Sock.Receive (result.Buffers, result.SockFlags);
680                                 } catch (Exception e) {
681                                         result.Complete (e);
682                                         return;
683                                 }
684                                 result.Complete (total);
685                         }
686
687                         int send_so_far;
688
689                         void UpdateSendValues (int last_sent)
690                         {
691                                 if (result.error == 0) {
692                                         send_so_far += last_sent;
693                                         result.Offset += last_sent;
694                                         result.Size -= last_sent;
695                                 }
696                         }
697
698                         public void Send ()
699                         {
700                                 if (result.operation == SocketOperation.SendGeneric) {
701                                         SendGeneric ();
702                                         return;
703                                 }
704                                 // Actual send() done in the runtime
705                                 if (result.error == 0) {
706                                         UpdateSendValues (result.Total);
707                                         if (result.Sock.disposed) {
708                                                 result.Complete ();
709                                                 return;
710                                         }
711
712                                         if (result.Size > 0) {
713                                                 Socket.socket_pool_queue (Worker.Dispatcher, result);
714                                                 return; // Have to finish writing everything. See bug #74475.
715                                         }
716                                         result.Total = send_so_far;
717                                         send_so_far = 0;
718                                 }
719                                 result.Complete ();
720                         }
721
722                         public void SendTo ()
723                         {
724 #if !MOONLIGHT
725                                 int total = 0;
726                                 try {
727                                         total = result.Sock.SendTo_nochecks (result.Buffer,
728                                                                     result.Offset,
729                                                                     result.Size,
730                                                                     result.SockFlags,
731                                                                     result.EndPoint);
732
733                                         UpdateSendValues (total);
734                                         if (result.Size > 0) {
735                                                 Socket.socket_pool_queue (Worker.Dispatcher, result);
736                                                 return; // Have to finish writing everything. See bug #74475.
737                                         }
738                                         result.Total = send_so_far;
739                                         send_so_far = 0;
740                                 } catch (Exception e) {
741                                         send_so_far = 0;
742                                         result.Complete (e);
743                                         return;
744                                 }
745
746                                 result.Complete ();
747 #endif
748                         }
749
750                         public void SendGeneric ()
751                         {
752                                 int total = 0;
753                                 try {
754                                         total = result.Sock.Send (result.Buffers, result.SockFlags);
755                                 } catch (Exception e) {
756                                         result.Complete (e);
757                                         return;
758                                 }
759                                 result.Complete (total);
760                         }
761                 }
762
763                 private Queue readQ = new Queue (2);
764                 private Queue writeQ = new Queue (2);
765
766                 internal delegate void SocketAsyncCall (SocketAsyncResult sar);
767
768                 /*
769                  *      These two fields are looked up by name by the runtime, don't change
770                  *  their name without also updating the runtime code.
771                  */
772                 private static int ipv4Supported = -1, ipv6Supported = -1;
773                 int linger_timeout;
774
775                 static Socket ()
776                 {
777                         // initialize ipv4Supported and ipv6Supported
778                         CheckProtocolSupport ();
779                 }
780
781                 internal static void CheckProtocolSupport ()
782                 {
783                         if(ipv4Supported == -1) {
784                                 try {
785                                         Socket tmp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
786                                         tmp.Close();
787
788                                         ipv4Supported = 1;
789                                 } catch {
790                                         ipv4Supported = 0;
791                                 }
792                         }
793
794                         if (ipv6Supported == -1) {
795 #if !NET_2_1
796 #if CONFIGURATION_DEP
797                                 SettingsSection config;
798                                 config = (SettingsSection) System.Configuration.ConfigurationManager.GetSection ("system.net/settings");
799                                 if (config != null)
800                                         ipv6Supported = config.Ipv6.Enabled ? -1 : 0;
801 #else
802                                 NetConfig config = System.Configuration.ConfigurationSettings.GetConfig("system.net/settings") as NetConfig;
803                                 if (config != null)
804                                         ipv6Supported = config.ipv6Enabled ? -1 : 0;
805 #endif
806 #endif
807                                 if (ipv6Supported != 0) {
808                                         try {
809                                                 Socket tmp = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
810                                                 tmp.Close();
811
812                                                 ipv6Supported = 1;
813                                         } catch {
814                                                 ipv6Supported = 0;
815                                         }
816                                 }
817                         }
818                 }
819
820                 public static bool SupportsIPv4 {
821                         get {
822                                 CheckProtocolSupport();
823                                 return ipv4Supported == 1;
824                         }
825                 }
826
827                 [ObsoleteAttribute ("Use OSSupportsIPv6 instead")]
828                 public static bool SupportsIPv6 {
829                         get {
830                                 CheckProtocolSupport();
831                                 return ipv6Supported == 1;
832                         }
833                 }
834 #if NET_2_1
835                 public static bool OSSupportsIPv4 {
836                         get {
837                                 CheckProtocolSupport();
838                                 return ipv4Supported == 1;
839                         }
840                 }
841 #endif
842 #if NET_2_1
843                 public static bool OSSupportsIPv6 {
844                         get {
845                                 CheckProtocolSupport();
846                                 return ipv6Supported == 1;
847                         }
848                 }
849 #else
850                 public static bool OSSupportsIPv6 {
851                         get {
852                                 NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces ();
853                                 
854                                 foreach (NetworkInterface adapter in nics) {
855                                         if (adapter.Supports (NetworkInterfaceComponent.IPv6))
856                                                 return true;
857                                 }
858                                 return false;
859                         }
860                 }
861 #endif
862
863                 /* the field "socket" is looked up by name by the runtime */
864                 private IntPtr socket;
865                 private AddressFamily address_family;
866                 private SocketType socket_type;
867                 private ProtocolType protocol_type;
868                 internal bool blocking=true;
869                 List<Thread> blocking_threads;
870                 private bool isbound;
871                 /* When true, the socket was connected at the time of
872                  * the last IO operation
873                  */
874                 private bool connected;
875                 /* true if we called Close_internal */
876                 private bool closed;
877                 internal bool disposed;
878                 bool connect_in_progress;
879
880                 /*
881                  * This EndPoint is used when creating new endpoints. Because
882                  * there are many types of EndPoints possible,
883                  * seed_endpoint.Create(addr) is used for creating new ones.
884                  * As such, this value is set on Bind, SentTo, ReceiveFrom,
885                  * Connect, etc.
886                  */
887                 internal EndPoint seed_endpoint = null;
888
889                 void RegisterForBlockingSyscall ()
890                 {
891                         while (blocking_threads == null) {
892                                 //In the rare event this CAS fail, there's a good chance other thread won, so we're kosher.
893                                 //In the VERY rare event of all CAS fail together, we pay the full price of of failure.
894                                 Interlocked.CompareExchange (ref blocking_threads, new List<Thread> (), null);
895                         }
896
897                         try {
898                                 
899                         } finally {
900                                 /* We must use a finally block here to make this atomic. */
901                                 lock (blocking_threads) {
902                                         blocking_threads.Add (Thread.CurrentThread);
903                                 }
904                         }
905                 }
906
907                 /* This must be called from a finally block! */
908                 void UnRegisterForBlockingSyscall ()
909                 {
910                         //If this NRE, we're in deep problems because Register Must have
911                         lock (blocking_threads) {
912                                 blocking_threads.Remove (Thread.CurrentThread);
913                         }
914                 }
915
916                 void AbortRegisteredThreads () {
917                         if (blocking_threads == null)
918                                 return;
919
920                         lock (blocking_threads) {
921                                 foreach (var t in blocking_threads)
922                                         cancel_blocking_socket_operation (t);
923                                 blocking_threads.Clear ();
924                         }
925                 }
926
927 #if !TARGET_JVM
928                 // Creates a new system socket, returning the handle
929                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
930                 private extern IntPtr Socket_internal(AddressFamily family,
931                                                       SocketType type,
932                                                       ProtocolType proto,
933                                                       out int error);
934 #endif          
935                 
936                 public Socket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)
937                 {
938 #if NET_2_1 && !MOBILE
939                         switch (addressFamily) {
940                         case AddressFamily.InterNetwork:        // ok
941                         case AddressFamily.InterNetworkV6:      // ok
942                         case AddressFamily.Unknown:             // SocketException will be thrown later (with right error #)
943                                 break;
944                         // case AddressFamily.Unspecified:
945                         default:
946                                 throw new ArgumentException ("addressFamily");
947                         }
948
949                         switch (socketType) {
950                         case SocketType.Stream:                 // ok
951                         case SocketType.Unknown:                // SocketException will be thrown later (with right error #)
952                                 break;
953                         default:
954                                 throw new ArgumentException ("socketType");
955                         }
956
957                         switch (protocolType) {
958                         case ProtocolType.Tcp:                  // ok
959                         case ProtocolType.Unspecified:          // ok
960                         case ProtocolType.Unknown:              // SocketException will be thrown later (with right error #)
961                                 break;
962                         default:
963                                 throw new ArgumentException ("protocolType");
964                         }
965 #endif
966                         address_family = addressFamily;
967                         socket_type = socketType;
968                         protocol_type = protocolType;
969                         
970                         int error;
971                         
972                         socket = Socket_internal (addressFamily, socketType, protocolType, out error);
973                         if (error != 0)
974                                 throw new SocketException (error);
975 #if !NET_2_1 || MOBILE
976                         SocketDefaults ();
977 #endif
978                 }
979
980                 ~Socket ()
981                 {
982                         Dispose (false);
983                 }
984
985
986                 public AddressFamily AddressFamily {
987                         get { return address_family; }
988                 }
989
990 #if !TARGET_JVM
991                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
992                 private extern static void Blocking_internal(IntPtr socket,
993                                                              bool block,
994                                                              out int error);
995 #endif
996
997                 public bool Blocking {
998                         get {
999                                 return(blocking);
1000                         }
1001                         set {
1002                                 if (disposed && closed)
1003                                         throw new ObjectDisposedException (GetType ().ToString ());
1004
1005                                 int error;
1006                                 
1007                                 Blocking_internal (socket, value, out error);
1008
1009                                 if (error != 0)
1010                                         throw new SocketException (error);
1011                                 
1012                                 blocking=value;
1013                         }
1014                 }
1015
1016                 public bool Connected {
1017                         get { return connected; }
1018                         internal set { connected = value; }
1019                 }
1020
1021                 public ProtocolType ProtocolType {
1022                         get { return protocol_type; }
1023                 }
1024
1025                 public bool NoDelay {
1026                         get {
1027                                 if (disposed && closed)
1028                                         throw new ObjectDisposedException (GetType ().ToString ());
1029
1030                                 ThrowIfUpd ();
1031
1032                                 return (int)(GetSocketOption (
1033                                         SocketOptionLevel.Tcp,
1034                                         SocketOptionName.NoDelay)) != 0;
1035                         }
1036
1037                         set {
1038                                 if (disposed && closed)
1039                                         throw new ObjectDisposedException (GetType ().ToString ());
1040
1041                                 ThrowIfUpd ();
1042
1043                                 SetSocketOption (
1044                                         SocketOptionLevel.Tcp,
1045                                         SocketOptionName.NoDelay, value ? 1 : 0);
1046                         }
1047                 }
1048
1049                 public int ReceiveBufferSize {
1050                         get {
1051                                 if (disposed && closed) {
1052                                         throw new ObjectDisposedException (GetType ().ToString ());
1053                                 }
1054                                 return((int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer));
1055                         }
1056                         set {
1057                                 if (disposed && closed) {
1058                                         throw new ObjectDisposedException (GetType ().ToString ());
1059                                 }
1060                                 if (value < 0) {
1061                                         throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
1062                                 }
1063                                 
1064                                 SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, value);
1065                         }
1066                 }
1067
1068                 public int SendBufferSize {
1069                         get {
1070                                 if (disposed && closed) {
1071                                         throw new ObjectDisposedException (GetType ().ToString ());
1072                                 }
1073                                 return((int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendBuffer));
1074                         }
1075                         set {
1076                                 if (disposed && closed) {
1077                                         throw new ObjectDisposedException (GetType ().ToString ());
1078                                 }
1079                                 if (value < 0) {
1080                                         throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
1081                                 }
1082                                 
1083                                 SetSocketOption (SocketOptionLevel.Socket,
1084                                                  SocketOptionName.SendBuffer,
1085                                                  value);
1086                         }
1087                 }
1088
1089                 public short Ttl {
1090                         get {
1091                                 if (disposed && closed) {
1092                                         throw new ObjectDisposedException (GetType ().ToString ());
1093                                 }
1094                                 
1095                                 short ttl_val;
1096                                 
1097                                 if (address_family == AddressFamily.InterNetwork) {
1098                                         ttl_val = (short)((int)GetSocketOption (SocketOptionLevel.IP, SocketOptionName.IpTimeToLive));
1099                                 } else if (address_family == AddressFamily.InterNetworkV6) {
1100                                         ttl_val = (short)((int)GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.HopLimit));
1101                                 } else {
1102                                         throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
1103                                 }
1104                                 
1105                                 return(ttl_val);
1106                         }
1107                         set {
1108                                 if (disposed && closed) {
1109                                         throw new ObjectDisposedException (GetType ().ToString ());
1110                                 }
1111                                 if (value < 0) {
1112                                         throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
1113                                 }
1114                                 
1115                                 if (address_family == AddressFamily.InterNetwork) {
1116                                         SetSocketOption (SocketOptionLevel.IP, SocketOptionName.IpTimeToLive, value);
1117                                 } else if (address_family == AddressFamily.InterNetworkV6) {
1118                                         SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.HopLimit, value);
1119                                 } else {
1120                                         throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
1121                                 }
1122                         }
1123                 }
1124
1125                 // Returns the remote endpoint details in addr and port
1126                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1127                 private extern static SocketAddress RemoteEndPoint_internal(IntPtr socket, int family, out int error);
1128
1129                 public EndPoint RemoteEndPoint {
1130                         get {
1131                                 if (disposed && closed)
1132                                         throw new ObjectDisposedException (GetType ().ToString ());
1133                                 
1134 #if MOONLIGHT
1135                                 if (!connected)
1136                                         return seed_endpoint;
1137 #else
1138                                 /*
1139                                  * If the seed EndPoint is null, Connect, Bind,
1140                                  * etc has not yet been called. MS returns null
1141                                  * in this case.
1142                                  */
1143                                 if (!connected || seed_endpoint == null)
1144                                         return null;
1145 #endif                  
1146                                 SocketAddress sa;
1147                                 int error;
1148                                 
1149                                 sa=RemoteEndPoint_internal(socket, (int) address_family, out error);
1150
1151                                 if (error != 0)
1152                                         throw new SocketException (error);
1153
1154                                 return seed_endpoint.Create (sa);
1155                         }
1156                 }
1157
1158                 void Linger (IntPtr handle)
1159                 {
1160                         if (!connected || linger_timeout <= 0)
1161                                 return;
1162
1163                         // We don't want to receive any more data
1164                         int error;
1165                         Shutdown_internal (handle, SocketShutdown.Receive, out error);
1166                         if (error != 0)
1167                                 return;
1168
1169                         int seconds = linger_timeout / 1000;
1170                         int ms = linger_timeout % 1000;
1171                         if (ms > 0) {
1172                                 // If the other end closes, this will return 'true' with 'Available' == 0
1173                                 Poll_internal (handle, SelectMode.SelectRead, ms * 1000, out error);
1174                                 if (error != 0)
1175                                         return;
1176
1177                         }
1178                         if (seconds > 0) {
1179                                 LingerOption linger = new LingerOption (true, seconds);
1180                                 SetSocketOption_internal (handle, SocketOptionLevel.Socket, SocketOptionName.Linger, linger, null, 0, out error);
1181                                 /* Not needed, we're closing upon return */
1182                                 /*if (error != 0)
1183                                         return; */
1184                         }
1185                 }
1186                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1187                 static extern void cancel_blocking_socket_operation (Thread thread);
1188
1189                 protected virtual void Dispose (bool disposing)
1190                 {
1191                         if (disposed)
1192                                 return;
1193
1194                         disposed = true;
1195                         bool was_connected = connected;
1196                         connected = false;
1197                         if ((int) socket != -1) {
1198                                 int error;
1199                                 closed = true;
1200                                 IntPtr x = socket;
1201                                 socket = (IntPtr) (-1);
1202                                 
1203                                 AbortRegisteredThreads ();
1204
1205                                 if (was_connected)
1206                                         Linger (x);
1207                                 //DateTime start = DateTime.UtcNow;
1208                                 Close_internal (x, out error);
1209                                 //Console.WriteLine ("Time spent in Close_internal: {0}ms", (DateTime.UtcNow - start).TotalMilliseconds);
1210                                 if (error != 0)
1211                                         throw new SocketException (error);
1212                         }
1213                 }
1214
1215 #if NET_2_1 || NET_4_0
1216                 public void Dispose ()
1217 #else
1218                 void IDisposable.Dispose ()
1219 #endif
1220                 {
1221                         Dispose (true);
1222                         GC.SuppressFinalize (this);
1223                 }
1224
1225                 // Closes the socket
1226                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1227                 private extern static void Close_internal(IntPtr socket, out int error);
1228
1229                 public void Close ()
1230                 {
1231                         linger_timeout = 0;
1232                         ((IDisposable) this).Dispose ();
1233                 }
1234
1235                 public void Close (int timeout) 
1236                 {
1237                         linger_timeout = timeout;
1238                         ((IDisposable) this).Dispose ();
1239                 }
1240
1241                 // Connects to the remote address
1242                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1243                 private extern static void Connect_internal(IntPtr sock,
1244                                                             SocketAddress sa,
1245                                                             out int error);
1246
1247                 public void Connect (EndPoint remoteEP)
1248                 {
1249                         SocketAddress serial = null;
1250
1251                         if (disposed && closed)
1252                                 throw new ObjectDisposedException (GetType ().ToString ());
1253
1254                         if (remoteEP == null)
1255                                 throw new ArgumentNullException ("remoteEP");
1256
1257                         IPEndPoint ep = remoteEP as IPEndPoint;
1258 #if !MOONLIGHT
1259                         if (ep != null && socket_type != SocketType.Dgram) /* Dgram uses Any to 'disconnect' */
1260 #else
1261                         if (ep != null)
1262 #endif
1263                                 if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any))
1264                                         throw new SocketException ((int) SocketError.AddressNotAvailable);
1265
1266 #if MOONLIGHT
1267                         if (protocol_type != ProtocolType.Tcp)
1268                                 throw new SocketException ((int) SocketError.AccessDenied);
1269 #else
1270                         if (islistening)
1271                                 throw new InvalidOperationException ();
1272 #endif
1273                         serial = remoteEP.Serialize ();
1274
1275                         int error = 0;
1276
1277                         try {
1278                                 RegisterForBlockingSyscall ();
1279                                 Connect_internal (socket, serial, out error);
1280                         } finally {
1281                                 UnRegisterForBlockingSyscall ();
1282                         }
1283
1284                         if (error == 0 || error == 10035)
1285                                 seed_endpoint = remoteEP; // Keep the ep around for non-blocking sockets
1286
1287                         if (error != 0) {
1288                                 if (closed)
1289                                         error = SOCKET_CLOSED;
1290                                 throw new SocketException (error);
1291                         }
1292
1293 #if !MOONLIGHT
1294                         if (socket_type == SocketType.Dgram && (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)))
1295                                 connected = false;
1296                         else
1297                                 connected = true;
1298 #else
1299                         connected = true;
1300 #endif
1301                         isbound = true;
1302                 }
1303
1304                 public bool ReceiveAsync (SocketAsyncEventArgs e)
1305                 {
1306                         // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1307                         if (disposed && closed)
1308                                 throw new ObjectDisposedException (GetType ().ToString ());
1309
1310                         // LAME SPEC: the ArgumentException is never thrown, instead an NRE is
1311                         // thrown when e.Buffer and e.BufferList are null (works fine when one is
1312                         // set to a valid object)
1313                         if (e.Buffer == null && e.BufferList == null)
1314                                 throw new NullReferenceException ("Either e.Buffer or e.BufferList must be valid buffers.");
1315
1316                         e.curSocket = this;
1317                         SocketOperation op = (e.Buffer != null) ? SocketOperation.Receive : SocketOperation.ReceiveGeneric;
1318                         e.Worker.Init (this, e, op);
1319                         SocketAsyncResult res = e.Worker.result;
1320                         if (e.Buffer != null) {
1321                                 res.Buffer = e.Buffer;
1322                                 res.Offset = e.Offset;
1323                                 res.Size = e.Count;
1324                         } else {
1325                                 res.Buffers = e.BufferList;
1326                         }
1327                         res.SockFlags = e.SocketFlags;
1328                         int count;
1329                         lock (readQ) {
1330                                 readQ.Enqueue (e.Worker);
1331                                 count = readQ.Count;
1332                         }
1333                         if (count == 1) {
1334                                 // Receive takes care of ReceiveGeneric
1335                                 socket_pool_queue (Worker.Dispatcher, res);
1336                         }
1337
1338                         return true;
1339                 }
1340
1341                 public bool SendAsync (SocketAsyncEventArgs e)
1342                 {
1343                         // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1344                         if (disposed && closed)
1345                                 throw new ObjectDisposedException (GetType ().ToString ());
1346                         if (e.Buffer == null && e.BufferList == null)
1347                                 throw new NullReferenceException ("Either e.Buffer or e.BufferList must be valid buffers.");
1348
1349                         e.curSocket = this;
1350                         SocketOperation op = (e.Buffer != null) ? SocketOperation.Send : SocketOperation.SendGeneric;
1351                         e.Worker.Init (this, e, op);
1352                         SocketAsyncResult res = e.Worker.result;
1353                         if (e.Buffer != null) {
1354                                 res.Buffer = e.Buffer;
1355                                 res.Offset = e.Offset;
1356                                 res.Size = e.Count;
1357                         } else {
1358                                 res.Buffers = e.BufferList;
1359                         }
1360                         res.SockFlags = e.SocketFlags;
1361                         int count;
1362                         lock (writeQ) {
1363                                 writeQ.Enqueue (e.Worker);
1364                                 count = writeQ.Count;
1365                         }
1366                         if (count == 1) {
1367                                 // Send takes care of SendGeneric
1368                                 socket_pool_queue (Worker.Dispatcher, res);
1369                         }
1370                         return true;
1371                 }
1372
1373                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1374                 extern static bool Poll_internal (IntPtr socket, SelectMode mode, int timeout, out int error);
1375
1376                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1377                 private extern static int Receive_internal(IntPtr sock,
1378                                                            byte[] buffer,
1379                                                            int offset,
1380                                                            int count,
1381                                                            SocketFlags flags,
1382                                                            out int error);
1383
1384                 internal int Receive_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
1385                 {
1386                         int nativeError;
1387                         int ret = Receive_internal (socket, buf, offset, size, flags, out nativeError);
1388                         error = (SocketError) nativeError;
1389                         if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress) {
1390                                 connected = false;
1391                                 isbound = false;
1392                         } else {
1393                                 connected = true;
1394                         }
1395                         
1396                         return ret;
1397                 }
1398
1399                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1400                 private extern static void GetSocketOption_obj_internal(IntPtr socket,
1401                         SocketOptionLevel level, SocketOptionName name, out object obj_val,
1402                         out int error);
1403
1404                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1405                 private extern static int Send_internal(IntPtr sock,
1406                                                         byte[] buf, int offset,
1407                                                         int count,
1408                                                         SocketFlags flags,
1409                                                         out int error);
1410
1411                 internal int Send_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
1412                 {
1413                         if (size == 0) {
1414                                 error = SocketError.Success;
1415                                 return 0;
1416                         }
1417
1418                         int nativeError;
1419
1420                         int ret = Send_internal (socket, buf, offset, size, flags, out nativeError);
1421
1422                         error = (SocketError)nativeError;
1423
1424                         if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress) {
1425                                 connected = false;
1426                                 isbound = false;
1427                         } else {
1428                                 connected = true;
1429                         }
1430
1431                         return ret;
1432                 }
1433
1434                 public object GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName)
1435                 {
1436                         if (disposed && closed)
1437                                 throw new ObjectDisposedException (GetType ().ToString ());
1438
1439                         object obj_val;
1440                         int error;
1441
1442                         GetSocketOption_obj_internal (socket, optionLevel, optionName, out obj_val,
1443                                 out error);
1444                         if (error != 0)
1445                                 throw new SocketException (error);
1446
1447                         if (optionName == SocketOptionName.Linger) {
1448                                 return((LingerOption)obj_val);
1449                         } else if (optionName == SocketOptionName.AddMembership ||
1450                                    optionName == SocketOptionName.DropMembership) {
1451                                 return((MulticastOption)obj_val);
1452                         } else if (obj_val is int) {
1453                                 return((int)obj_val);
1454                         } else {
1455                                 return(obj_val);
1456                         }
1457                 }
1458
1459                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
1460                 private extern static void Shutdown_internal (IntPtr socket, SocketShutdown how, out int error);
1461                 
1462                 public void Shutdown (SocketShutdown how)
1463                 {
1464                         if (disposed && closed)
1465                                 throw new ObjectDisposedException (GetType ().ToString ());
1466
1467                         if (!connected)
1468                                 throw new SocketException (10057); // Not connected
1469
1470                         int error;
1471                         
1472                         Shutdown_internal (socket, how, out error);
1473                         if (error != 0)
1474                                 throw new SocketException (error);
1475                 }
1476
1477                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1478                 private extern static void SetSocketOption_internal (IntPtr socket, SocketOptionLevel level,
1479                                                                      SocketOptionName name, object obj_val,
1480                                                                      byte [] byte_val, int int_val,
1481                                                                      out int error);
1482
1483                 public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int optionValue)
1484                 {
1485                         if (disposed && closed)
1486                                 throw new ObjectDisposedException (GetType ().ToString ());
1487
1488                         int error;
1489
1490                         SetSocketOption_internal (socket, optionLevel, optionName, null,
1491                                                  null, optionValue, out error);
1492
1493                         if (error != 0)
1494                                 throw new SocketException (error);
1495                 }
1496
1497                 private void ThrowIfUpd ()
1498                 {
1499 #if !NET_2_1 || MOBILE
1500                         if (protocol_type == ProtocolType.Udp)
1501                                 throw new SocketException ((int)SocketError.ProtocolOption);
1502 #endif
1503                 }
1504
1505 #if !MOONLIGHT
1506                 public
1507 #endif
1508                 IAsyncResult BeginConnect(EndPoint end_point, AsyncCallback callback, object state)
1509                 {
1510                         if (disposed && closed)
1511                                 throw new ObjectDisposedException (GetType ().ToString ());
1512
1513                         if (end_point == null)
1514                                 throw new ArgumentNullException ("end_point");
1515
1516                         SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Connect);
1517                         req.EndPoint = end_point;
1518
1519                         // Bug #75154: Connect() should not succeed for .Any addresses.
1520                         if (end_point is IPEndPoint) {
1521                                 IPEndPoint ep = (IPEndPoint) end_point;
1522                                 if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)) {
1523                                         req.Complete (new SocketException ((int) SocketError.AddressNotAvailable), true);
1524                                         return req;
1525                                 }
1526                         }
1527
1528                         int error = 0;
1529                         if (connect_in_progress) {
1530                                 // This could happen when multiple IPs are used
1531                                 // Calling connect() again will reset the connection attempt and cause
1532                                 // an error. Better to just close the socket and move on.
1533                                 connect_in_progress = false;
1534                                 Close_internal (socket, out error);
1535                                 socket = Socket_internal (address_family, socket_type, protocol_type, out error);
1536                                 if (error != 0)
1537                                         throw new SocketException (error);
1538                         }
1539                         bool blk = blocking;
1540                         if (blk)
1541                                 Blocking = false;
1542                         SocketAddress serial = end_point.Serialize ();
1543                         Connect_internal (socket, serial, out error);
1544                         if (blk)
1545                                 Blocking = true;
1546                         if (error == 0) {
1547                                 // succeeded synch
1548                                 connected = true;
1549                                 isbound = true;
1550                                 req.Complete (true);
1551                                 return req;
1552                         }
1553
1554                         if (error != (int) SocketError.InProgress && error != (int) SocketError.WouldBlock) {
1555                                 // error synch
1556                                 connected = false;
1557                                 isbound = false;
1558                                 req.Complete (new SocketException (error), true);
1559                                 return req;
1560                         }
1561
1562                         // continue asynch
1563                         connected = false;
1564                         isbound = false;
1565                         connect_in_progress = true;
1566                         socket_pool_queue (Worker.Dispatcher, req);
1567                         return req;
1568                 }
1569
1570 #if !MOONLIGHT
1571                 public
1572 #else
1573                 internal
1574 #endif
1575                 IAsyncResult BeginConnect (IPAddress[] addresses, int port, AsyncCallback callback, object state)
1576
1577                 {
1578                         if (disposed && closed)
1579                                 throw new ObjectDisposedException (GetType ().ToString ());
1580
1581                         if (addresses == null)
1582                                 throw new ArgumentNullException ("addresses");
1583
1584                         if (addresses.Length == 0)
1585                                 throw new ArgumentException ("Empty addresses list");
1586
1587                         if (this.AddressFamily != AddressFamily.InterNetwork &&
1588                                 this.AddressFamily != AddressFamily.InterNetworkV6)
1589                                 throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
1590
1591                         if (port <= 0 || port > 65535)
1592                                 throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
1593 #if !MOONLIGHT
1594                         if (islistening)
1595                                 throw new InvalidOperationException ();
1596 #endif
1597
1598                         SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Connect);
1599                         req.Addresses = addresses;
1600                         req.Port = port;
1601                         connected = false;
1602                         return BeginMConnect (req);
1603                 }
1604
1605                 IAsyncResult BeginMConnect (SocketAsyncResult req)
1606                 {
1607                         IAsyncResult ares = null;
1608                         Exception exc = null;
1609                         for (int i = req.CurrentAddress; i < req.Addresses.Length; i++) {
1610                                 IPAddress addr = req.Addresses [i];
1611                                 IPEndPoint ep = new IPEndPoint (addr, req.Port);
1612                                 try {
1613                                         req.CurrentAddress++;
1614                                         ares = BeginConnect (ep, null, req);
1615                                         if (ares.IsCompleted && ares.CompletedSynchronously) {
1616                                                 ((SocketAsyncResult) ares).CheckIfThrowDelayedException ();
1617                                                 req.DoMConnectCallback ();
1618                                         }
1619                                         break;
1620                                 } catch (Exception e) {
1621                                         exc = e;
1622                                         ares = null;
1623                                 }
1624                         }
1625
1626                         if (ares == null)
1627                                 throw exc;
1628
1629                         return req;
1630                 }
1631
1632                 // Returns false when it is ok to use RemoteEndPoint
1633                 //         true when addresses must be used (and addresses could be null/empty)
1634                 bool GetCheckedIPs (SocketAsyncEventArgs e, out IPAddress [] addresses)
1635                 {
1636                         addresses = null;
1637 #if MOONLIGHT || NET_4_0
1638                         // Connect to the first address that match the host name, like:
1639                         // http://blogs.msdn.com/ncl/archive/2009/07/20/new-ncl-features-in-net-4-0-beta-2.aspx
1640                         // while skipping entries that do not match the address family
1641                         DnsEndPoint dep = (e.RemoteEndPoint as DnsEndPoint);
1642                         if (dep != null) {
1643                                 addresses = Dns.GetHostAddresses (dep.Host);
1644 #if MOONLIGHT && !INSIDE_SYSTEM
1645                                 if (!e.PolicyRestricted && !SecurityManager.HasElevatedPermissions) {
1646                                         List<IPAddress> valid = new List<IPAddress> ();
1647                                         foreach (IPAddress a in addresses) {
1648                                                 // if we're not downloading a socket policy then check the policy
1649                                                 // and if we're not running with elevated permissions (SL4 OoB option)
1650                                                 endpoint = new IPEndPoint (a, dep.Port);
1651                                                 if (!CrossDomainPolicyManager.CheckEndPoint (endpoint, e.SocketClientAccessPolicyProtocol))
1652                                                         continue;
1653                                                 valid.Add (a);
1654                                         }
1655                                         if (valid.Count == 0)
1656                                                 e.SocketError = SocketError.AccessDenied;
1657                                         addresses = valid.ToArray ();
1658                                 }
1659 #endif
1660                                 return true;
1661                         } else {
1662                                 e.ConnectByNameError = null;
1663 #if MOONLIGHT && !INSIDE_SYSTEM
1664                                 if (!e.PolicyRestricted && !SecurityManager.HasElevatedPermissions) {
1665                                         if (CrossDomainPolicyManager.CheckEndPoint (e.RemoteEndPoint, e.SocketClientAccessPolicyProtocol))
1666                                                 return false;
1667                                         else
1668                                                 e.SocketError = SocketError.AccessDenied;
1669                                 } else
1670 #endif
1671                                         return false;
1672                         }
1673 #else
1674                         return false; // < NET_4_0 -> use remote endpoint
1675 #endif
1676                 }
1677
1678                 bool ConnectAsyncReal (SocketAsyncEventArgs e)
1679                 {                       
1680                         bool use_remoteep = true;
1681 #if MOONLIGHT || NET_4_0
1682                         IPAddress [] addresses = null;
1683                         use_remoteep = !GetCheckedIPs (e, out addresses);
1684 #endif
1685 #if MOONLIGHT
1686                         bool policy_failed = (e.SocketError == SocketError.AccessDenied);
1687 #endif
1688                         e.curSocket = this;
1689                         Worker w = e.Worker;
1690                         w.Init (this, e, SocketOperation.Connect);
1691                         SocketAsyncResult result = w.result;
1692 #if MOONLIGHT
1693                         if (policy_failed) {
1694                                 // SocketAsyncEventArgs.Completed must be called
1695                                 connected = false;
1696                                 result.EndPoint = e.RemoteEndPoint;
1697                                 result.error = (int) SocketError.AccessDenied;
1698                                 result.Complete ();
1699                                 socket_pool_queue (Worker.Dispatcher, result);
1700                                 return true;
1701                         }
1702 #endif
1703                         IAsyncResult ares = null;
1704                         try {
1705                                 if (use_remoteep) {
1706                                         result.EndPoint = e.RemoteEndPoint;
1707                                         ares = BeginConnect (e.RemoteEndPoint, SocketAsyncEventArgs.Dispatcher, e);
1708                                 }
1709 #if MOONLIGHT || NET_4_0
1710                                 else {
1711
1712                                         DnsEndPoint dep = (e.RemoteEndPoint as DnsEndPoint);
1713                                         result.Addresses = addresses;
1714                                         result.Port = dep.Port;
1715
1716                                         ares = BeginConnect (addresses, dep.Port, SocketAsyncEventArgs.Dispatcher, e);
1717                                 }
1718 #endif
1719                                 if (ares.IsCompleted && ares.CompletedSynchronously) {
1720                                         ((SocketAsyncResult) ares).CheckIfThrowDelayedException ();
1721                                         return false;
1722                                 }
1723                         } catch (Exception exc) {
1724                                 result.Complete (exc, true);
1725                                 return false;
1726                         }
1727                         return true;
1728                 }
1729
1730 #if !MOONLIGHT
1731                 public bool ConnectAsync (SocketAsyncEventArgs e)
1732                 {
1733                         // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1734                         if (disposed && closed)
1735                                 throw new ObjectDisposedException (GetType ().ToString ());
1736                         if (islistening)
1737                                 throw new InvalidOperationException ("You may not perform this operation after calling the Listen method.");
1738                         if (e.RemoteEndPoint == null)
1739                                 throw new ArgumentNullException ("remoteEP");
1740
1741                         return ConnectAsyncReal (e);
1742                 }
1743 #endif
1744 #if MOONLIGHT
1745                 static void CheckConnect (SocketAsyncEventArgs e)
1746                 {
1747                         // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1748
1749                         if (e.RemoteEndPoint == null)
1750                                 throw new ArgumentNullException ("remoteEP");
1751                         if (e.BufferList != null)
1752                                 throw new ArgumentException ("Multiple buffers cannot be used with this method.");
1753                 }
1754
1755                 public bool ConnectAsync (SocketAsyncEventArgs e)
1756                 {
1757                         if (disposed && closed)
1758                                 throw new ObjectDisposedException (GetType ().ToString ());
1759
1760                         CheckConnect (e);
1761                         // if an address family is specified then they must match
1762                         AddressFamily raf = e.RemoteEndPoint.AddressFamily;
1763                         if ((raf != AddressFamily.Unspecified) && (raf != AddressFamily))
1764                                 throw new NotSupportedException ("AddressFamily mismatch between socket and endpoint");
1765
1766                         // connected, not yet connected or even policy denied, the Socket.RemoteEndPoint is always 
1767                         // available after the ConnectAsync call
1768                         seed_endpoint = e.RemoteEndPoint;
1769                         return ConnectAsyncReal (e);
1770                 }
1771
1772                 public static bool ConnectAsync (SocketType socketType, ProtocolType protocolType, SocketAsyncEventArgs e)
1773                 {
1774                         // exception ordering requires to check before creating the socket (good thing resource wise too)
1775                         CheckConnect (e);
1776
1777                         // create socket based on the endpoint address family (if specified), otherwise default fo IPv4
1778                         AddressFamily raf = e.RemoteEndPoint.AddressFamily;
1779                         if (raf == AddressFamily.Unspecified)
1780                                 raf = AddressFamily.InterNetwork;
1781                         Socket s = new Socket (raf, socketType, protocolType);
1782                         return s.ConnectAsyncReal (e);
1783                 }
1784
1785                 public static void CancelConnectAsync (SocketAsyncEventArgs e)
1786                 {
1787                         if (e == null)
1788                                 throw new ArgumentNullException ("e");
1789
1790                         // FIXME: this is canceling a synchronous connect, not an async one
1791                         Socket s = e.ConnectSocket;
1792                         if (s != null)
1793                                 s.AbortRegisteredThreads ();
1794                 }
1795 #endif
1796                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
1797                 private extern static int Receive_internal (IntPtr sock, WSABUF[] bufarray, SocketFlags flags, out int error);
1798 #if !MOONLIGHT
1799                 public
1800 #else
1801                 internal
1802 #endif
1803                 int Receive (IList<ArraySegment<byte>> buffers)
1804                 {
1805                         int ret;
1806                         SocketError error;
1807                         ret = Receive (buffers, SocketFlags.None, out error);
1808                         if (error != SocketError.Success) {
1809                                 throw new SocketException ((int)error);
1810                         }
1811                         return(ret);
1812                 }
1813
1814                 [CLSCompliant (false)]
1815 #if !MOONLIGHT
1816                 public
1817 #else
1818                 internal
1819 #endif
1820                 int Receive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags)
1821                 {
1822                         int ret;
1823                         SocketError error;
1824                         ret = Receive (buffers, socketFlags, out error);
1825                         if (error != SocketError.Success) {
1826                                 throw new SocketException ((int)error);
1827                         }
1828                         return(ret);
1829                 }
1830
1831                 [CLSCompliant (false)]
1832 #if !MOONLIGHT
1833                 public
1834 #else
1835                 internal
1836 #endif
1837                 int Receive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode)
1838                 {
1839                         if (disposed && closed)
1840                                 throw new ObjectDisposedException (GetType ().ToString ());
1841
1842                         if (buffers == null ||
1843                             buffers.Count == 0) {
1844                                 throw new ArgumentNullException ("buffers");
1845                         }
1846
1847                         int numsegments = buffers.Count;
1848                         int nativeError;
1849                         int ret;
1850
1851                         /* Only example I can find of sending a byte
1852                          * array reference directly into an internal
1853                          * call is in
1854                          * System.Runtime.Remoting/System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeSocket.cs,
1855                          * so taking a lead from that...
1856                          */
1857                         WSABUF[] bufarray = new WSABUF[numsegments];
1858                         GCHandle[] gch = new GCHandle[numsegments];
1859
1860                         for(int i = 0; i < numsegments; i++) {
1861                                 ArraySegment<byte> segment = buffers[i];
1862
1863                                 if (segment.Offset < 0 || segment.Count < 0 ||
1864                                     segment.Count > segment.Array.Length - segment.Offset)
1865                                         throw new ArgumentOutOfRangeException ("segment");
1866
1867                                 gch[i] = GCHandle.Alloc (segment.Array, GCHandleType.Pinned);
1868                                 bufarray[i].len = segment.Count;
1869                                 bufarray[i].buf = Marshal.UnsafeAddrOfPinnedArrayElement (segment.Array, segment.Offset);
1870                         }
1871
1872                         try {
1873                                 ret = Receive_internal (socket, bufarray,
1874                                                         socketFlags,
1875                                                         out nativeError);
1876                         } finally {
1877                                 for(int i = 0; i < numsegments; i++) {
1878                                         if (gch[i].IsAllocated) {
1879                                                 gch[i].Free ();
1880                                         }
1881                                 }
1882                         }
1883
1884                         errorCode = (SocketError)nativeError;
1885                         return(ret);
1886                 }
1887
1888                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
1889                 private extern static int Send_internal (IntPtr sock, WSABUF[] bufarray, SocketFlags flags, out int error);
1890 #if !MOONLIGHT
1891                 public
1892 #else
1893                 internal
1894 #endif
1895                 int Send (IList<ArraySegment<byte>> buffers)
1896                 {
1897                         int ret;
1898                         SocketError error;
1899                         ret = Send (buffers, SocketFlags.None, out error);
1900                         if (error != SocketError.Success) {
1901                                 throw new SocketException ((int)error);
1902                         }
1903                         return(ret);
1904                 }
1905
1906 #if !MOONLIGHT
1907                 public
1908 #else
1909                 internal
1910 #endif
1911                 int Send (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags)
1912                 {
1913                         int ret;
1914                         SocketError error;
1915                         ret = Send (buffers, socketFlags, out error);
1916                         if (error != SocketError.Success) {
1917                                 throw new SocketException ((int)error);
1918                         }
1919                         return(ret);
1920                 }
1921
1922                 [CLSCompliant (false)]
1923 #if !MOONLIGHT
1924                 public
1925 #else
1926                 internal
1927 #endif
1928                 int Send (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode)
1929                 {
1930                         if (disposed && closed)
1931                                 throw new ObjectDisposedException (GetType ().ToString ());
1932                         if (buffers == null)
1933                                 throw new ArgumentNullException ("buffers");
1934                         if (buffers.Count == 0)
1935                                 throw new ArgumentException ("Buffer is empty", "buffers");
1936                         int numsegments = buffers.Count;
1937                         int nativeError;
1938                         int ret;
1939
1940                         WSABUF[] bufarray = new WSABUF[numsegments];
1941                         GCHandle[] gch = new GCHandle[numsegments];
1942                         for(int i = 0; i < numsegments; i++) {
1943                                 ArraySegment<byte> segment = buffers[i];
1944
1945                                 if (segment.Offset < 0 || segment.Count < 0 ||
1946                                     segment.Count > segment.Array.Length - segment.Offset)
1947                                         throw new ArgumentOutOfRangeException ("segment");
1948
1949                                 gch[i] = GCHandle.Alloc (segment.Array, GCHandleType.Pinned);
1950                                 bufarray[i].len = segment.Count;
1951                                 bufarray[i].buf = Marshal.UnsafeAddrOfPinnedArrayElement (segment.Array, segment.Offset);
1952                         }
1953
1954                         try {
1955                                 ret = Send_internal (socket, bufarray, socketFlags, out nativeError);
1956                         } finally {
1957                                 for(int i = 0; i < numsegments; i++) {
1958                                         if (gch[i].IsAllocated) {
1959                                                 gch[i].Free ();
1960                                         }
1961                                 }
1962                         }
1963                         errorCode = (SocketError)nativeError;
1964                         return(ret);
1965                 }
1966
1967                 Exception InvalidAsyncOp (string method)
1968                 {
1969                         return new InvalidOperationException (method + " can only be called once per asynchronous operation");
1970                 }
1971
1972 #if !MOONLIGHT
1973                 public
1974 #else
1975                 internal
1976 #endif
1977                 int EndReceive (IAsyncResult result)
1978                 {
1979                         SocketError error;
1980                         int bytesReceived = EndReceive (result, out error);
1981                         if (error != SocketError.Success) {
1982                                 if (error != SocketError.WouldBlock && error != SocketError.InProgress)
1983                                         connected = false;
1984                                 throw new SocketException ((int)error);
1985                         }
1986                         return bytesReceived;
1987                 }
1988
1989 #if !MOONLIGHT
1990                 public
1991 #else
1992                 internal
1993 #endif
1994                 int EndReceive (IAsyncResult asyncResult, out SocketError errorCode)
1995                 {
1996                         if (disposed && closed)
1997                                 throw new ObjectDisposedException (GetType ().ToString ());
1998
1999                         if (asyncResult == null)
2000                                 throw new ArgumentNullException ("asyncResult");
2001
2002                         SocketAsyncResult req = asyncResult as SocketAsyncResult;
2003                         if (req == null)
2004                                 throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
2005
2006                         if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
2007                                 throw InvalidAsyncOp ("EndReceive");
2008                         if (!asyncResult.IsCompleted)
2009                                 asyncResult.AsyncWaitHandle.WaitOne ();
2010
2011                         errorCode = req.ErrorCode;
2012                         // If no socket error occurred, call CheckIfThrowDelayedException in case there are other
2013                         // kinds of exceptions that should be thrown.
2014                         if (errorCode == SocketError.Success)
2015                                 req.CheckIfThrowDelayedException();
2016
2017                         return(req.Total);
2018                 }
2019
2020 #if !MOONLIGHT
2021                 public
2022 #else
2023                 internal
2024 #endif
2025                 int EndSend (IAsyncResult result)
2026                 {
2027                         SocketError error;
2028                         int bytesSent = EndSend (result, out error);
2029                         if (error != SocketError.Success) {
2030                                 if (error != SocketError.WouldBlock && error != SocketError.InProgress)
2031                                         connected = false;
2032                                 throw new SocketException ((int)error);
2033                         }
2034                         return bytesSent;
2035                 }
2036
2037 #if !MOONLIGHT
2038                 public
2039 #else
2040                 internal
2041 #endif
2042                 int EndSend (IAsyncResult asyncResult, out SocketError errorCode)
2043                 {
2044                         if (disposed && closed)
2045                                 throw new ObjectDisposedException (GetType ().ToString ());
2046                         if (asyncResult == null)
2047                                 throw new ArgumentNullException ("asyncResult");
2048
2049                         SocketAsyncResult req = asyncResult as SocketAsyncResult;
2050                         if (req == null)
2051                                 throw new ArgumentException ("Invalid IAsyncResult", "result");
2052
2053                         if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
2054                                 throw InvalidAsyncOp ("EndSend");
2055                         if (!asyncResult.IsCompleted)
2056                                 asyncResult.AsyncWaitHandle.WaitOne ();
2057
2058                         errorCode = req.ErrorCode;
2059                         // If no socket error occurred, call CheckIfThrowDelayedException in case there are other
2060                         // kinds of exceptions that should be thrown.
2061                         if (errorCode == SocketError.Success)
2062                                 req.CheckIfThrowDelayedException ();
2063
2064                         return(req.Total);
2065                 }
2066
2067                 // Used by Udpclient
2068 #if !MOONLIGHT
2069                 public
2070 #else
2071                 internal
2072 #endif
2073                 int EndReceiveFrom(IAsyncResult result, ref EndPoint end_point)
2074                 {
2075                         if (disposed && closed)
2076                                 throw new ObjectDisposedException (GetType ().ToString ());
2077
2078                         if (result == null)
2079                                 throw new ArgumentNullException ("result");
2080
2081                         if (end_point == null)
2082                                 throw new ArgumentNullException ("remote_end");
2083
2084                         SocketAsyncResult req = result as SocketAsyncResult;
2085                         if (req == null)
2086                                 throw new ArgumentException ("Invalid IAsyncResult", "result");
2087
2088                         if (Interlocked.CompareExchange (ref req.EndCalled, 1, 0) == 1)
2089                                 throw InvalidAsyncOp ("EndReceiveFrom");
2090                         if (!result.IsCompleted)
2091                                 result.AsyncWaitHandle.WaitOne();
2092
2093                         req.CheckIfThrowDelayedException();
2094                         end_point = req.EndPoint;
2095                         return req.Total;
2096                 }
2097
2098                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2099                 static extern void socket_pool_queue (SocketAsyncCall d, SocketAsyncResult r);
2100         }
2101 }
2102