Add support on Windows to install atexit handler(s) early in application’s startup.
[mono.git] / mcs / class / referencesource / System / net / System / Net / Sockets / Socket.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="Socket.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //------------------------------------------------------------------------------
6
7 #if MONO
8 #undef FEATURE_PAL
9 #endif
10
11 namespace System.Net.Sockets {
12     using System.Collections;
13     using System.Collections.Generic;
14     using System.Diagnostics;
15     using System.Globalization;
16     using System.IO;
17     using System.Net;
18     using System.Net.Configuration;
19     using System.Runtime.InteropServices;
20     using System.Security.Permissions;
21     using System.Threading;
22     using System.Runtime.Versioning;
23     using System.Diagnostics.Contracts;
24     using System.ComponentModel;
25
26     /// <devdoc>
27     /// <para>The <see cref='Sockets.Socket'/> class implements the Berkeley sockets
28     ///    interface.</para>
29     /// </devdoc>
30
31     public partial class Socket : IDisposable
32     {
33 #if !MONO
34         internal const int DefaultCloseTimeout = -1; // don't change for default, otherwise breaking change
35
36         // AcceptQueue - queued list of accept requests for BeginAccept or async Result for Begin Connect
37         private object m_AcceptQueueOrConnectResult;
38
39         // the following 8 members represent the state of the socket
40         private SafeCloseSocket  m_Handle;
41
42         // m_RightEndPoint is null if the socket has not been bound.  Otherwise, it is any EndPoint of the
43         // correct type (IPEndPoint, etc).
44         internal EndPoint   m_RightEndPoint;  
45         internal EndPoint    m_RemoteEndPoint;
46         // this flags monitor if the socket was ever connected at any time and if it still is.
47         private bool        m_IsConnected; //  = false;
48         private bool        m_IsDisconnected; //  = false;
49
50         // when the socket is created it will be in blocking mode
51         // we'll only be able to Accept or Connect, so we only need
52         // to handle one of these cases at a time
53         private bool        willBlock = true; // desired state of the socket for the user
54         private bool        willBlockInternal = true; // actual win32 state of the socket
55         private bool        isListening = false;
56
57         // Our internal state doesn't automatically get updated after a non-blocking connect
58         // completes.  Keep track of whether we're doing a non-blocking connect, and make sure
59         // to poll for the real state until we're done connecting.
60         private bool m_NonBlockingConnectInProgress;
61
62         // Keep track of the kind of endpoint used to do a non-blocking connect, so we can set
63         // it to m_RightEndPoint when we discover we're connected.
64         private EndPoint m_NonBlockingConnectRightEndPoint;
65
66         // These are constants initialized by constructor
67         private AddressFamily   addressFamily;
68         private SocketType      socketType;
69         private ProtocolType    protocolType;
70
71         // These caches are one degree off of Socket since they're not used in the [....] case/when disabled in config.
72         private CacheSet m_Caches;
73
74         private class CacheSet
75         {
76             internal CallbackClosure ConnectClosureCache;
77             internal CallbackClosure AcceptClosureCache;
78             internal CallbackClosure SendClosureCache;
79             internal CallbackClosure ReceiveClosureCache;
80
81             internal OverlappedCache SendOverlappedCache;
82             internal OverlappedCache ReceiveOverlappedCache;
83         }
84
85         //
86         // Overlapped constants.
87         //
88 #if !(FEATURE_PAL && !MONO) || CORIOLIS
89         internal static volatile bool UseOverlappedIO;
90 #else
91         // Disable the I/O completion port for Rotor
92         internal static volatile bool UseOverlappedIO = true;
93 #endif // !(FEATURE_PAL && !MONO) || CORIOLIS
94         private bool useOverlappedIO;
95
96         // Bool marked true if the native socket m_Handle was bound to the ThreadPool
97         private bool        m_BoundToThreadPool; // = false;
98
99         // Bool marked true if the native socket option IP_PKTINFO or IPV6_PKTINFO has been set
100         private bool m_ReceivingPacketInformation;
101
102         // Event used for async Connect/Accept calls
103         private ManualResetEvent m_AsyncEvent;
104         private RegisteredWaitHandle m_RegisteredWait;
105         private AsyncEventBits m_BlockEventBits = AsyncEventBits.FdNone;
106
107         //These members are to cache permission checks
108         private SocketAddress   m_PermittedRemoteAddress;
109
110         private DynamicWinsockMethods m_DynamicWinsockMethods;
111 #endif // !MONO
112
113         private static object s_InternalSyncObject;
114 #if !MONO
115         private int m_CloseTimeout = Socket.DefaultCloseTimeout;
116         private int m_IntCleanedUp;                 // 0 if not completed >0 otherwise.
117         private const int microcnv = 1000000;
118         private readonly static int protocolInformationSize = Marshal.SizeOf(typeof(UnsafeNclNativeMethods.OSSOCK.WSAPROTOCOL_INFO));
119 #endif // !MONO
120
121         internal static volatile bool s_SupportsIPv4;
122         internal static volatile bool s_SupportsIPv6;
123         internal static volatile bool s_OSSupportsIPv6;
124         internal static volatile bool s_Initialized;
125         private static volatile WaitOrTimerCallback s_RegisteredWaitCallback;
126         private static volatile bool s_LoggingEnabled;
127 #if !FEATURE_PAL // perfcounter
128         internal static volatile bool s_PerfCountersEnabled;
129 #endif
130
131 //************* constructors *************************
132
133         //------------------------------------
134
135         // Creates a Dual Mode socket for working with both IPv4 and IPv6
136         public Socket(SocketType socketType, ProtocolType protocolType)
137             : this(AddressFamily.InterNetworkV6, socketType, protocolType) {
138             DualMode = true;
139         }
140
141         /// <devdoc>
142         ///    <para>
143         ///       Initializes a new instance of the <see cref='Sockets.Socket'/> class.
144         ///    </para>
145         /// </devdoc>
146         public Socket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType) {
147             s_LoggingEnabled = Logging.On;
148             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "Socket", addressFamily);
149             InitializeSockets();
150
151 #if MONO
152             int error;
153             m_Handle = new SafeSocketHandle (Socket_internal (addressFamily, socketType, protocolType, out error), true);
154 #else
155             m_Handle = SafeCloseSocket.CreateWSASocket(
156                     addressFamily,
157                     socketType,
158                     protocolType);
159 #endif
160
161             if (m_Handle.IsInvalid) {
162                 //
163                 // failed to create the win32 socket, throw
164                 //
165                 throw new SocketException();
166             }
167
168             this.addressFamily = addressFamily;
169             this.socketType = socketType;
170             this.protocolType = protocolType;
171
172             IPProtectionLevel defaultProtectionLevel = SettingsSectionInternal.Section.IPProtectionLevel;
173             if (defaultProtectionLevel != IPProtectionLevel.Unspecified) {
174                 SetIPProtectionLevel(defaultProtectionLevel);
175             }
176
177 #if MONO
178             SocketDefaults ();
179 #endif
180
181             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "Socket", null);
182         }
183
184 #if !MONO
185         public Socket(SocketInformation socketInformation) {
186             s_LoggingEnabled = Logging.On;
187             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "Socket", addressFamily);
188
189             ExceptionHelper.UnrestrictedSocketPermission.Demand();
190
191             InitializeSockets();
192             if(socketInformation.ProtocolInformation == null || socketInformation.ProtocolInformation.Length < protocolInformationSize){
193                 throw new ArgumentException(SR.GetString(SR.net_sockets_invalid_socketinformation), "socketInformation.ProtocolInformation");
194             }
195
196             unsafe{
197                 fixed(byte * pinnedBuffer = socketInformation.ProtocolInformation){
198                     m_Handle = SafeCloseSocket.CreateWSASocket(pinnedBuffer);
199
200                     UnsafeNclNativeMethods.OSSOCK.WSAPROTOCOL_INFO protocolInfo = (UnsafeNclNativeMethods.OSSOCK.WSAPROTOCOL_INFO)Marshal.PtrToStructure((IntPtr)pinnedBuffer, typeof(UnsafeNclNativeMethods.OSSOCK.WSAPROTOCOL_INFO));
201                     addressFamily = protocolInfo.iAddressFamily;
202                     socketType = (SocketType)protocolInfo.iSocketType;
203                     protocolType = (ProtocolType)protocolInfo.iProtocol;
204                 }
205             }
206
207             if (m_Handle.IsInvalid) {
208                 SocketException e = new SocketException();
209                 if(e.ErrorCode == (int)SocketError.InvalidArgument){
210                     throw new ArgumentException(SR.GetString(SR.net_sockets_invalid_socketinformation), "socketInformation");
211                 }
212                 else {
213                     throw e;
214                 }
215             }
216
217             if (addressFamily != AddressFamily.InterNetwork && addressFamily != AddressFamily.InterNetworkV6) {
218                 throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
219             }
220
221             m_IsConnected = socketInformation.IsConnected;
222             willBlock = !socketInformation.IsNonBlocking;
223             InternalSetBlocking(willBlock);
224             isListening = socketInformation.IsListening;
225             UseOnlyOverlappedIO = socketInformation.UseOnlyOverlappedIO;
226
227
228             //are we bound?  if so, what's the local endpoint?
229
230             if (socketInformation.RemoteEndPoint != null) {
231                 m_RightEndPoint = socketInformation.RemoteEndPoint;
232                 m_RemoteEndPoint = socketInformation.RemoteEndPoint;
233             }
234             else {
235                 EndPoint ep = null;
236                 if (addressFamily == AddressFamily.InterNetwork ) {
237                     ep = IPEndPoint.Any;
238                 }
239                 else if(addressFamily == AddressFamily.InterNetworkV6) {
240                     ep = IPEndPoint.IPv6Any;
241                 }
242
243                 SocketAddress socketAddress = ep.Serialize();
244                 SocketError errorCode;
245                 try
246                 {
247                     errorCode = UnsafeNclNativeMethods.OSSOCK.getsockname(
248                         m_Handle,
249                         socketAddress.m_Buffer,
250                         ref socketAddress.m_Size);
251                 }
252                 catch (ObjectDisposedException)
253                 {
254                     errorCode = SocketError.NotSocket;
255                 }
256
257                 if (errorCode == SocketError.Success) {
258                     try {
259                         //we're bound
260                         m_RightEndPoint = ep.Create(socketAddress);
261                     }
262                     catch {
263                     }
264                 }
265             }
266
267             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "Socket", null);
268          }
269
270
271         /// <devdoc>
272         ///    <para>
273         ///       Called by the class to create a socket to accept an
274         ///       incoming request.
275         ///    </para>
276         /// </devdoc>
277         private Socket(SafeCloseSocket fd) {
278             s_LoggingEnabled = Logging.On;
279             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "Socket", null);
280             InitializeSockets();
281             // ExceptionHelper.UnmanagedPermission.Demand();
282             //<
283
284
285
286
287
288             //
289             // this should never happen, let's check anyway
290             //
291             if (fd == null || fd.IsInvalid) {
292                 throw new ArgumentException(SR.GetString(SR.net_InvalidSocketHandle));
293             }
294
295             m_Handle = fd;
296
297             addressFamily = Sockets.AddressFamily.Unknown;
298             socketType = Sockets.SocketType.Unknown;
299             protocolType = Sockets.ProtocolType.Unknown;
300             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "Socket", null);
301         }
302 #endif
303
304
305 //************* properties *************************
306
307
308         /// <devdoc>
309         /// <para>Indicates whether IPv4 support is available and enabled on this machine.</para>
310         /// </devdoc>
311         [Obsolete("SupportsIPv4 is obsoleted for this type, please use OSSupportsIPv4 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
312         public static bool SupportsIPv4 {
313             get {
314                 InitializeSockets();
315                 return s_SupportsIPv4;
316             }
317         }
318
319         // Renamed to be consistent with OSSupportsIPv6
320         public static bool OSSupportsIPv4 {
321             get {
322                 InitializeSockets();
323                 return s_SupportsIPv4;
324             }
325         }
326
327         /// <devdoc>
328         /// <para>Indicates whether IPv6 support is available and enabled on this machine.</para>
329         /// </devdoc>
330
331         [Obsolete("SupportsIPv6 is obsoleted for this type, please use OSSupportsIPv6 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
332         public static bool SupportsIPv6 {
333             get {
334                 InitializeSockets();
335                 return s_SupportsIPv6;
336             }
337         }
338
339         internal static bool LegacySupportsIPv6 {
340             get {
341                 InitializeSockets();
342                 return s_SupportsIPv6;
343             }
344         }
345
346         public static bool OSSupportsIPv6 {
347             get {
348                 InitializeSockets();
349                 return s_OSSupportsIPv6;
350             }
351         }
352
353 #if !MONO
354         /// <devdoc>
355         ///    <para>
356         ///       Gets the amount of data pending in the network's input buffer that can be
357         ///       read from the socket.
358         ///    </para>
359         /// </devdoc>
360         public int Available {
361             get {
362                 if (CleanedUp) {
363                     throw new ObjectDisposedException(this.GetType().FullName);
364                 }
365
366                 int argp = 0;
367
368                 // This may throw ObjectDisposedException.
369                 SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.ioctlsocket(
370                     m_Handle,
371                     IoctlSocketConstants.FIONREAD,
372                     ref argp);
373
374                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Available_get() UnsafeNclNativeMethods.OSSOCK.ioctlsocket returns errorCode:" + errorCode);
375
376                 //
377                 // if the native call fails we'll throw a SocketException
378                 //
379                 if (errorCode==SocketError.SocketError) {
380                     //
381                     // update our internal state after this socket error and throw
382                     //
383                     SocketException socketException = new SocketException();
384                     UpdateStatusAfterSocketError(socketException);
385                     if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "Available", socketException);
386                     throw socketException;
387                 }
388
389                 return argp;
390             }
391          }
392
393
394
395
396
397         /// <devdoc>
398         ///    <para>
399         ///       Gets the local end point.
400         ///    </para>
401         /// </devdoc>
402         public EndPoint LocalEndPoint {
403             get {
404                 if (CleanedUp) {
405                     throw new ObjectDisposedException(this.GetType().FullName);
406                 }
407
408                 if (m_NonBlockingConnectInProgress && Poll(0, SelectMode.SelectWrite))
409                 {
410                     // update the state if we've become connected after a non-blocking connect
411                     m_IsConnected = true;
412                     m_RightEndPoint = m_NonBlockingConnectRightEndPoint;
413                     m_NonBlockingConnectInProgress = false;
414                 }
415
416                 if (m_RightEndPoint == null) {
417                     return null;
418                 }
419
420                 SocketAddress socketAddress = m_RightEndPoint.Serialize();
421
422                 // This may throw ObjectDisposedException.
423                 SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.getsockname(
424                     m_Handle,
425                     socketAddress.m_Buffer,
426                     ref socketAddress.m_Size);
427
428                 if (errorCode!=SocketError.Success) {
429                     //
430                     // update our internal state after this socket error and throw
431                     //
432                     SocketException socketException = new SocketException();
433                     UpdateStatusAfterSocketError(socketException);
434                     if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "LocalEndPoint", socketException);
435                     throw socketException;
436                 }
437
438                 return m_RightEndPoint.Create(socketAddress);
439             }
440         }
441
442         /// <devdoc>
443         ///    <para>
444         ///       Gets the remote end point
445         ///    </para>
446         /// </devdoc>
447         public EndPoint RemoteEndPoint {
448             get {
449                 if (CleanedUp) {
450                     throw new ObjectDisposedException(this.GetType().FullName);
451                 }
452
453                 if (m_RemoteEndPoint==null) {
454
455                     if (m_NonBlockingConnectInProgress && Poll(0, SelectMode.SelectWrite))
456                     {
457                         // update the state if we've become connected after a non-blocking connect
458                         m_IsConnected = true;
459                         m_RightEndPoint = m_NonBlockingConnectRightEndPoint;
460                         m_NonBlockingConnectInProgress = false;
461                     }
462
463                     if (m_RightEndPoint==null) {
464                         return null;
465                     }
466
467                     SocketAddress socketAddress = m_RightEndPoint.Serialize();
468
469                     // This may throw ObjectDisposedException.
470                     SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.getpeername(
471                         m_Handle,
472                         socketAddress.m_Buffer,
473                         ref socketAddress.m_Size);
474
475                     if (errorCode!=SocketError.Success) {
476                         //
477                         // update our internal state after this socket error and throw
478                         //
479                         SocketException socketException = new SocketException();
480                         UpdateStatusAfterSocketError(socketException);
481                         if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "RemoteEndPoint", socketException);
482                         throw socketException;
483                     }
484
485                     try {
486                         m_RemoteEndPoint = m_RightEndPoint.Create(socketAddress);
487                     }
488                     catch {
489                     }
490                 }
491
492                 return m_RemoteEndPoint;
493             }
494         }
495 #endif // !MONO
496
497         /// <devdoc>
498         ///    <para>
499         ///       Gets the operating system m_Handle for the socket.
500         ///YUKON: should we cut this method off, who are the users?
501         ///    </para>
502         /// </devdoc>
503         public IntPtr Handle {
504             get {
505 #if !MONO
506                 ExceptionHelper.UnmanagedPermission.Demand();
507 #endif
508                 return m_Handle.DangerousGetHandle();
509             }
510         }
511 #if !MONO
512         internal SafeCloseSocket SafeHandle {
513             get {
514                 return m_Handle;
515             }
516         }
517
518
519         // Non-blocking I/O control
520         /// <devdoc>
521         ///    <para>
522         ///       Gets and sets the blocking mode of a socket.
523         ///    </para>
524         /// </devdoc>
525         public bool Blocking {
526             get {
527                 //
528                 // return the user's desired blocking behaviour (not the actual win32 state)
529                 //
530                 return willBlock;
531             }
532             set {
533                 if (CleanedUp) {
534                     throw new ObjectDisposedException(this.GetType().FullName);
535                 }
536
537                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::set_Blocking() value:" + value.ToString() + " willBlock:" + willBlock.ToString() + " willBlockInternal:" + willBlockInternal.ToString());
538
539                 bool current;
540
541                 SocketError errorCode = InternalSetBlocking(value, out current);
542
543                 if (errorCode!=SocketError.Success) {
544                     //
545                     // update our internal state after this socket error and throw
546                     SocketException socketException = new SocketException(errorCode);
547                     UpdateStatusAfterSocketError(socketException);
548                     if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "Blocking", socketException);
549                     throw socketException;
550                 }
551
552                 //
553                 // win32 call succeeded, update desired state
554                 //
555                 willBlock = current;
556             }
557         }
558 #endif // !MONO
559
560         public bool UseOnlyOverlappedIO{
561             get {
562                 //
563                 // return the user's desired blocking behaviour (not the actual win32 state)
564                 //
565                 return useOverlappedIO;
566
567             }
568             set {
569 #if !MONO
570                 if (m_BoundToThreadPool) {
571                     throw new InvalidOperationException(SR.GetString(SR.net_io_completionportwasbound));
572                 }
573 #endif
574
575                 useOverlappedIO = value;
576             }
577         }
578
579 #if !MONO
580         /// <devdoc>
581         ///    <para>
582         ///       Gets the connection state of the Socket. This property will return the latest
583         ///       known state of the Socket. When it returns false, the Socket was either never connected
584         ///       or it is not connected anymore. When it returns true, though, there's no guarantee that the Socket
585         ///       is still connected, but only that it was connected at the time of the last IO operation.
586         ///    </para>
587         /// </devdoc>
588         public bool Connected {
589             get {
590                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Connected() m_IsConnected:"+m_IsConnected);
591
592                 if (m_NonBlockingConnectInProgress && Poll(0, SelectMode.SelectWrite))
593                 {
594                     // update the state if we've become connected after a non-blocking connect
595                     m_IsConnected = true;
596                     m_RightEndPoint = m_NonBlockingConnectRightEndPoint;
597                     m_NonBlockingConnectInProgress = false;
598                 }
599
600                 return m_IsConnected;
601             }
602         }
603 #endif // !MONO
604
605         /// <devdoc>
606         ///    <para>
607         ///       Gets the socket's address family.
608         ///    </para>
609         /// </devdoc>
610         public AddressFamily AddressFamily {
611             get {
612                 return addressFamily;
613             }
614         }
615
616         /// <devdoc>
617         ///    <para>
618         ///       Gets the socket's socketType.
619         ///    </para>
620         /// </devdoc>
621         public SocketType SocketType {
622             get {
623                 return socketType;
624             }
625         }
626
627         /// <devdoc>
628         ///    <para>
629         ///       Gets the socket's protocol socketType.
630         ///    </para>
631         /// </devdoc>
632         public ProtocolType ProtocolType {
633             get {
634                 return protocolType;
635             }
636         }
637
638 #if !MONO
639         public bool IsBound{
640             get{
641                 return (m_RightEndPoint != null);
642             }
643         }
644 #endif // !MONO
645
646         public bool ExclusiveAddressUse{
647             get {
648                 return (int)GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse) != 0 ? true : false;
649             }
650             set {
651                 if (IsBound) {
652                     throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustnotbebound));
653                 }
654                 SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse, value ? 1 : 0);
655             }
656         }
657
658
659         public int ReceiveBufferSize {
660             get {
661                 return (int)GetSocketOption(SocketOptionLevel.Socket,
662                                      SocketOptionName.ReceiveBuffer);
663             }
664             set {
665                 if (value<0) {
666                     throw new ArgumentOutOfRangeException("value");
667                 }
668
669                 SetSocketOption(SocketOptionLevel.Socket,
670                                   SocketOptionName.ReceiveBuffer, value);
671             }
672         }
673
674         public int SendBufferSize {
675             get {
676                 return (int)GetSocketOption(SocketOptionLevel.Socket,
677                                      SocketOptionName.SendBuffer);
678             }
679
680             set {
681                 if (value<0) {
682                     throw new ArgumentOutOfRangeException("value");
683                 }
684
685                 SetSocketOption(SocketOptionLevel.Socket,
686                                   SocketOptionName.SendBuffer, value);
687             }
688         }
689
690         public int ReceiveTimeout {
691             get {
692                 return (int)GetSocketOption(SocketOptionLevel.Socket,
693                                      SocketOptionName.ReceiveTimeout);
694             }
695             set {
696                 if (value< -1) {
697                     throw new ArgumentOutOfRangeException("value");
698                 }
699                 if (value == -1) {
700                     value = 0;
701                 }
702
703                 SetSocketOption(SocketOptionLevel.Socket,
704                                   SocketOptionName.ReceiveTimeout, value);
705             }
706         }
707
708         public int SendTimeout {
709             get {
710                 return (int)GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout);
711             }
712
713             set {
714                 if (value< -1) {
715                     throw new ArgumentOutOfRangeException("value");
716                 }
717                 if (value == -1) {
718                     value = 0;
719                 }
720
721                 SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, value);
722             }
723         }
724
725         public LingerOption LingerState {
726             get {
727                 return (LingerOption)GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger);
728             }
729             set {
730                 SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, value);
731             }
732         }
733
734 #if !MONO
735         public bool NoDelay {
736             get {
737                 return (int)GetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay) != 0 ? true : false;
738             }
739             set {
740                 SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, value ? 1 : 0);
741             }
742         }
743 #endif // !MONO
744
745         public short Ttl{
746             get {
747                 if (addressFamily == AddressFamily.InterNetwork) {
748                     return (short)(int)GetSocketOption(SocketOptionLevel.IP, SocketOptionName.IpTimeToLive);
749                 }
750                 else if (addressFamily == AddressFamily.InterNetworkV6) {
751                     return (short)(int)GetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IpTimeToLive);
752                 }
753                 else{
754                     throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
755                 }
756             }
757
758             set {
759
760                 // valid values are from 0 to 255 since Ttl is really just a byte value on the wire
761                 if (value < 0 || value > 255) {
762                     throw new ArgumentOutOfRangeException("value");
763                 }
764
765                 if (addressFamily == AddressFamily.InterNetwork) {
766                     SetSocketOption(SocketOptionLevel.IP, SocketOptionName.IpTimeToLive, value);
767                 }
768
769                 else if (addressFamily == AddressFamily.InterNetworkV6) {
770                     SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IpTimeToLive, value);
771                 }
772                 else{
773                     throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
774                 }
775             }
776         }
777
778         public bool DontFragment{
779             get {
780                 if (addressFamily == AddressFamily.InterNetwork) {
781                     return (int)GetSocketOption(SocketOptionLevel.IP, SocketOptionName.DontFragment) != 0 ? true : false;
782                 }
783                 else{
784                     throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
785                 }
786             }
787
788             set {
789                 if (addressFamily == AddressFamily.InterNetwork) {
790                     SetSocketOption(SocketOptionLevel.IP, SocketOptionName.DontFragment, value ? 1 : 0);
791                 }
792                 else{
793                     throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
794                 }
795             }
796         }
797
798 #if !MONO
799         public bool MulticastLoopback{
800             get {
801                 if (addressFamily == AddressFamily.InterNetwork) {
802                     return (int)GetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastLoopback) != 0 ? true : false;
803                 }
804                 else if (addressFamily == AddressFamily.InterNetworkV6) {
805                     return (int)GetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback) != 0 ? true : false;
806                 }
807                 else{
808                     throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
809                 }
810             }
811
812             set {
813                 if (addressFamily == AddressFamily.InterNetwork) {
814                     SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastLoopback, value ? 1 : 0);
815                 }
816
817                 else if (addressFamily == AddressFamily.InterNetworkV6) {
818                     SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback, value ? 1 : 0);
819                 }
820                 else{
821                     throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
822                 }
823             }
824         }
825
826         public bool EnableBroadcast{
827             get {
828                 return (int)GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast) != 0 ? true : false;
829             }
830             set {
831                 SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, value ? 1 : 0);
832             }
833         }
834 #endif // !MONO
835
836         public bool DualMode {
837             get {
838                 if (AddressFamily != AddressFamily.InterNetworkV6) {
839                     throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
840                 }
841                 return ((int)GetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only) == 0);
842             }
843             set {
844                 if (AddressFamily != AddressFamily.InterNetworkV6) {
845                     throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
846                 }
847                 SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, value ? 0 : 1);
848             }
849         }
850
851         private bool IsDualMode {
852             get {
853                 return AddressFamily == AddressFamily.InterNetworkV6 && DualMode;
854             }
855         }
856
857         internal bool CanTryAddressFamily(AddressFamily family) {
858             return (family == addressFamily) || (family == AddressFamily.InterNetwork && IsDualMode);
859         }
860
861
862 //************* public methods *************************
863
864
865
866
867 #if !MONO
868         /// <devdoc>
869         ///    <para>Associates a socket with an end point.</para>
870         /// </devdoc>
871         public void Bind(EndPoint localEP) {
872
873             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "Bind", localEP);
874
875             if (CleanedUp) {
876                 throw new ObjectDisposedException(this.GetType().FullName);
877             }
878             //
879             // parameter validation
880             //
881             if (localEP==null) {
882                 throw new ArgumentNullException("localEP");
883             }
884
885             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Bind() localEP:" + localEP.ToString());
886
887             EndPoint endPointSnapshot = localEP;
888             IPEndPoint ipSnapshot = localEP as IPEndPoint;
889
890             //
891             // for now security is implemented only on IPEndPoint
892             // If EndPoint is of other type - unmanaged code permisison is demanded
893             //
894             if (ipSnapshot != null)
895             {
896                 // Take a snapshot that will make it immutable and not derived.
897                 ipSnapshot = ipSnapshot.Snapshot();                                
898                 // DualMode: Do the security check on the users IPv4 address, but map to IPv6 before binding.
899                 endPointSnapshot = RemapIPEndPoint(ipSnapshot);
900
901                 //
902                 // create the permissions the user would need for the call
903                 //
904                 SocketPermission socketPermission
905                     = new SocketPermission(
906                         NetworkAccess.Accept,
907                         Transport,
908                         ipSnapshot.Address.ToString(),
909                         ipSnapshot.Port);
910                 //
911                 // demand for them
912                 //
913                 socketPermission.Demand();
914
915                 // Here the permission check has succeded.
916                 // NB: if local port is 0, then winsock will assign some>1024,
917                 //     so assuming that this is safe. We will not check the
918                 //     NetworkAccess.Accept permissions in Receive.
919             }
920             else {
921                 //<
922
923
924
925
926
927                 ExceptionHelper.UnmanagedPermission.Demand();
928             }
929
930             //
931             // ask the EndPoint to generate a SocketAddress that we
932             // can pass down to winsock
933             //
934             SocketAddress socketAddress = CallSerializeCheckDnsEndPoint(endPointSnapshot);
935             DoBind(endPointSnapshot, socketAddress);
936             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "Bind", "");
937         }
938
939         internal void InternalBind(EndPoint localEP)
940         {
941             if (s_LoggingEnabled) Logging.Enter(Logging.Sockets, this, "InternalBind", localEP);
942
943             if (CleanedUp)
944             {
945                 throw new ObjectDisposedException(GetType().FullName);
946             }
947
948             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::InternalBind() localEP:" + localEP.ToString());
949             GlobalLog.Assert(!(localEP is DnsEndPoint), "Calling InternalBind with a DnsEndPoint, about to get NotImplementedException");
950
951             //
952             // ask the EndPoint to generate a SocketAddress that we
953             // can pass down to winsock
954             //
955             EndPoint endPointSnapshot = localEP;
956             SocketAddress socketAddress = SnapshotAndSerialize(ref endPointSnapshot);
957             DoBind(endPointSnapshot, socketAddress);
958
959             if (s_LoggingEnabled) Logging.Exit(Logging.Sockets, this, "InternalBind", "");
960         }
961
962         private void DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
963         {
964             // Mitigation for Blue Screen of Death (Win7, maybe others)
965             IPEndPoint ipEndPoint = endPointSnapshot as IPEndPoint;
966             if (!OSSupportsIPv4 && ipEndPoint != null && ipEndPoint.Address.IsIPv4MappedToIPv6)
967             {
968                 SocketException socketException = new SocketException(SocketError.InvalidArgument);
969                 UpdateStatusAfterSocketError(socketException);
970                 if (s_LoggingEnabled) Logging.Exception(Logging.Sockets, this, "DoBind", socketException);
971                 throw socketException;
972             }
973
974             // This may throw ObjectDisposedException.
975             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.bind(
976                 m_Handle,
977                 socketAddress.m_Buffer,
978                 socketAddress.m_Size);
979
980 #if TRAVE
981             try
982             {
983                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Bind() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " UnsafeNclNativeMethods.OSSOCK.bind returns errorCode:" + errorCode);
984             }
985             catch (ObjectDisposedException) { }
986 #endif
987
988             //
989             // if the native call fails we'll throw a SocketException
990             //
991             if (errorCode != SocketError.Success)
992             {
993                 //
994                 // update our internal state after this socket error and throw
995                 //
996                 SocketException socketException = new SocketException();
997                 UpdateStatusAfterSocketError(socketException);
998                 if (s_LoggingEnabled) Logging.Exception(Logging.Sockets, this, "DoBind", socketException);
999                 throw socketException;
1000             }
1001
1002             if (m_RightEndPoint == null)
1003             {
1004                 //
1005                 // save a copy of the EndPoint so we can use it for Create()
1006                 //
1007                 m_RightEndPoint = endPointSnapshot;
1008             }
1009         }
1010
1011
1012         /// <devdoc>
1013         ///    <para>Establishes a connection to a remote system.</para>
1014         /// </devdoc>
1015         public void Connect(EndPoint remoteEP) {
1016             if (CleanedUp) {
1017                 throw new ObjectDisposedException(this.GetType().FullName);
1018             }
1019             //
1020             // parameter validation
1021             //
1022             if (remoteEP==null) {
1023                 throw new ArgumentNullException("remoteEP");
1024             }
1025
1026             if(m_IsDisconnected){
1027                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_disconnectedConnect));
1028             }
1029
1030             if (isListening)
1031             {
1032                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustnotlisten));
1033             }
1034
1035             ValidateBlockingMode();
1036             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Connect() DST:" + ValidationHelper.ToString(remoteEP));
1037
1038             DnsEndPoint dnsEP = remoteEP as DnsEndPoint;
1039             if (dnsEP != null)
1040             {
1041                 if (dnsEP.AddressFamily != AddressFamily.Unspecified && !CanTryAddressFamily(dnsEP.AddressFamily)) 
1042                 {
1043                     throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
1044                 }
1045
1046                 Connect(dnsEP.Host, dnsEP.Port);
1047                 return;
1048             }
1049
1050             //This will check the permissions for connect
1051             EndPoint endPointSnapshot = remoteEP;
1052             SocketAddress socketAddress = CheckCacheRemote(ref endPointSnapshot, true);
1053
1054             if (!Blocking)
1055             {
1056                 m_NonBlockingConnectRightEndPoint = endPointSnapshot;
1057                 m_NonBlockingConnectInProgress = true;
1058             }
1059
1060             DoConnect(endPointSnapshot, socketAddress);
1061         }
1062
1063
1064         public void Connect(IPAddress address, int port){
1065
1066             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "Connect", address);
1067
1068             if (CleanedUp){
1069                 throw new ObjectDisposedException(this.GetType().FullName);
1070             }
1071             //if address family isn't the socket address family throw
1072             if (address==null) {
1073                 throw new ArgumentNullException("address");
1074             }
1075
1076             if (!ValidationHelper.ValidateTcpPort(port)) {
1077                 throw new ArgumentOutOfRangeException("port");
1078             }
1079             if (!CanTryAddressFamily(address.AddressFamily)) {
1080                 throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
1081             }
1082
1083             IPEndPoint remoteEP = new IPEndPoint(address, port);
1084             Connect(remoteEP);
1085             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "Connect", null);
1086         }
1087
1088
1089         public void Connect(string host, int port){
1090             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "Connect", host);
1091
1092             if (CleanedUp){
1093                 throw new ObjectDisposedException(this.GetType().FullName);
1094             }
1095             if (host==null) {
1096                 throw new ArgumentNullException("host");
1097             }
1098             if (!ValidationHelper.ValidateTcpPort(port)){
1099                 throw new ArgumentOutOfRangeException("port");
1100             }
1101             if (addressFamily != AddressFamily.InterNetwork && addressFamily != AddressFamily.InterNetworkV6) {
1102                 throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
1103             }
1104
1105             IPAddress[] addresses = Dns.GetHostAddresses(host);
1106             Connect(addresses,port);
1107             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "Connect", null);
1108         }
1109
1110         public void Connect(IPAddress[] addresses, int port){
1111             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "Connect", addresses);
1112
1113             if (CleanedUp){
1114                 throw new ObjectDisposedException(this.GetType().FullName);
1115             }
1116             if (addresses==null) {
1117                 throw new ArgumentNullException("addresses");
1118             }
1119             if (addresses.Length == 0) {
1120                 throw new ArgumentException(SR.GetString(SR.net_sockets_invalid_ipaddress_length), "addresses");
1121             }
1122             if (!ValidationHelper.ValidateTcpPort(port)) {
1123                 throw new ArgumentOutOfRangeException("port");
1124             }
1125             if (addressFamily != AddressFamily.InterNetwork && addressFamily != AddressFamily.InterNetworkV6) {
1126                 throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
1127             }
1128
1129             Exception   lastex = null;
1130             foreach ( IPAddress address in addresses ) {
1131                 if (CanTryAddressFamily(address.AddressFamily)) {
1132                     try
1133                     {
1134                         Connect(new IPEndPoint(address,port) );
1135                         lastex = null;
1136                         break;
1137                     }
1138                     catch ( Exception ex )
1139                     {
1140                         if (NclUtilities.IsFatal(ex)) throw;
1141                         lastex = ex;
1142                     }
1143                 }
1144             }
1145
1146             if ( lastex != null )
1147                 throw lastex;
1148
1149             //if we're not connected, then we didn't get a valid ipaddress in the list
1150             if (!Connected) {
1151                 throw new ArgumentException(SR.GetString(SR.net_invalidAddressList), "addresses");
1152             }
1153
1154             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "Connect", null);
1155         }
1156
1157
1158         /// <devdoc>
1159         ///    <para>
1160         ///       Forces a socket connection to close.
1161         ///    </para>
1162         /// </devdoc>
1163         public void Close()
1164         {
1165             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Close() timeout = " + m_CloseTimeout);
1166             if (s_LoggingEnabled) Logging.Enter(Logging.Sockets, this, "Close", null);
1167             ((IDisposable)this).Dispose();
1168             if (s_LoggingEnabled) Logging.Exit(Logging.Sockets, this, "Close", null);
1169         }
1170
1171         public void Close(int timeout)
1172         {
1173             if (timeout < -1)
1174             {
1175                 throw new ArgumentOutOfRangeException("timeout");
1176             }
1177             m_CloseTimeout = timeout;
1178             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Close() timeout = " + m_CloseTimeout);
1179             ((IDisposable)this).Dispose();
1180         }
1181
1182
1183         /// <devdoc>
1184         ///    <para>
1185         ///       Places a socket in a listening state.
1186         ///    </para>
1187         /// </devdoc>
1188         public void Listen(int backlog) {
1189             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "Listen", backlog);
1190             if (CleanedUp) {
1191                 throw new ObjectDisposedException(this.GetType().FullName);
1192             }
1193
1194             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Listen() backlog:" + backlog.ToString());
1195
1196             // No access permissions are necessary here because
1197             // the verification is done for Bind
1198
1199             // This may throw ObjectDisposedException.
1200             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.listen(
1201                 m_Handle,
1202                 backlog);
1203
1204 #if TRAVE
1205             try
1206             {
1207                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Listen() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " UnsafeNclNativeMethods.OSSOCK.listen returns errorCode:" + errorCode);
1208             }
1209             catch (ObjectDisposedException) { }
1210 #endif
1211
1212             //
1213             // if the native call fails we'll throw a SocketException
1214             //
1215             if (errorCode!=SocketError.Success) {
1216                 //
1217                 // update our internal state after this socket error and throw
1218                 //
1219                 SocketException socketException = new SocketException();
1220                 UpdateStatusAfterSocketError(socketException);
1221                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "Listen", socketException);
1222                 throw socketException;
1223             }
1224             isListening = true;
1225             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "Listen", "");
1226         }
1227
1228         /// <devdoc>
1229         ///    <para>
1230         ///       Creates a new <see cref='Sockets.Socket'/> instance to handle an incoming
1231         ///       connection.
1232         ///    </para>
1233         /// </devdoc>
1234         public Socket Accept() {
1235             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "Accept", "");
1236
1237             //
1238             // parameter validation
1239             //
1240
1241             if (CleanedUp) {
1242                 throw new ObjectDisposedException(this.GetType().FullName);
1243             }
1244
1245             if (m_RightEndPoint==null) {
1246                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustbind));
1247             }
1248
1249             if(!isListening){
1250                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustlisten));
1251             }
1252
1253             if(m_IsDisconnected){
1254                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_disconnectedAccept));
1255             }
1256
1257             ValidateBlockingMode();
1258             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Accept() SRC:" + ValidationHelper.ToString(LocalEndPoint));
1259
1260             SocketAddress socketAddress = m_RightEndPoint.Serialize();
1261
1262             // This may throw ObjectDisposedException.
1263             SafeCloseSocket acceptedSocketHandle = SafeCloseSocket.Accept(
1264                 m_Handle,
1265                 socketAddress.m_Buffer,
1266                 ref socketAddress.m_Size);
1267
1268             //
1269             // if the native call fails we'll throw a SocketException
1270             //
1271             if (acceptedSocketHandle.IsInvalid) {
1272                 //
1273                 // update our internal state after this socket error and throw
1274                 //
1275                 SocketException socketException = new SocketException();
1276                 UpdateStatusAfterSocketError(socketException);
1277                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "Accept", socketException);
1278                 throw socketException;
1279             }
1280
1281             Socket socket = CreateAcceptSocket(acceptedSocketHandle, m_RightEndPoint.Create(socketAddress), false);
1282             if (s_LoggingEnabled) {
1283                 Logging.PrintInfo(Logging.Sockets, socket, SR.GetString(SR.net_log_socket_accepted, socket.RemoteEndPoint, socket.LocalEndPoint));
1284                 Logging.Exit(Logging.Sockets, this, "Accept", socket);
1285             }
1286             return socket;
1287         }
1288 #endif // !MONO
1289
1290         /// <devdoc>
1291         ///    <para>Sends a data buffer to a connected socket.</para>
1292         /// </devdoc>
1293         public int Send(byte[] buffer, int size, SocketFlags socketFlags) {
1294             return Send(buffer, 0, size, socketFlags);
1295         }
1296         /// <devdoc>
1297         ///    <para>[To be supplied.]</para>
1298         /// </devdoc>
1299         public int Send(byte[] buffer, SocketFlags socketFlags) {
1300             return Send(buffer, 0, buffer!=null ? buffer.Length : 0, socketFlags);
1301         }
1302         /// <devdoc>
1303         ///    <para>[To be supplied.]</para>
1304         /// </devdoc>
1305         public int Send(byte[] buffer) {
1306             return Send(buffer, 0, buffer!=null ? buffer.Length : 0, SocketFlags.None);
1307         }
1308
1309 #if !FEATURE_PAL
1310
1311         /// <devdoc>
1312         ///    <para>[To be supplied.]</para>
1313         /// </devdoc>
1314         public int Send(IList<ArraySegment<byte>> buffers) {
1315             return Send(buffers,SocketFlags.None);
1316         }
1317
1318         /// <devdoc>
1319         ///    <para>[To be supplied.]</para>
1320         /// </devdoc>
1321         public int Send(IList<ArraySegment<byte>> buffers, SocketFlags socketFlags) {
1322             SocketError errorCode;
1323             int bytesTransferred = Send(buffers, socketFlags, out errorCode);
1324             if(errorCode != SocketError.Success){
1325                 throw new SocketException(errorCode);
1326             }
1327             return bytesTransferred;
1328         }
1329
1330 #if !MONO
1331         public int Send(IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode) {
1332             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "Send", "");
1333             if (CleanedUp) {
1334                 throw new ObjectDisposedException(this.GetType().FullName);
1335             }
1336             if (buffers==null) {
1337                throw new ArgumentNullException("buffers");
1338             }
1339
1340             if(buffers.Count == 0){
1341                 throw new ArgumentException(SR.GetString(SR.net_sockets_zerolist,"buffers"), "buffers");
1342             }
1343
1344             ValidateBlockingMode();
1345             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Send() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " DST:" + ValidationHelper.ToString(RemoteEndPoint));
1346
1347             //make sure we don't let the app mess up the buffer array enough to cause
1348             //corruption.
1349
1350             errorCode = SocketError.Success;
1351             int count = buffers.Count;
1352             WSABuffer[] WSABuffers = new WSABuffer[count];
1353             GCHandle[] objectsToPin = null;
1354             int bytesTransferred;
1355
1356             try {
1357                 objectsToPin = new GCHandle[count];
1358                 for (int i = 0; i < count; ++i)
1359                 {
1360                     ArraySegment<byte> buffer = buffers[i];
1361                     ValidationHelper.ValidateSegment(buffer);
1362                     objectsToPin[i] = GCHandle.Alloc(buffer.Array, GCHandleType.Pinned);
1363                     WSABuffers[i].Length = buffer.Count;
1364                     WSABuffers[i].Pointer = Marshal.UnsafeAddrOfPinnedArrayElement(buffer.Array, buffer.Offset);
1365                 }
1366
1367                 // This may throw ObjectDisposedException.
1368                 errorCode = UnsafeNclNativeMethods.OSSOCK.WSASend_Blocking(
1369                     m_Handle.DangerousGetHandle(),
1370                     WSABuffers,
1371                     count,
1372                     out bytesTransferred,
1373                     socketFlags,
1374                     SafeNativeOverlapped.Zero,
1375                     IntPtr.Zero);
1376
1377                 if ((SocketError)errorCode==SocketError.SocketError) {
1378                     errorCode = (SocketError)Marshal.GetLastWin32Error();
1379                 }
1380
1381 #if TRAVE
1382                 try
1383                 {
1384                     GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Send() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " DST:" + ValidationHelper.ToString(RemoteEndPoint) + " UnsafeNclNativeMethods.OSSOCK.send returns errorCode:" + errorCode + " bytesTransferred:" + bytesTransferred);
1385                 }
1386                 catch (ObjectDisposedException) { }
1387 #endif
1388             }
1389             finally {
1390                 if (objectsToPin != null)
1391                     for (int i = 0; i < objectsToPin.Length; ++i)
1392                         if (objectsToPin[i].IsAllocated)
1393                             objectsToPin[i].Free();
1394             }
1395
1396             if (errorCode != SocketError.Success) {
1397                 //
1398                 // update our internal state after this socket error and throw
1399                 //
1400                 UpdateStatusAfterSocketError(errorCode);
1401                 if(s_LoggingEnabled){
1402                     Logging.Exception(Logging.Sockets, this, "Send", new SocketException(errorCode));
1403                     Logging.Exit(Logging.Sockets, this, "Send", 0);
1404                 }
1405                 return 0;
1406             }
1407
1408 #if !FEATURE_PAL // perfcounter
1409             if (s_PerfCountersEnabled)
1410             {
1411                 if (bytesTransferred>0) {
1412                     NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketBytesSent, bytesTransferred);
1413                     if (Transport==TransportType.Udp) {
1414                         NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketDatagramsSent);
1415                     }
1416                 }
1417             }
1418 #endif
1419             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "Send", bytesTransferred);
1420             return bytesTransferred;
1421         }
1422 #endif // !MONO
1423
1424         /// <devdoc>
1425         ///    <para>Sends a file to
1426         ///       a connected socket.</para>
1427         /// </devdoc>
1428         [ResourceExposure(ResourceScope.Machine)]
1429         [ResourceConsumption(ResourceScope.Machine)]
1430         public void SendFile(string fileName)
1431         {
1432             SendFile(fileName,null,null,TransmitFileOptions.UseDefaultWorkerThread);
1433         }
1434
1435 #if !MONO
1436         /// <devdoc>
1437         ///    <para>Sends a file to
1438         ///       a connected socket.</para>
1439         /// </devdoc>
1440         [ResourceExposure(ResourceScope.Machine)]
1441         [ResourceConsumption(ResourceScope.Machine)]
1442         public void SendFile(string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags) {
1443             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "SendFile", "");
1444
1445             if (CleanedUp) {
1446                 throw new ObjectDisposedException(this.GetType().FullName);
1447             }
1448
1449             if (!Connected) {
1450                 throw new NotSupportedException(SR.GetString(SR.net_notconnected));
1451             }
1452
1453             ValidateBlockingMode();
1454             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SendFile() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " DST:" + ValidationHelper.ToString(RemoteEndPoint) + " fileName:" + fileName);
1455
1456             TransmitFileOverlappedAsyncResult asyncResult = new TransmitFileOverlappedAsyncResult(this);
1457
1458             FileStream fileStream = null;
1459             if (fileName != null && fileName.Length>0) {
1460                 fileStream = new FileStream(fileName,FileMode.Open,FileAccess.Read,FileShare.Read);
1461             }
1462
1463             SafeHandle fileHandle = null;
1464
1465             if (fileStream != null) {
1466                 ExceptionHelper.UnmanagedPermission.Assert();
1467                 try {
1468                     fileHandle = fileStream.SafeFileHandle;
1469                 }
1470                 finally {
1471                     SecurityPermission.RevertAssert();
1472                 }
1473             }
1474
1475             SocketError errorCode = SocketError.Success;
1476             try {
1477                 asyncResult.SetUnmanagedStructures(preBuffer, postBuffer, fileStream, 0, true);
1478
1479                 // This can throw ObjectDisposedException.
1480                 if (fileHandle != null ?
1481                     !UnsafeNclNativeMethods.OSSOCK.TransmitFile_Blocking(m_Handle.DangerousGetHandle(), fileHandle, 0, 0, SafeNativeOverlapped.Zero, asyncResult.TransmitFileBuffers, flags) :
1482                     !UnsafeNclNativeMethods.OSSOCK.TransmitFile_Blocking2(m_Handle.DangerousGetHandle(), IntPtr.Zero, 0, 0, SafeNativeOverlapped.Zero, asyncResult.TransmitFileBuffers, flags))
1483                 {
1484                     errorCode = (SocketError) Marshal.GetLastWin32Error();
1485                 }
1486             }
1487             finally {
1488                 asyncResult.SyncReleaseUnmanagedStructures();
1489             }
1490
1491 #if TRAVE
1492             try
1493             {
1494                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SendFile() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " DST:" + ValidationHelper.ToString(RemoteEndPoint) + " UnsafeNclNativeMethods.OSSOCK.TransmitFile returns errorCode:" + errorCode);
1495             }
1496             catch (ObjectDisposedException) { }
1497 #endif
1498
1499             //
1500             // if the native call fails we'll throw a SocketException
1501             //
1502             if (errorCode!=SocketError.Success) {
1503                 //
1504                 // update our internal state after this socket error and throw
1505                 //
1506                 SocketException socketException = new SocketException(errorCode);
1507                 UpdateStatusAfterSocketError(socketException);
1508                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "SendFile", socketException);
1509                 throw socketException;
1510             }
1511
1512             if ((asyncResult.Flags & (TransmitFileOptions.Disconnect | TransmitFileOptions.ReuseSocket) )!=0) {
1513                 SetToDisconnected();
1514                 m_RemoteEndPoint = null;
1515             }
1516
1517             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "SendFile", errorCode);
1518             return;
1519         }
1520 #endif // !MONO
1521 #endif // !FEATURE_PAL
1522
1523
1524         /// <devdoc>
1525         ///    <para>Sends data to
1526         ///       a connected socket, starting at the indicated location in the
1527         ///       data.</para>
1528         /// </devdoc>
1529
1530
1531         public int Send(byte[] buffer, int offset, int size, SocketFlags socketFlags) {
1532             SocketError errorCode;
1533             int bytesTransferred = Send(buffer, offset, size, socketFlags, out errorCode);
1534             if(errorCode != SocketError.Success){
1535                 throw new SocketException(errorCode);
1536             }
1537             return bytesTransferred;
1538         }
1539
1540 #if !MONO
1541         public int Send(byte[] buffer, int offset, int size, SocketFlags socketFlags, out SocketError errorCode) {
1542             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "Send", "");
1543
1544             if (CleanedUp) {
1545                 throw new ObjectDisposedException(this.GetType().FullName);
1546             }
1547             //
1548             // parameter validation
1549             //
1550             if (buffer==null) {
1551                 throw new ArgumentNullException("buffer");
1552             }
1553             if (offset<0 || offset>buffer.Length) {
1554                 throw new ArgumentOutOfRangeException("offset");
1555             }
1556             if (size<0 || size>buffer.Length-offset) {
1557                 throw new ArgumentOutOfRangeException("size");
1558             }
1559
1560
1561             errorCode = SocketError.Success;
1562             ValidateBlockingMode();
1563             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Send() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " DST:" + ValidationHelper.ToString(RemoteEndPoint) + " size:" + size);
1564
1565             // This can throw ObjectDisposedException.
1566             int bytesTransferred;
1567             unsafe {
1568                 if (buffer.Length == 0)
1569                     bytesTransferred = UnsafeNclNativeMethods.OSSOCK.send(m_Handle.DangerousGetHandle(), null, 0, socketFlags);
1570                 else{
1571                     fixed (byte* pinnedBuffer = buffer) {
1572                         bytesTransferred = UnsafeNclNativeMethods.OSSOCK.send(
1573                                         m_Handle.DangerousGetHandle(),
1574                                         pinnedBuffer+offset,
1575                                         size,
1576                                         socketFlags);
1577                     }
1578                 }
1579             }
1580
1581             //
1582             // if the native call fails we'll throw a SocketException
1583             //
1584             if ((SocketError)bytesTransferred==SocketError.SocketError) {
1585                 //
1586                 // update our internal state after this socket error and throw
1587                 //
1588                 errorCode = (SocketError)Marshal.GetLastWin32Error();
1589                 UpdateStatusAfterSocketError(errorCode);
1590                 if(s_LoggingEnabled){
1591                     Logging.Exception(Logging.Sockets, this, "Send", new SocketException(errorCode));
1592                     Logging.Exit(Logging.Sockets, this, "Send", 0);
1593                 }
1594                 return 0;
1595             }
1596
1597 #if !FEATURE_PAL // perfcounter
1598             if (s_PerfCountersEnabled)
1599             {
1600                 if (bytesTransferred>0) {
1601                     NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketBytesSent, bytesTransferred);
1602                     if (Transport==TransportType.Udp) {
1603                         NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketDatagramsSent);
1604                     }
1605                 }
1606             }
1607 #endif //!FEATURE_PAL
1608
1609             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Send() UnsafeNclNativeMethods.OSSOCK.send returns:" + bytesTransferred.ToString());
1610             GlobalLog.Dump(buffer, offset, bytesTransferred);
1611             if(s_LoggingEnabled)Logging.Dump(Logging.Sockets, this, "Send", buffer, offset, size);
1612             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "Send", bytesTransferred);
1613             return bytesTransferred;
1614         }
1615
1616
1617         /// <devdoc>
1618         ///    <para>Sends data to a specific end point, starting at the indicated location in the
1619         ///       data.</para>
1620         /// </devdoc>
1621         public int SendTo(byte[] buffer, int offset, int size, SocketFlags socketFlags, EndPoint remoteEP) {
1622             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "SendTo", "");
1623             if (CleanedUp) {
1624                 throw new ObjectDisposedException(this.GetType().FullName);
1625             }
1626             //
1627             // parameter validation
1628             //
1629             if (buffer==null) {
1630                 throw new ArgumentNullException("buffer");
1631             }
1632             if (remoteEP==null) {
1633                 throw new ArgumentNullException("remoteEP");
1634             }
1635             if (offset<0 || offset>buffer.Length) {
1636                 throw new ArgumentOutOfRangeException("offset");
1637             }
1638             if (size<0 || size>buffer.Length-offset) {
1639                 throw new ArgumentOutOfRangeException("size");
1640             }
1641
1642             ValidateBlockingMode();
1643             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SendTo() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " size:" + size + " remoteEP:" + ValidationHelper.ToString(remoteEP));
1644
1645             //That will check ConnectPermission for remoteEP
1646             EndPoint endPointSnapshot = remoteEP;
1647             SocketAddress socketAddress = CheckCacheRemote(ref endPointSnapshot, false);
1648
1649             // This can throw ObjectDisposedException.
1650             int bytesTransferred;
1651             unsafe
1652             {
1653                 if (buffer.Length == 0)
1654                 {
1655                     bytesTransferred = UnsafeNclNativeMethods.OSSOCK.sendto(
1656                         m_Handle.DangerousGetHandle(),
1657                         null,
1658                         0,
1659                         socketFlags,
1660                         socketAddress.m_Buffer,
1661                         socketAddress.m_Size);
1662                 }
1663                 else
1664                 {
1665                     fixed (byte* pinnedBuffer = buffer)
1666                     {
1667                         bytesTransferred = UnsafeNclNativeMethods.OSSOCK.sendto(
1668                             m_Handle.DangerousGetHandle(),
1669                             pinnedBuffer+offset,
1670                             size,
1671                             socketFlags,
1672                             socketAddress.m_Buffer,
1673                             socketAddress.m_Size);
1674                     }
1675                 }
1676             }
1677
1678             //
1679             // if the native call fails we'll throw a SocketException
1680             //
1681             if ((SocketError)bytesTransferred==SocketError.SocketError) {
1682                 //
1683                 // update our internal state after this socket error and throw
1684                 //
1685                 SocketException socketException = new SocketException();
1686                 UpdateStatusAfterSocketError(socketException);
1687                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "SendTo", socketException);
1688                 throw socketException;
1689             }
1690
1691             if (m_RightEndPoint==null) {
1692                 //
1693                 // save a copy of the EndPoint so we can use it for Create()
1694                 //
1695                 m_RightEndPoint = endPointSnapshot;
1696             }
1697
1698 #if !FEATURE_PAL // perfcounter
1699             if (s_PerfCountersEnabled)
1700             {
1701                 if (bytesTransferred>0) {
1702                     NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketBytesSent, bytesTransferred);
1703                     if (Transport==TransportType.Udp) {
1704                         NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketDatagramsSent);
1705                     }
1706                 }
1707             }
1708 #endif //!FEATURE_PAL
1709
1710             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SendTo() returning bytesTransferred:" + bytesTransferred.ToString());
1711             GlobalLog.Dump(buffer, offset, bytesTransferred);
1712             if(s_LoggingEnabled)Logging.Dump(Logging.Sockets, this, "SendTo", buffer, offset, size);
1713             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "SendTo", bytesTransferred);
1714             return bytesTransferred;
1715         }
1716 #endif // !MONO
1717
1718         /// <devdoc>
1719         ///    <para>Sends data to a specific end point, starting at the indicated location in the data.</para>
1720         /// </devdoc>
1721         public int SendTo(byte[] buffer, int size, SocketFlags socketFlags, EndPoint remoteEP) {
1722             return SendTo(buffer, 0, size, socketFlags, remoteEP);
1723         }
1724
1725         /// <devdoc>
1726         ///    <para>[To be supplied.]</para>
1727         /// </devdoc>
1728         public int SendTo(byte[] buffer, SocketFlags socketFlags, EndPoint remoteEP) {
1729             return SendTo(buffer, 0, buffer!=null ? buffer.Length : 0, socketFlags, remoteEP);
1730         }
1731
1732         /// <devdoc>
1733         ///    <para>[To be supplied.]</para>
1734         /// </devdoc>
1735         public int SendTo(byte[] buffer, EndPoint remoteEP) {
1736             return SendTo(buffer, 0, buffer!=null ? buffer.Length : 0, SocketFlags.None, remoteEP);
1737         }
1738
1739
1740         /// <devdoc>
1741         ///    <para>Receives data from a connected socket.</para>
1742         /// </devdoc>
1743         public int Receive(byte[] buffer, int size, SocketFlags socketFlags) {
1744             return Receive(buffer, 0, size, socketFlags);
1745         }
1746         /// <devdoc>
1747         ///    <para>[To be supplied.]</para>
1748         /// </devdoc>
1749         public int Receive(byte[] buffer, SocketFlags socketFlags) {
1750             return Receive(buffer, 0, buffer!=null ? buffer.Length : 0, socketFlags);
1751         }
1752         /// <devdoc>
1753         ///    <para>[To be supplied.]</para>
1754         /// </devdoc>
1755         public int Receive(byte[] buffer) {
1756             return Receive(buffer, 0, buffer!=null ? buffer.Length : 0, SocketFlags.None);
1757         }
1758
1759         /// <devdoc>
1760         ///    <para>Receives data from a connected socket into a specific location of the receive
1761         ///       buffer.</para>
1762         /// </devdoc>
1763
1764         public int Receive(byte[] buffer, int offset, int size, SocketFlags socketFlags) {
1765             SocketError errorCode;
1766             int bytesTransferred = Receive(buffer, offset, size, socketFlags, out errorCode);
1767             if(errorCode != SocketError.Success){
1768                 throw new SocketException(errorCode);
1769             }
1770             return bytesTransferred;
1771         }
1772
1773 #if !MONO
1774         public int Receive(byte[] buffer, int offset, int size, SocketFlags socketFlags, out SocketError errorCode) {
1775             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "Receive", "");
1776             if (CleanedUp) {
1777                 throw new ObjectDisposedException(this.GetType().FullName);
1778             }
1779             //
1780             // parameter validation
1781             //
1782
1783             if (buffer==null) {
1784                 throw new ArgumentNullException("buffer");
1785             }
1786             if (offset<0 || offset>buffer.Length) {
1787                 throw new ArgumentOutOfRangeException("offset");
1788             }
1789             if (size<0 || size>buffer.Length-offset) {
1790                 throw new ArgumentOutOfRangeException("size");
1791             }
1792
1793
1794             ValidateBlockingMode();
1795             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Receive() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " DST:" + ValidationHelper.ToString(RemoteEndPoint) + " size:" + size);
1796
1797             // This can throw ObjectDisposedException.
1798             int bytesTransferred;
1799             errorCode = SocketError.Success;
1800             unsafe {
1801                 if (buffer.Length == 0)
1802                 {
1803                     bytesTransferred = UnsafeNclNativeMethods.OSSOCK.recv(m_Handle.DangerousGetHandle(), null, 0, socketFlags);
1804                 }
1805                 else fixed (byte* pinnedBuffer = buffer) {
1806                     bytesTransferred = UnsafeNclNativeMethods.OSSOCK.recv(m_Handle.DangerousGetHandle(), pinnedBuffer+offset, size, socketFlags);
1807                 }
1808             }
1809
1810             if ((SocketError)bytesTransferred==SocketError.SocketError) {
1811                 //
1812                 // update our internal state after this socket error and throw
1813                 //
1814                 errorCode = (SocketError)Marshal.GetLastWin32Error();
1815                 UpdateStatusAfterSocketError(errorCode);
1816                 if(s_LoggingEnabled){
1817                     Logging.Exception(Logging.Sockets, this, "Receive", new SocketException(errorCode));
1818                     Logging.Exit(Logging.Sockets, this, "Receive", 0);
1819                 }
1820                 return 0;
1821             }
1822
1823 #if !FEATURE_PAL // perfcounter
1824             if (s_PerfCountersEnabled)
1825             {
1826                 bool peek = ((int)socketFlags & (int)SocketFlags.Peek)!=0;
1827
1828                 if (bytesTransferred>0 && !peek) {
1829                     NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketBytesReceived, bytesTransferred);
1830                     if (Transport==TransportType.Udp) {
1831                         NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketDatagramsReceived);
1832                     }
1833                 }
1834             }
1835 #endif //!FEATURE_PAL
1836
1837 #if TRAVE
1838             try
1839             {
1840                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Receive() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " DST:" + ValidationHelper.ToString(RemoteEndPoint) + " bytesTransferred:" + bytesTransferred);
1841             }
1842             catch (ObjectDisposedException) { }
1843 #endif
1844             GlobalLog.Dump(buffer, offset, bytesTransferred);
1845
1846             if(s_LoggingEnabled)Logging.Dump(Logging.Sockets, this, "Receive", buffer, offset, bytesTransferred);
1847             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "Receive", bytesTransferred);
1848
1849             return bytesTransferred;
1850         }
1851 #endif // !MONO
1852
1853         public int Receive(IList<ArraySegment<byte>> buffers) {
1854             return Receive(buffers,SocketFlags.None);
1855         }
1856
1857
1858         public int Receive(IList<ArraySegment<byte>> buffers, SocketFlags socketFlags) {
1859             SocketError errorCode;
1860             int bytesTransferred = Receive(buffers, socketFlags, out errorCode);
1861             if(errorCode != SocketError.Success){
1862                 throw new SocketException(errorCode);
1863             }
1864             return bytesTransferred;
1865         }
1866
1867 #if !MONO
1868         public int Receive(IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode) {
1869             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "Receive", "");
1870             if (CleanedUp) {
1871                 throw new ObjectDisposedException(this.GetType().FullName);
1872             }
1873
1874             if (buffers==null) {
1875                throw new ArgumentNullException("buffers");
1876             }
1877
1878             if(buffers.Count == 0){
1879                 throw new ArgumentException(SR.GetString(SR.net_sockets_zerolist,"buffers"), "buffers");
1880             }
1881
1882
1883             ValidateBlockingMode();
1884             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Receive() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " DST:" + ValidationHelper.ToString(RemoteEndPoint));
1885
1886             //make sure we don't let the app mess up the buffer array enough to cause
1887             //corruption.
1888             int count = buffers.Count;
1889             WSABuffer[] WSABuffers = new WSABuffer[count];
1890             GCHandle[] objectsToPin = null;
1891             int bytesTransferred;
1892             errorCode = SocketError.Success;
1893
1894             try {
1895                 objectsToPin = new GCHandle[count];
1896                 for (int i = 0; i < count; ++i)
1897                 {
1898                     ArraySegment<byte> buffer = buffers[i];
1899                     ValidationHelper.ValidateSegment(buffer);
1900                     objectsToPin[i] = GCHandle.Alloc(buffer.Array, GCHandleType.Pinned);
1901                     WSABuffers[i].Length = buffer.Count;
1902                     WSABuffers[i].Pointer = Marshal.UnsafeAddrOfPinnedArrayElement(buffer.Array, buffer.Offset);
1903                 }
1904
1905                 // This can throw ObjectDisposedException.
1906                 errorCode = UnsafeNclNativeMethods.OSSOCK.WSARecv_Blocking(
1907                     m_Handle.DangerousGetHandle(),
1908                     WSABuffers,
1909                     count,
1910                     out bytesTransferred,
1911                     ref socketFlags,
1912                     SafeNativeOverlapped.Zero,
1913                     IntPtr.Zero );
1914
1915                 if ((SocketError)errorCode==SocketError.SocketError) {
1916                     errorCode = (SocketError)Marshal.GetLastWin32Error();
1917                 }
1918 #if TRAVE
1919                 try
1920                 {
1921                     GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Receive() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " DST:" + ValidationHelper.ToString(RemoteEndPoint) + " UnsafeNclNativeMethods.OSSOCK.send returns errorCode:" + errorCode + " bytesTransferred:" + bytesTransferred);
1922                 }
1923                 catch (ObjectDisposedException) { }
1924 #endif
1925             }
1926             finally {
1927                 if (objectsToPin != null)
1928                     for (int i = 0; i < objectsToPin.Length; ++i)
1929                         if (objectsToPin[i].IsAllocated)
1930                             objectsToPin[i].Free();
1931             }
1932
1933             if (errorCode != SocketError.Success) {
1934                 //
1935                 // update our internal state after this socket error and throw
1936                 //
1937                 UpdateStatusAfterSocketError(errorCode);
1938                 if(s_LoggingEnabled){
1939                     Logging.Exception(Logging.Sockets, this, "Receive", new SocketException(errorCode));
1940                     Logging.Exit(Logging.Sockets, this, "Receive", 0);
1941                 }
1942                 return 0;
1943             }
1944
1945
1946
1947 #if !FEATURE_PAL // perfcounter
1948             if (s_PerfCountersEnabled)
1949             {
1950                 bool peek = ((int)socketFlags & (int)SocketFlags.Peek)!=0;
1951
1952                 if (bytesTransferred>0 && !peek) {
1953                     NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketBytesReceived, bytesTransferred);
1954                     if (Transport==TransportType.Udp) {
1955                         NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketDatagramsReceived);
1956                     }
1957                 }
1958             }
1959 #endif //!FEATURE_PAL
1960
1961 #if TRAVE
1962             try
1963             {
1964                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Receive() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " DST:" + ValidationHelper.ToString(RemoteEndPoint) + " bytesTransferred:" + bytesTransferred);
1965             }
1966             catch (ObjectDisposedException) { }
1967 #endif
1968
1969             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "Receive", bytesTransferred);
1970
1971             return bytesTransferred;
1972         }
1973
1974
1975
1976
1977         /// <devdoc>
1978         ///    <para>Receives a datagram into a specific location in the data buffer and stores
1979         ///       the end point.</para>
1980         /// </devdoc>
1981         public int ReceiveMessageFrom(byte[] buffer, int offset, int size, ref SocketFlags socketFlags, ref EndPoint remoteEP, out IPPacketInformation ipPacketInformation) {
1982             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "ReceiveMessageFrom", "");
1983
1984             if (CleanedUp) {
1985                 throw new ObjectDisposedException(this.GetType().FullName);
1986             }
1987             if (buffer==null) {
1988                 throw new ArgumentNullException("buffer");
1989             }
1990             if (remoteEP==null) {
1991                 throw new ArgumentNullException("remoteEP");
1992             }
1993             if (!CanTryAddressFamily(remoteEP.AddressFamily)) {
1994                 throw new ArgumentException(SR.GetString(SR.net_InvalidEndPointAddressFamily, 
1995                     remoteEP.AddressFamily, addressFamily), "remoteEP");
1996             }
1997             if (offset<0 || offset>buffer.Length) {
1998                 throw new ArgumentOutOfRangeException("offset");
1999             }
2000             if (size<0 || size>buffer.Length-offset) {
2001                 throw new ArgumentOutOfRangeException("size");
2002             }
2003             if (m_RightEndPoint==null) {
2004                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustbind));
2005             }
2006
2007
2008             ValidateBlockingMode();
2009
2010             // We don't do a CAS demand here because the contents of remoteEP aren't used by
2011             // WSARecvMsg; all that matters is that we generate a unique-to-this-call SocketAddress
2012             // with the right address family
2013             EndPoint endPointSnapshot = remoteEP;
2014             SocketAddress socketAddress = SnapshotAndSerialize(ref endPointSnapshot);
2015
2016             ReceiveMessageOverlappedAsyncResult asyncResult = new ReceiveMessageOverlappedAsyncResult(this,null,null);
2017             asyncResult.SetUnmanagedStructures(buffer, offset, size, socketAddress, socketFlags);
2018
2019             // save a copy of the original EndPoint
2020             SocketAddress socketAddressOriginal = endPointSnapshot.Serialize();
2021
2022             //setup structure
2023             int bytesTransfered = 0;
2024             SocketError errorCode = SocketError.Success;
2025
2026             SetReceivingPacketInformation();
2027
2028             try
2029             {
2030                 // This can throw ObjectDisposedException (retrieving the delegate AND resolving the handle).
2031                 if (WSARecvMsg_Blocking(
2032                     m_Handle.DangerousGetHandle(),
2033                     Marshal.UnsafeAddrOfPinnedArrayElement(asyncResult.m_MessageBuffer,0),
2034                     out bytesTransfered,
2035                     IntPtr.Zero,
2036                     IntPtr.Zero) == SocketError.SocketError)
2037                 {
2038                     errorCode =  (SocketError)Marshal.GetLastWin32Error();
2039                 }
2040             }
2041             finally {
2042                 asyncResult.SyncReleaseUnmanagedStructures();
2043             }
2044
2045
2046             //
2047             // if the native call fails we'll throw a SocketException
2048             //
2049             if (errorCode!=SocketError.Success && errorCode != SocketError.MessageSize) {
2050                 //
2051                 // update our internal state after this socket error and throw
2052                 //
2053                 SocketException socketException = new SocketException(errorCode);
2054                 UpdateStatusAfterSocketError(socketException);
2055                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "ReceiveMessageFrom", socketException);
2056                 throw socketException;
2057             }
2058
2059
2060             if (!socketAddressOriginal.Equals(asyncResult.m_SocketAddress))
2061             {
2062                 try {
2063                     remoteEP = endPointSnapshot.Create(asyncResult.m_SocketAddress);
2064                 }
2065                 catch {
2066                 }
2067                 if (m_RightEndPoint==null) {
2068                     //
2069                     // save a copy of the EndPoint so we can use it for Create()
2070                     //
2071                     m_RightEndPoint = endPointSnapshot;
2072                 }
2073             }
2074
2075             socketFlags = asyncResult.m_flags;
2076             ipPacketInformation = asyncResult.m_IPPacketInformation;
2077
2078             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "ReceiveMessageFrom", errorCode);
2079             return bytesTransfered;
2080         }
2081
2082         /// <devdoc>
2083         ///    <para>Receives a datagram into a specific location in the data buffer and stores
2084         ///       the end point.</para>
2085         /// </devdoc>
2086         public int ReceiveFrom(byte[] buffer, int offset, int size, SocketFlags socketFlags, ref EndPoint remoteEP) {
2087             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "ReceiveFrom", "");
2088             if (CleanedUp) {
2089                 throw new ObjectDisposedException(this.GetType().FullName);
2090             }
2091             //
2092             // parameter validation
2093             //
2094             if (buffer==null) {
2095                 throw new ArgumentNullException("buffer");
2096             }
2097             if (remoteEP==null) {
2098                 throw new ArgumentNullException("remoteEP");
2099             }
2100             if (!CanTryAddressFamily(remoteEP.AddressFamily)) {
2101                 throw new ArgumentException(SR.GetString(SR.net_InvalidEndPointAddressFamily, 
2102                     remoteEP.AddressFamily, addressFamily), "remoteEP");
2103             }
2104             if (offset<0 || offset>buffer.Length) {
2105                 throw new ArgumentOutOfRangeException("offset");
2106             }
2107             if (size<0 || size>buffer.Length-offset) {
2108                 throw new ArgumentOutOfRangeException("size");
2109             }
2110             if (m_RightEndPoint==null) {
2111                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustbind));
2112             }
2113
2114
2115             ValidateBlockingMode();
2116             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::ReceiveFrom() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " size:" + size + " remoteEP:" + remoteEP.ToString());
2117
2118             // We don't do a CAS demand here because the contents of remoteEP aren't used by
2119             // WSARecvFrom; all that matters is that we generate a unique-to-this-call SocketAddress
2120             // with the right address family
2121             EndPoint endPointSnapshot = remoteEP;
2122             SocketAddress socketAddress = SnapshotAndSerialize(ref endPointSnapshot);
2123             SocketAddress socketAddressOriginal = endPointSnapshot.Serialize();
2124
2125             // This can throw ObjectDisposedException.
2126             int bytesTransferred;
2127             unsafe {
2128                 if (buffer.Length == 0)
2129                     bytesTransferred = UnsafeNclNativeMethods.OSSOCK.recvfrom(m_Handle.DangerousGetHandle(), null, 0, socketFlags, socketAddress.m_Buffer, ref socketAddress.m_Size );
2130                 else fixed (byte* pinnedBuffer = buffer) {
2131                     bytesTransferred = UnsafeNclNativeMethods.OSSOCK.recvfrom(m_Handle.DangerousGetHandle(), pinnedBuffer+offset, size, socketFlags, socketAddress.m_Buffer, ref socketAddress.m_Size );
2132                 }
2133             }
2134
2135             // If the native call fails we'll throw a SocketException.
2136             // Must do this immediately after the native call so that the SocketException() constructor can pick up the error code.
2137             SocketException socketException = null;
2138             if ((SocketError) bytesTransferred == SocketError.SocketError)
2139             {
2140                 socketException = new SocketException();
2141                 UpdateStatusAfterSocketError(socketException);
2142                 if (s_LoggingEnabled) Logging.Exception(Logging.Sockets, this, "ReceiveFrom", socketException);
2143                 
2144                 if(socketException.ErrorCode != (int)SocketError.MessageSize){
2145                     throw socketException;
2146                 }
2147             }
2148
2149             if (!socketAddressOriginal.Equals(socketAddress)) {
2150                 try {
2151                     remoteEP = endPointSnapshot.Create(socketAddress);
2152                 }
2153                 catch {
2154                 }
2155                 if (m_RightEndPoint==null) {
2156                     //
2157                     // save a copy of the EndPoint so we can use it for Create()
2158                     //
2159                     m_RightEndPoint = endPointSnapshot;
2160                 }
2161             }
2162
2163             if(socketException != null){
2164                 throw socketException;
2165             }
2166
2167
2168 #if !FEATURE_PAL // perfcounter
2169             if (s_PerfCountersEnabled)
2170             {
2171                 if (bytesTransferred>0) {
2172                     NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketBytesReceived, bytesTransferred);
2173                     if (Transport==TransportType.Udp) {
2174                         NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketDatagramsReceived);
2175                     }
2176                 }
2177             }
2178 #endif //!FEATURE_PAL
2179             GlobalLog.Dump(buffer, offset, bytesTransferred);
2180
2181             if(s_LoggingEnabled)Logging.Dump(Logging.Sockets, this, "ReceiveFrom", buffer, offset, size);
2182             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "ReceiveFrom", bytesTransferred);
2183             return bytesTransferred;
2184         }
2185 #endif // !MONO
2186
2187         /// <devdoc>
2188         ///    <para>Receives a datagram and stores the source end point.</para>
2189         /// </devdoc>
2190         public int ReceiveFrom(byte[] buffer, int size, SocketFlags socketFlags, ref EndPoint remoteEP) {
2191             return ReceiveFrom(buffer, 0, size, socketFlags, ref remoteEP);
2192         }
2193         /// <devdoc>
2194         ///    <para>[To be supplied.]</para>
2195         /// </devdoc>
2196         public int ReceiveFrom(byte[] buffer, SocketFlags socketFlags, ref EndPoint remoteEP) {
2197             return ReceiveFrom(buffer, 0, buffer!=null ? buffer.Length : 0, socketFlags, ref remoteEP);
2198         }
2199         /// <devdoc>
2200         ///    <para>[To be supplied.]</para>
2201         /// </devdoc>
2202         public int ReceiveFrom(byte[] buffer, ref EndPoint remoteEP) {
2203             return ReceiveFrom(buffer, 0, buffer!=null ? buffer.Length : 0, SocketFlags.None, ref remoteEP);
2204         }
2205
2206 #if !MONO
2207         // UE
2208         /// <devdoc>
2209         ///    <para>[To be supplied.]</para>
2210         /// </devdoc>
2211         public int IOControl(int ioControlCode, byte[] optionInValue, byte[] optionOutValue) {
2212             if (CleanedUp) {
2213                 throw new ObjectDisposedException(this.GetType().FullName);
2214             }
2215             if (ioControlCode==IoctlSocketConstants.FIONBIO) {
2216                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_useblocking));
2217             }
2218
2219             ExceptionHelper.UnmanagedPermission.Demand();
2220
2221             int realOptionLength = 0;
2222
2223             // This can throw ObjectDisposedException.
2224             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.WSAIoctl_Blocking(
2225                 m_Handle.DangerousGetHandle(),
2226                 ioControlCode,
2227                 optionInValue,
2228                 optionInValue!=null ? optionInValue.Length : 0,
2229                 optionOutValue,
2230                 optionOutValue!=null ? optionOutValue.Length : 0,
2231                 out realOptionLength,
2232                 SafeNativeOverlapped.Zero,
2233                 IntPtr.Zero);
2234
2235             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::IOControl() UnsafeNclNativeMethods.OSSOCK.WSAIoctl returns errorCode:" + errorCode);
2236
2237             //
2238             // if the native call fails we'll throw a SocketException
2239             //
2240             if (errorCode==SocketError.SocketError) {
2241                 //
2242                 // update our internal state after this socket error and throw
2243                 //
2244                 SocketException socketException = new SocketException();
2245                 UpdateStatusAfterSocketError(socketException);
2246                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "IOControl", socketException);
2247                 throw socketException;
2248             }
2249
2250             return realOptionLength;
2251         }
2252 #endif // !MONO
2253
2254         // UE
2255         /// <devdoc>
2256         ///    <para>[To be supplied.]</para>
2257         /// </devdoc>
2258         public int IOControl(IOControlCode ioControlCode, byte[] optionInValue, byte[] optionOutValue) {
2259             return IOControl(unchecked((int)ioControlCode),optionInValue,optionOutValue);
2260         }
2261
2262 #if !MONO
2263         internal int IOControl( IOControlCode ioControlCode, 
2264                                                                         IntPtr optionInValue, 
2265                                                                         int inValueSize,
2266                                                                         IntPtr optionOutValue,
2267                                                                         int outValueSize) 
2268                 {
2269             if (CleanedUp) {
2270                 throw new ObjectDisposedException(this.GetType().FullName);
2271             }
2272             if ( (unchecked((int)ioControlCode)) ==IoctlSocketConstants.FIONBIO) {
2273                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_useblocking));
2274             }
2275
2276             int realOptionLength = 0;
2277
2278             // This can throw ObjectDisposedException.
2279             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.WSAIoctl_Blocking_Internal(
2280                 m_Handle.DangerousGetHandle(),
2281                 (uint)ioControlCode,
2282                 optionInValue,
2283                                 inValueSize,
2284                 optionOutValue,
2285                                 outValueSize,
2286                 out realOptionLength,
2287                 SafeNativeOverlapped.Zero,
2288                 IntPtr.Zero);
2289
2290             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::IOControl() UnsafeNclNativeMethods.OSSOCK.WSAIoctl returns errorCode:" + errorCode);
2291
2292             //
2293             // if the native call fails we'll throw a SocketException
2294             //
2295             if (errorCode==SocketError.SocketError) {
2296                 //
2297                 // update our internal state after this socket error and throw
2298                 //
2299                 SocketException socketException = new SocketException();
2300                 UpdateStatusAfterSocketError(socketException);
2301                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "IOControl", socketException);
2302                 throw socketException;
2303             }
2304
2305             return realOptionLength;
2306         }
2307 #endif // !MONO
2308
2309         public void SetIPProtectionLevel(IPProtectionLevel level) {
2310             if (level == IPProtectionLevel.Unspecified) {
2311                 throw new ArgumentException(SR.GetString(SR.net_sockets_invalid_optionValue_all), "level");
2312             }
2313
2314             if (addressFamily == AddressFamily.InterNetworkV6) {
2315                 SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPProtectionLevel, (int)level);
2316             }
2317             else if (addressFamily == AddressFamily.InterNetwork) {
2318                 SetSocketOption(SocketOptionLevel.IP, SocketOptionName.IPProtectionLevel, (int)level);
2319             }
2320             else {
2321                 throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
2322             }
2323         }
2324
2325 #if !MONO
2326         /// <devdoc>
2327         ///    <para>
2328         ///       Sets the specified option to the specified value.
2329         ///    </para>
2330         /// </devdoc>
2331         public void SetSocketOption(SocketOptionLevel optionLevel, SocketOptionName optionName, int optionValue) {
2332             if (CleanedUp) {
2333                 throw new ObjectDisposedException(this.GetType().FullName);
2334             }
2335             CheckSetOptionPermissions(optionLevel, optionName);
2336             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SetSocketOption(): optionLevel:" + optionLevel.ToString() + " optionName:" + optionName.ToString() + " optionValue:" + optionValue.ToString());
2337             SetSocketOption(optionLevel, optionName, optionValue, false);
2338         }
2339
2340
2341         /// <devdoc>
2342         ///    <para>[To be supplied.]</para>
2343         /// </devdoc>
2344         public void SetSocketOption(SocketOptionLevel optionLevel, SocketOptionName optionName, byte[] optionValue) {
2345             if (CleanedUp) {
2346                 throw new ObjectDisposedException(this.GetType().FullName);
2347             }
2348
2349             CheckSetOptionPermissions(optionLevel, optionName);
2350
2351             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SetSocketOption(): optionLevel:" + optionLevel.ToString() + " optionName:" + optionName.ToString() + " optionValue:" + optionValue.ToString());
2352
2353             // This can throw ObjectDisposedException.
2354             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.setsockopt(
2355                 m_Handle,
2356                 optionLevel,
2357                 optionName,
2358                 optionValue,
2359                 optionValue != null ? optionValue.Length : 0);
2360
2361             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SetSocketOption() UnsafeNclNativeMethods.OSSOCK.setsockopt returns errorCode:" + errorCode);
2362
2363             //
2364             // if the native call fails we'll throw a SocketException
2365             //
2366             if (errorCode==SocketError.SocketError) {
2367                 //
2368                 // update our internal state after this socket error and throw
2369                 //
2370                 SocketException socketException = new SocketException();
2371                 UpdateStatusAfterSocketError(socketException);
2372                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "SetSocketOption", socketException);
2373                 throw socketException;
2374             }
2375         }
2376
2377         /// <devdoc>
2378         ///    <para>Sets the specified option to the specified value.</para>
2379         /// </devdoc>
2380
2381         public void SetSocketOption(SocketOptionLevel optionLevel, SocketOptionName optionName, bool optionValue) {
2382             SetSocketOption(optionLevel,optionName,(optionValue?1:0));
2383         }
2384
2385         /// <devdoc>
2386         ///    <para>Sets the specified option to the specified value.</para>
2387         /// </devdoc>
2388         public void SetSocketOption(SocketOptionLevel optionLevel, SocketOptionName optionName, object optionValue) {
2389             if (CleanedUp) {
2390                 throw new ObjectDisposedException(this.GetType().FullName);
2391             }
2392             //
2393             // parameter validation
2394             //
2395             if (optionValue==null) {
2396                 throw new ArgumentNullException("optionValue");
2397             }
2398
2399             CheckSetOptionPermissions(optionLevel, optionName);
2400
2401             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SetSocketOption(): optionLevel:" + optionLevel.ToString() + " optionName:" + optionName.ToString() + " optionValue:" + optionValue.ToString());
2402
2403             if (optionLevel==SocketOptionLevel.Socket && optionName==SocketOptionName.Linger) {
2404                 LingerOption lingerOption = optionValue as LingerOption;
2405                 if (lingerOption==null) {
2406                     throw new ArgumentException(SR.GetString(SR.net_sockets_invalid_optionValue, "LingerOption"), "optionValue");
2407                 }
2408                 if (lingerOption.LingerTime < 0 || lingerOption.LingerTime>(int)UInt16.MaxValue) {
2409                     throw new ArgumentException(SR.GetString(SR.ArgumentOutOfRange_Bounds_Lower_Upper, 0, (int)UInt16.MaxValue), "optionValue.LingerTime");
2410                 }
2411                 setLingerOption(lingerOption);
2412             }
2413             else if (optionLevel==SocketOptionLevel.IP && (optionName==SocketOptionName.AddMembership || optionName==SocketOptionName.DropMembership)) {
2414                 MulticastOption multicastOption = optionValue as MulticastOption;
2415                 if (multicastOption==null) {
2416                     throw new ArgumentException(SR.GetString(SR.net_sockets_invalid_optionValue, "MulticastOption"), "optionValue");
2417                 }
2418                 setMulticastOption(optionName, multicastOption);
2419             }
2420             //
2421             // IPv6 Changes: Handle IPv6 Multicast Add / Drop
2422             //
2423             else if (optionLevel==SocketOptionLevel.IPv6 && (optionName==SocketOptionName.AddMembership || optionName==SocketOptionName.DropMembership)) {
2424                 IPv6MulticastOption multicastOption = optionValue as IPv6MulticastOption;
2425                 if (multicastOption==null) {
2426                     throw new ArgumentException(SR.GetString(SR.net_sockets_invalid_optionValue, "IPv6MulticastOption"), "optionValue");
2427                 }
2428                 setIPv6MulticastOption(optionName, multicastOption);
2429             }
2430             else {
2431                 throw new ArgumentException(SR.GetString(SR.net_sockets_invalid_optionValue_all), "optionValue");
2432             }
2433         }
2434
2435
2436         /// <devdoc>
2437         ///    <para>
2438         ///       Gets the value of a socket option.
2439         ///    </para>
2440         /// </devdoc>
2441         // UE
2442         public object GetSocketOption(SocketOptionLevel optionLevel, SocketOptionName optionName) {
2443             if (CleanedUp) {
2444                 throw new ObjectDisposedException(this.GetType().FullName);
2445             }
2446             if (optionLevel==SocketOptionLevel.Socket && optionName==SocketOptionName.Linger) {
2447                 return getLingerOpt();
2448             }
2449             else if (optionLevel==SocketOptionLevel.IP && (optionName==SocketOptionName.AddMembership || optionName==SocketOptionName.DropMembership)) {
2450                 return getMulticastOpt(optionName);
2451             }
2452             //
2453             // Handle IPv6 case
2454             //
2455             else if (optionLevel==SocketOptionLevel.IPv6 && (optionName==SocketOptionName.AddMembership || optionName==SocketOptionName.DropMembership)) {
2456                 return getIPv6MulticastOpt(optionName);
2457             }
2458             else {
2459                 int optionValue = 0;
2460                 int optionLength = 4;
2461
2462                 // This can throw ObjectDisposedException.
2463                 SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.getsockopt(
2464                     m_Handle,
2465                     optionLevel,
2466                     optionName,
2467                     out optionValue,
2468                     ref optionLength);
2469
2470                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::GetSocketOption() UnsafeNclNativeMethods.OSSOCK.getsockopt returns errorCode:" + errorCode);
2471
2472                 //
2473                 // if the native call fails we'll throw a SocketException
2474                 //
2475                 if (errorCode==SocketError.SocketError) {
2476                     //
2477                     // update our internal state after this socket error and throw
2478                     //
2479                     SocketException socketException = new SocketException();
2480                     UpdateStatusAfterSocketError(socketException);
2481                     if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "GetSocketOption", socketException);
2482                     throw socketException;
2483                 }
2484
2485                 return optionValue;
2486             }
2487         }
2488
2489         // UE
2490         /// <devdoc>
2491         ///    <para>[To be supplied.]</para>
2492         /// </devdoc>
2493         public void GetSocketOption(SocketOptionLevel optionLevel, SocketOptionName optionName, byte[] optionValue) {
2494             if (CleanedUp) {
2495                 throw new ObjectDisposedException(this.GetType().FullName);
2496             }
2497
2498             int optionLength = optionValue!=null ? optionValue.Length : 0;
2499
2500             // This can throw ObjectDisposedException.
2501             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.getsockopt(
2502                 m_Handle,
2503                 optionLevel,
2504                 optionName,
2505                 optionValue,
2506                 ref optionLength);
2507
2508             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::GetSocketOption() UnsafeNclNativeMethods.OSSOCK.getsockopt returns errorCode:" + errorCode);
2509
2510             //
2511             // if the native call fails we'll throw a SocketException
2512             //
2513             if (errorCode==SocketError.SocketError) {
2514                 //
2515                 // update our internal state after this socket error and throw
2516                 //
2517                 SocketException socketException = new SocketException();
2518                 UpdateStatusAfterSocketError(socketException);
2519                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "GetSocketOption", socketException);
2520                 throw socketException;
2521             }
2522         }
2523
2524         // UE
2525         /// <devdoc>
2526         ///    <para>[To be supplied.]</para>
2527         /// </devdoc>
2528         public byte[] GetSocketOption(SocketOptionLevel optionLevel, SocketOptionName optionName, int optionLength) {
2529             if (CleanedUp) {
2530                 throw new ObjectDisposedException(this.GetType().FullName);
2531             }
2532
2533             byte[] optionValue = new byte[optionLength];
2534             int realOptionLength = optionLength;
2535
2536             // This can throw ObjectDisposedException.
2537             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.getsockopt(
2538                 m_Handle,
2539                 optionLevel,
2540                 optionName,
2541                 optionValue,
2542                 ref realOptionLength);
2543
2544             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::GetSocketOption() UnsafeNclNativeMethods.OSSOCK.getsockopt returns errorCode:" + errorCode);
2545
2546             //
2547             // if the native call fails we'll throw a SocketException
2548             //
2549             if (errorCode==SocketError.SocketError) {
2550                 //
2551                 // update our internal state after this socket error and throw
2552                 //
2553                 SocketException socketException = new SocketException();
2554                 UpdateStatusAfterSocketError(socketException);
2555                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "GetSocketOption", socketException);
2556                 throw socketException;
2557             }
2558
2559             if (optionLength!=realOptionLength) {
2560                 byte[] newOptionValue = new byte[realOptionLength];
2561                 Buffer.BlockCopy(optionValue, 0, newOptionValue, 0, realOptionLength);
2562                 optionValue = newOptionValue;
2563             }
2564
2565             return optionValue;
2566         }
2567
2568
2569         /// <devdoc>
2570         ///    <para>
2571         ///       Determines the status of the socket.
2572         ///    </para>
2573         /// </devdoc>
2574         public bool Poll(int microSeconds, SelectMode mode) {
2575             if (CleanedUp) {
2576                 throw new ObjectDisposedException(this.GetType().FullName);
2577             }
2578
2579             IntPtr handle = m_Handle.DangerousGetHandle();
2580             IntPtr[] fileDescriptorSet = new IntPtr[2] { (IntPtr) 1, handle };
2581             TimeValue IOwait = new TimeValue();
2582
2583             //
2584             // negative timeout value implies indefinite wait
2585             //
2586             int socketCount;
2587             if (microSeconds != -1) {
2588                 MicrosecondsToTimeValue((long)(uint)microSeconds, ref IOwait);
2589                 socketCount =
2590                     UnsafeNclNativeMethods.OSSOCK.select(
2591                         0,
2592                         mode==SelectMode.SelectRead ? fileDescriptorSet : null,
2593                         mode==SelectMode.SelectWrite ? fileDescriptorSet : null,
2594                         mode==SelectMode.SelectError ? fileDescriptorSet : null,
2595                         ref IOwait);
2596             }
2597             else {
2598                 socketCount =
2599                     UnsafeNclNativeMethods.OSSOCK.select(
2600                         0,
2601                         mode==SelectMode.SelectRead ? fileDescriptorSet : null,
2602                         mode==SelectMode.SelectWrite ? fileDescriptorSet : null,
2603                         mode==SelectMode.SelectError ? fileDescriptorSet : null,
2604                         IntPtr.Zero);
2605             }
2606             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Poll() UnsafeNclNativeMethods.OSSOCK.select returns socketCount:" + socketCount);
2607
2608             //
2609             // if the native call fails we'll throw a SocketException
2610             //
2611             if ((SocketError)socketCount==SocketError.SocketError) {
2612                 //
2613                 // update our internal state after this socket error and throw
2614                 //
2615                 SocketException socketException = new SocketException();
2616                 UpdateStatusAfterSocketError(socketException);
2617                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "Poll", socketException);
2618                 throw socketException;
2619             }
2620             if ((int)fileDescriptorSet[0]==0) {
2621                 return false;
2622             }
2623             return fileDescriptorSet[1] == handle;
2624         }
2625
2626         /// <devdoc>
2627         ///    <para>Determines the status of a socket.</para>
2628         /// </devdoc>
2629         public static void Select(IList checkRead, IList checkWrite, IList checkError, int microSeconds) {
2630             // parameter validation
2631             if ((checkRead==null || checkRead.Count==0) && (checkWrite==null || checkWrite.Count==0) && (checkError==null || checkError.Count==0)) {
2632                 throw new ArgumentNullException(SR.GetString(SR.net_sockets_empty_select));
2633             }
2634             const int MaxSelect = 65536;
2635             if (checkRead!=null && checkRead.Count>MaxSelect) {
2636                 throw new ArgumentOutOfRangeException("checkRead", SR.GetString(SR.net_sockets_toolarge_select, "checkRead", MaxSelect.ToString(NumberFormatInfo.CurrentInfo)));
2637             }
2638             if (checkWrite!=null && checkWrite.Count>MaxSelect) {
2639                 throw new ArgumentOutOfRangeException("checkWrite", SR.GetString(SR.net_sockets_toolarge_select, "checkWrite", MaxSelect.ToString(NumberFormatInfo.CurrentInfo)));
2640             }
2641             if (checkError!=null && checkError.Count>MaxSelect) {
2642                 throw new ArgumentOutOfRangeException("checkError", SR.GetString(SR.net_sockets_toolarge_select, "checkError", MaxSelect.ToString(NumberFormatInfo.CurrentInfo)));
2643             }
2644             IntPtr[] readfileDescriptorSet   = SocketListToFileDescriptorSet(checkRead);
2645             IntPtr[] writefileDescriptorSet  = SocketListToFileDescriptorSet(checkWrite);
2646             IntPtr[] errfileDescriptorSet    = SocketListToFileDescriptorSet(checkError);
2647
2648             // This code used to erroneously pass a non-null timeval structure containing zeroes 
2649             // to select() when the caller specified (-1) for the microseconds parameter.  That 
2650             // caused select to actually have a *zero* timeout instead of an infinite timeout
2651             // turning the operation into a non-blocking poll.
2652             //
2653             // Now we pass a null timeval struct when microseconds is (-1).
2654             // 
2655             // Negative microsecond values that weren't exactly (-1) were originally successfully 
2656             // converted to a timeval struct containing unsigned non-zero integers.  This code 
2657             // retains that behavior so that any app working around the original bug with, 
2658             // for example, (-2) specified for microseconds, will continue to get the same behavior.
2659
2660             int socketCount;
2661
2662             if (microSeconds != -1) {
2663                 TimeValue IOwait = new TimeValue();
2664                 MicrosecondsToTimeValue((long)(uint)microSeconds, ref IOwait);
2665
2666                 socketCount =
2667                     UnsafeNclNativeMethods.OSSOCK.select(
2668                         0, // ignored value
2669                         readfileDescriptorSet,
2670                         writefileDescriptorSet,
2671                         errfileDescriptorSet,
2672                         ref IOwait);
2673             }
2674             else {
2675                 socketCount =
2676                     UnsafeNclNativeMethods.OSSOCK.select(
2677                         0, // ignored value
2678                         readfileDescriptorSet,
2679                         writefileDescriptorSet,
2680                         errfileDescriptorSet,
2681                         IntPtr.Zero);
2682             }
2683
2684             GlobalLog.Print("Socket::Select() UnsafeNclNativeMethods.OSSOCK.select returns socketCount:" + socketCount);
2685
2686             //
2687             // if the native call fails we'll throw a SocketException
2688             //
2689             if ((SocketError)socketCount==SocketError.SocketError) {
2690                 throw new SocketException();
2691             }
2692             SelectFileDescriptor(checkRead, readfileDescriptorSet);
2693             SelectFileDescriptor(checkWrite, writefileDescriptorSet);
2694             SelectFileDescriptor(checkError, errfileDescriptorSet);
2695         }
2696 #endif // !MONO
2697
2698 #if !FEATURE_PAL
2699         /// <devdoc>
2700         ///    <para>[To be supplied.]</para>
2701         /// </devdoc>
2702
2703         [HostProtection(ExternalThreading=true)]
2704         [ResourceExposure(ResourceScope.Machine)]
2705         [ResourceConsumption(ResourceScope.Machine)]
2706         public IAsyncResult BeginSendFile(
2707             string fileName,
2708             AsyncCallback callback,
2709             object state)
2710         {
2711             return BeginSendFile(fileName,null,null,TransmitFileOptions.UseDefaultWorkerThread,callback,state);
2712         }
2713 #endif
2714
2715 #if !MONO
2716         //
2717         // Async Winsock Support, the following functions use either
2718         //   the Async Winsock support to do overlapped I/O WSASend/WSARecv
2719         //   or a WSAEventSelect call to enable selection and non-blocking mode
2720         //   of otherwise normal Winsock calls.
2721         //
2722         //   Currently the following Async Socket calls are supported:
2723         //      Send, Recv, SendTo, RecvFrom, Connect, Accept
2724         //
2725
2726         /*++
2727
2728         Routine Description:
2729
2730            BeginConnect - Does a async winsock connect, by calling
2731            WSAEventSelect to enable Connect Events to signal an event and
2732            wake up a callback which involkes a callback.
2733
2734             So note: This routine may go pending at which time,
2735             but any case the callback Delegate will be called upon completion
2736
2737         Arguments:
2738
2739            remoteEP - status line that we wish to parse
2740            Callback - Async Callback Delegate that is called upon Async Completion
2741            State - State used to track callback, set by caller, not required
2742
2743         Return Value:
2744
2745            IAsyncResult - Async result used to retreive result
2746
2747         --*/
2748
2749
2750         /// <devdoc>
2751         ///    <para>[To be supplied.]</para>
2752         /// </devdoc>
2753         [HostProtection(ExternalThreading=true)]
2754         public IAsyncResult BeginConnect(EndPoint remoteEP, AsyncCallback callback, object state)
2755         {
2756             //
2757             //  parameter validation
2758             //
2759             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "BeginConnect", remoteEP);
2760
2761             if (CleanedUp) {
2762                 throw new ObjectDisposedException(this.GetType().FullName);
2763             }
2764
2765             if (remoteEP==null) {
2766                 throw new ArgumentNullException("remoteEP");
2767             }
2768
2769             if (isListening)
2770             {
2771                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustnotlisten));
2772             }
2773
2774             DnsEndPoint dnsEP = remoteEP as DnsEndPoint;
2775             if (dnsEP != null) 
2776             {
2777                 if (dnsEP.AddressFamily != AddressFamily.Unspecified && !CanTryAddressFamily(dnsEP.AddressFamily)) 
2778                 {
2779                     throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
2780                 }
2781
2782                 return BeginConnect(dnsEP.Host, dnsEP.Port, callback, state);
2783             }
2784
2785             if (CanUseConnectEx(remoteEP))
2786             {
2787                 return BeginConnectEx(remoteEP, true, callback, state);
2788             }
2789
2790             // This will check the permissions for connect.
2791             EndPoint endPointSnapshot = remoteEP;
2792             SocketAddress socketAddress = CheckCacheRemote(ref endPointSnapshot, true);
2793
2794             // Flow the context.  No need to lock it since we don't use it until the callback.
2795             ConnectAsyncResult asyncResult = new ConnectAsyncResult(this, endPointSnapshot, state, callback);
2796             asyncResult.StartPostingAsyncOp(false);
2797
2798             // Post the connect.
2799             DoBeginConnect(endPointSnapshot, socketAddress, asyncResult);
2800
2801             // We didn't throw, so finish the posting op.  This will call the callback if the operation already completed.
2802             asyncResult.FinishPostingAsyncOp(ref Caches.ConnectClosureCache);
2803
2804             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "BeginConnect", asyncResult);
2805             return asyncResult;
2806         }
2807
2808
2809
2810
2811         public SocketInformation DuplicateAndClose(int targetProcessId){
2812             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "DuplicateAndClose", null);
2813
2814             if (CleanedUp)
2815             {
2816                 throw new ObjectDisposedException(GetType().FullName);
2817             }
2818
2819             ExceptionHelper.UnrestrictedSocketPermission.Demand();
2820
2821             SocketInformation info = new SocketInformation();
2822             info.ProtocolInformation = new byte[protocolInformationSize];
2823
2824             // This can throw ObjectDisposedException.
2825             SocketError errorCode;
2826 #if !FEATURE_PAL
2827             unsafe {
2828                 fixed (byte* pinnedBuffer = info.ProtocolInformation) {
2829                     errorCode = (SocketError) UnsafeNclNativeMethods.OSSOCK.WSADuplicateSocket(m_Handle, (uint)targetProcessId, pinnedBuffer);
2830                 }
2831             }
2832 #else
2833             errorCode = SocketError.SocketError;
2834 #endif // !FEATURE_PAL
2835
2836             if (errorCode!=SocketError.Success) {
2837                 SocketException socketException = new SocketException();
2838                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "DuplicateAndClose", socketException);
2839                 throw socketException;
2840             }
2841
2842
2843             info.IsConnected = Connected;
2844             info.IsNonBlocking = !Blocking;
2845             info.IsListening = isListening;
2846             info.UseOnlyOverlappedIO = UseOnlyOverlappedIO;
2847             info.RemoteEndPoint = m_RemoteEndPoint;
2848
2849             //make sure we don't shutdown, etc.
2850             Close(-1);
2851
2852             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "DuplicateAndClose", null);
2853             return info;
2854         }
2855
2856
2857
2858
2859         internal IAsyncResult UnsafeBeginConnect(EndPoint remoteEP, AsyncCallback callback, object state)
2860         {
2861             if (CanUseConnectEx(remoteEP))
2862             {
2863                 return BeginConnectEx(remoteEP, false, callback, state);
2864             }
2865             EndPoint endPointSnapshot = remoteEP;
2866             SocketAddress socketAddress = SnapshotAndSerialize(ref endPointSnapshot);
2867
2868             // No context flow here.  Can use Lazy.
2869             ConnectAsyncResult asyncResult = new ConnectAsyncResult(this, endPointSnapshot, state, callback);
2870             DoBeginConnect(endPointSnapshot, socketAddress, asyncResult);
2871             return asyncResult;
2872         }
2873
2874         // Leaving the public logging as "BeginConnect" since that makes sense to the people looking at the output.
2875         // Private logging can remain "DoBeginConnect".
2876         private void DoBeginConnect(EndPoint endPointSnapshot, SocketAddress socketAddress, LazyAsyncResult asyncResult)
2877         {
2878             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginConnect() endPointSnapshot:" + endPointSnapshot.ToString());
2879
2880             EndPoint oldEndPoint = m_RightEndPoint;
2881             
2882             // get async going
2883             if (m_AcceptQueueOrConnectResult != null)
2884             {
2885                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_no_duplicate_async));
2886             }
2887
2888             m_AcceptQueueOrConnectResult = asyncResult;
2889
2890             if (!SetAsyncEventSelect(AsyncEventBits.FdConnect)){
2891                 m_AcceptQueueOrConnectResult = null;
2892                 throw new ObjectDisposedException(this.GetType().FullName);
2893             }
2894             
2895             // This can throw ObjectDisposedException.
2896             IntPtr handle = m_Handle.DangerousGetHandle();
2897
2898             //we should fix this in Whidbey.
2899             if (m_RightEndPoint == null) {
2900                   m_RightEndPoint = endPointSnapshot;
2901             }
2902
2903             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.WSAConnect(
2904                 handle,
2905                 socketAddress.m_Buffer,
2906                 socketAddress.m_Size,
2907                 IntPtr.Zero,
2908                 IntPtr.Zero,
2909                 IntPtr.Zero,
2910                 IntPtr.Zero);
2911
2912             if (errorCode!=SocketError.Success) {
2913                 errorCode = (SocketError)Marshal.GetLastWin32Error();
2914             }
2915             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginConnect() UnsafeNclNativeMethods.OSSOCK.WSAConnect returns errorCode:" + errorCode);
2916
2917             if (errorCode != SocketError.WouldBlock)
2918             {
2919                 bool completeSynchronously = true;
2920                 if (errorCode == SocketError.Success)
2921                 {
2922                     SetToConnected();
2923                 }
2924                 else
2925                 {
2926                     asyncResult.ErrorCode = (int) errorCode;
2927                 }
2928
2929                 // Using interlocked to avoid a race condition with RegisteredWaitCallback
2930                 // Although UnsetAsyncEventSelect() below should cancel the callback, but 
2931                 // it may already be in progress and therefore resulting in simultaneous
2932                 // registeredWaitCallback calling ConnectCallback() and the synchronous
2933                 // completion here.
2934                 if (Interlocked.Exchange(ref m_RegisteredWait, null) == null)
2935                     completeSynchronously = false;
2936                 //
2937                 // Cancel async event and go back to blocking mode.
2938                 //
2939                 UnsetAsyncEventSelect();
2940
2941                 if (errorCode == SocketError.Success)
2942                 {
2943                     //
2944                     // synchronously complete the IO and call the user's callback.
2945                     //
2946                     if (completeSynchronously)
2947                         asyncResult.InvokeCallback();
2948                 }
2949                 else
2950                 {
2951                     //
2952                     // if the asynchronous native call fails synchronously
2953                     // we'll throw a SocketException
2954                     //
2955                     m_RightEndPoint = oldEndPoint;
2956                     SocketException socketException = new SocketException(errorCode);
2957                     UpdateStatusAfterSocketError(socketException);
2958                     m_AcceptQueueOrConnectResult = null;
2959                     if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "BeginConnect", socketException);
2960                     throw socketException;
2961                 }
2962             }
2963
2964             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginConnect() to:" + endPointSnapshot.ToString() + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
2965         }
2966
2967         // Begin ConnectEx is only supported for connection oriented protocols
2968         // for now this is only supported on win32 platforms.  We need to fix this
2969         // when the getdelegatefrom function methods are available on 64bit.
2970         // to use this, the endpoint must either be an IP endpoint, or the
2971         // socket must already be bound.
2972         private bool CanUseConnectEx(EndPoint remoteEP)
2973         {
2974 #if !FEATURE_PAL
2975             return socketType == SocketType.Stream &&
2976                 (m_RightEndPoint != null || remoteEP.GetType() == typeof(IPEndPoint)) &&
2977                 (Thread.CurrentThread.IsThreadPoolThread || SettingsSectionInternal.Section.AlwaysUseCompletionPortsForConnect || m_IsDisconnected);
2978 #else
2979             return false;
2980 #endif
2981         }
2982
2983         //
2984         // This is the internal callback that will be called when
2985         // the IO we issued for the user to winsock has completed.
2986         // when this function gets called it must:
2987         // 1) update the AsyncResult object with the results of the completed IO
2988         // 2) signal events that the user might be waiting on
2989         // 3) call the callback function that the user might have specified
2990         //
2991         // This method was copied from a ConnectAsyncResult class that became useless.
2992         private void ConnectCallback()
2993         {
2994             LazyAsyncResult asyncResult = (LazyAsyncResult) m_AcceptQueueOrConnectResult;
2995
2996
2997             GlobalLog.Enter("Socket#" + ValidationHelper.HashString(this) + "::ConnectCallback");
2998             //
2999             // If we came here due to a ---- between BeginConnect and Dispose
3000             //
3001             if (asyncResult.InternalPeekCompleted)
3002             {
3003                 GlobalLog.Assert(CleanedUp, "Socket#{0}::ConnectCallback()|asyncResult is compelted but the socket does not have CleanedUp set.", ValidationHelper.HashString(this));
3004                 GlobalLog.Leave("Socket#" + ValidationHelper.HashString(this) + "::ConnectCallback", "Already completed, socket must be closed");
3005                 return;
3006             }
3007
3008
3009             //<
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020             //
3021             // get async completion
3022             //
3023             /*
3024             int errorCode = (int)socket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Error);
3025             GlobalLog.Print("Socket#" + ValidationHelper.HashString(socket) + "::ConnectCallback() GetSocketOption() returns errorCode:" + errorCode.ToString());
3026             */
3027
3028             NetworkEvents networkEvents = new NetworkEvents();
3029             networkEvents.Events = AsyncEventBits.FdConnect;
3030
3031             SocketError errorCode = SocketError.OperationAborted;
3032             object result = null;
3033
3034             try
3035             {
3036                 if (!CleanedUp)
3037                 {
3038                     try
3039                     {
3040                         errorCode = UnsafeNclNativeMethods.OSSOCK.WSAEnumNetworkEvents(
3041                             m_Handle,
3042                             m_AsyncEvent.SafeWaitHandle,
3043                             ref networkEvents);
3044
3045                         if (errorCode != SocketError.Success)
3046                         {
3047                             errorCode = (SocketError) Marshal.GetLastWin32Error();
3048                             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::ConnectCallback() WSAEnumNetworkEvents() failed with errorCode:" + errorCode.ToString());
3049                         }
3050                         else
3051                         {
3052                             errorCode = (SocketError) networkEvents.ErrorCodes[(int) AsyncEventBitsPos.FdConnectBit];
3053                             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::ConnectCallback() ErrorCodes(FdConnect) got errorCode:" + errorCode.ToString());
3054                         }
3055                         //
3056                         // Cancel async event and go back to blocking mode.
3057                         //
3058                         UnsetAsyncEventSelect();
3059                     }
3060                     catch (ObjectDisposedException)
3061                     {
3062                         errorCode = SocketError.OperationAborted;
3063                     }
3064                 }
3065
3066                 //
3067                 // if the native non-blocking call failed we'll throw a SocketException in EndConnect()
3068                 //
3069                 if (errorCode == SocketError.Success)
3070                 {
3071                     //
3072                     // the Socket is connected, update our state and performance counter
3073                     //
3074                     SetToConnected();
3075                 }
3076             }
3077             catch (Exception exception)
3078             {
3079                 if (NclUtilities.IsFatal(exception)) throw;
3080
3081                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::ConnectCallback() caught exception:" + exception.Message + ", CleanedUp:" + CleanedUp);
3082                 result = exception;
3083             }
3084
3085             if (!asyncResult.InternalPeekCompleted)
3086             {
3087                 // A "ErrorCode" concept is questionable, for ex. below lines are subject to a race condition
3088                 asyncResult.ErrorCode = (int) errorCode;
3089                 asyncResult.InvokeCallback(result);
3090             }
3091
3092             GlobalLog.Leave("Socket#" + ValidationHelper.HashString(this) + "::ConnectCallback", errorCode.ToString());
3093         }
3094
3095         [HostProtection(ExternalThreading=true)]
3096         public IAsyncResult BeginConnect(string host, int port, AsyncCallback requestCallback, object state){
3097             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "BeginConnect", host);
3098
3099             if (CleanedUp){
3100                 throw new ObjectDisposedException(this.GetType().FullName);
3101             }
3102
3103             if (host==null) {
3104                 throw new ArgumentNullException("host");
3105             }
3106             if (!ValidationHelper.ValidateTcpPort(port)){
3107                 throw new ArgumentOutOfRangeException("port");
3108             }
3109             if (addressFamily != AddressFamily.InterNetwork && addressFamily != AddressFamily.InterNetworkV6) {
3110                 throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
3111             }
3112
3113             if (isListening)
3114             {
3115                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustnotlisten));
3116             }
3117
3118             // Here, want to flow the context.  No need to lock.
3119             MultipleAddressConnectAsyncResult result = new MultipleAddressConnectAsyncResult(null, port, this, state, requestCallback);
3120             result.StartPostingAsyncOp(false);
3121
3122             IAsyncResult dnsResult = Dns.UnsafeBeginGetHostAddresses(host, new AsyncCallback(DnsCallback), result);
3123             if (dnsResult.CompletedSynchronously)
3124             {
3125                 if (DoDnsCallback(dnsResult, result))
3126                 {
3127                     result.InvokeCallback();
3128                 }
3129             }
3130
3131             // Done posting.
3132             result.FinishPostingAsyncOp(ref Caches.ConnectClosureCache);
3133
3134             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "BeginConnect", result);
3135             return result;
3136         }
3137 #endif // !MONO
3138
3139         [HostProtection(ExternalThreading=true)]
3140         public IAsyncResult BeginConnect(IPAddress address, int port, AsyncCallback requestCallback, object state){
3141             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "BeginConnect", address);
3142             if (CleanedUp){
3143                 throw new ObjectDisposedException(this.GetType().FullName);
3144             }
3145
3146             if (address==null) {
3147                 throw new ArgumentNullException("address");
3148             }
3149             if (!ValidationHelper.ValidateTcpPort(port)){
3150                 throw new ArgumentOutOfRangeException("port");
3151             }
3152             //if address family isn't the socket address family throw
3153             if (!CanTryAddressFamily(address.AddressFamily)) {
3154                 throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
3155             }
3156
3157             IAsyncResult result = BeginConnect(new IPEndPoint(address,port),requestCallback,state);
3158             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "BeginConnect", result);
3159             return result;
3160         }
3161
3162 #if !MONO
3163         [HostProtection(ExternalThreading=true)]
3164         public IAsyncResult BeginConnect(IPAddress[] addresses, int port, AsyncCallback requestCallback, object state)
3165         {
3166             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "BeginConnect", addresses);
3167             if (CleanedUp){
3168                 throw new ObjectDisposedException(this.GetType().FullName);
3169             }
3170
3171             if (addresses==null) {
3172                 throw new ArgumentNullException("addresses");
3173             }
3174             if (addresses.Length == 0) {
3175                 throw new ArgumentException(SR.GetString(SR.net_invalidAddressList), "addresses");
3176             }
3177             if (!ValidationHelper.ValidateTcpPort(port)) {
3178                 throw new ArgumentOutOfRangeException("port");
3179             }
3180             if (addressFamily != AddressFamily.InterNetwork && addressFamily != AddressFamily.InterNetworkV6) {
3181                 throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
3182             }
3183
3184             if (isListening)
3185             {
3186                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustnotlisten));
3187             }
3188
3189             // Set up the result to capture the context.  No need for a lock.
3190             MultipleAddressConnectAsyncResult result = new MultipleAddressConnectAsyncResult(addresses, port, this, state, requestCallback);
3191             result.StartPostingAsyncOp(false);
3192
3193             if (DoMultipleAddressConnectCallback(PostOneBeginConnect(result), result))
3194             {
3195                 // if it completes synchronously, invoke the callback from here
3196                 result.InvokeCallback();
3197             }
3198
3199             // Finished posting async op.  Possibly will call callback.
3200             result.FinishPostingAsyncOp(ref Caches.ConnectClosureCache);
3201
3202             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "BeginConnect", result);
3203             return result;
3204         }
3205
3206         // Supports DisconnectEx - this provides completion port IO and support for
3207         //disconnect and reconnects
3208         [HostProtection(ExternalThreading=true)]
3209         public IAsyncResult BeginDisconnect(bool reuseSocket, AsyncCallback callback, object state)
3210         {
3211             // Start context-flowing op.  No need to lock - we don't use the context till the callback.
3212             DisconnectOverlappedAsyncResult asyncResult = new DisconnectOverlappedAsyncResult(this, state, callback);
3213             asyncResult.StartPostingAsyncOp(false);
3214
3215             // Post the disconnect.
3216             DoBeginDisconnect(reuseSocket, asyncResult);
3217
3218             // Finish flowing (or call the callback), and return.
3219             asyncResult.FinishPostingAsyncOp();
3220             return asyncResult;
3221         }
3222
3223         private void DoBeginDisconnect(bool reuseSocket, DisconnectOverlappedAsyncResult asyncResult)
3224         {
3225             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "BeginDisconnect",null);
3226             if (CleanedUp) {
3227                 throw new ObjectDisposedException(this.GetType().FullName);
3228             }
3229
3230             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginDisconnect() ");
3231
3232 #if FEATURE_PAL && !MONO
3233             throw new PlatformNotSupportedException(SR.GetString(SR.WinXPRequired));
3234 #endif
3235
3236
3237             asyncResult.SetUnmanagedStructures(null);
3238
3239             SocketError errorCode=SocketError.Success;
3240
3241             // This can throw ObjectDisposedException (handle, and retrieving the delegate).
3242             if (!DisconnectEx(m_Handle,asyncResult.OverlappedHandle, (int)(reuseSocket?TransmitFileOptions.ReuseSocket:0),0)) {
3243                 errorCode = (SocketError)Marshal.GetLastWin32Error();
3244             }
3245
3246             if (errorCode == SocketError.Success) {
3247                 SetToDisconnected();
3248                 m_RemoteEndPoint = null;
3249             }
3250
3251             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginDisconnect() UnsafeNclNativeMethods.OSSOCK.DisConnectEx returns:" + errorCode.ToString());
3252
3253             // if the asynchronous native call fails synchronously
3254             // we'll throw a SocketException
3255             //
3256             errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode);
3257
3258             if (errorCode!= SocketError.Success) {
3259                 //
3260                 // update our internal state after this socket error and throw
3261                 //
3262                 SocketException socketException = new SocketException(errorCode);
3263                 UpdateStatusAfterSocketError(socketException);
3264                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets,this,"BeginDisconnect", socketException);
3265                 throw socketException;
3266             }
3267
3268             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginDisconnect() returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
3269             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "BeginDisconnect", asyncResult);
3270         }
3271
3272
3273         // Supports DisconnectEx - this provides support for disconnect and reconnects
3274         public void Disconnect(bool reuseSocket) {
3275
3276              if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "Disconnect",null);
3277              if (CleanedUp) {
3278                  throw new ObjectDisposedException(this.GetType().FullName);
3279              }
3280
3281 #if FEATURE_PAL && !MONO
3282             throw new PlatformNotSupportedException(SR.GetString(SR.WinXPRequired));
3283 #endif // FEATURE_PAL && !MONO
3284
3285
3286              GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Disconnect() ");
3287
3288              SocketError errorCode = SocketError.Success;
3289
3290              // This can throw ObjectDisposedException (handle, and retrieving the delegate).
3291              if (!DisconnectEx_Blocking(m_Handle.DangerousGetHandle(), IntPtr.Zero, (int) (reuseSocket ? TransmitFileOptions.ReuseSocket : 0), 0))
3292              {
3293                  errorCode = (SocketError)Marshal.GetLastWin32Error();
3294              }
3295
3296              GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Disconnect() UnsafeNclNativeMethods.OSSOCK.DisConnectEx returns:" + errorCode.ToString());
3297
3298
3299              if (errorCode!= SocketError.Success) {
3300                  //
3301                  // update our internal state after this socket error and throw
3302                  //
3303                 SocketException socketException = new SocketException(errorCode);
3304                 UpdateStatusAfterSocketError(socketException);
3305                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets,this,"Disconnect", socketException);
3306                 throw socketException;
3307              }
3308
3309              SetToDisconnected();
3310              m_RemoteEndPoint = null;
3311              
3312              if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "Disconnect", null);
3313         }
3314
3315         /*++
3316
3317         Routine Description:
3318
3319            EndConnect - Called addressFamilyter receiving callback from BeginConnect,
3320             in order to retrive the result of async call
3321
3322         Arguments:
3323
3324            AsyncResult - the AsyncResult Returned fron BeginConnect call
3325
3326         Return Value:
3327
3328            int - Return code from aync Connect, 0 for success, SocketError.NotConnected otherwise
3329
3330         --*/
3331         /// <devdoc>
3332         ///    <para>[To be supplied.]</para>
3333         /// </devdoc>
3334         public void EndConnect(IAsyncResult asyncResult) {
3335             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "EndConnect", asyncResult);
3336             if (CleanedUp) {
3337                 throw new ObjectDisposedException(this.GetType().FullName);
3338             }
3339             //
3340             // parameter validation
3341             //
3342             if (asyncResult==null) {
3343                 throw new ArgumentNullException("asyncResult");
3344             }
3345
3346             LazyAsyncResult castedAsyncResult = null;
3347             EndPoint remoteEndPoint = null;
3348             ConnectOverlappedAsyncResult coar;
3349             MultipleAddressConnectAsyncResult macar;
3350             ConnectAsyncResult car;
3351
3352             coar = asyncResult as ConnectOverlappedAsyncResult;
3353             if (coar == null) {
3354                 macar = asyncResult as MultipleAddressConnectAsyncResult;
3355                 if (macar == null) {
3356                     car = asyncResult as ConnectAsyncResult;
3357                     if (car != null) {
3358                         remoteEndPoint = car.RemoteEndPoint;
3359                         castedAsyncResult = car;
3360                     }
3361                 } else {
3362                     remoteEndPoint = macar.RemoteEndPoint;
3363                     castedAsyncResult = macar;
3364                 }
3365             } else {
3366                 remoteEndPoint = coar.RemoteEndPoint;
3367                 castedAsyncResult = coar;
3368             }
3369             
3370             if (castedAsyncResult == null || castedAsyncResult.AsyncObject!=this) {
3371                 throw new ArgumentException(SR.GetString(SR.net_io_invalidasyncresult), "asyncResult");
3372             }
3373             if (castedAsyncResult.EndCalled) {
3374                 throw new InvalidOperationException(SR.GetString(SR.net_io_invalidendcall, "EndConnect"));
3375             }
3376
3377             castedAsyncResult.InternalWaitForCompletion();
3378             castedAsyncResult.EndCalled = true;
3379             m_AcceptQueueOrConnectResult = null;
3380
3381             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::EndConnect() asyncResult:" + ValidationHelper.HashString(asyncResult));
3382
3383             if (castedAsyncResult.Result is Exception) {
3384                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "EndConnect", (Exception)castedAsyncResult.Result);
3385                 throw (Exception)castedAsyncResult.Result;
3386             }
3387             if ((SocketError)castedAsyncResult.ErrorCode!=SocketError.Success) {
3388                 //
3389                 // update our internal state after this socket error and throw
3390                 //
3391                 SocketException socketException = new SocketException(castedAsyncResult.ErrorCode, remoteEndPoint);
3392                 UpdateStatusAfterSocketError(socketException);
3393                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "EndConnect", socketException);
3394                 throw socketException;
3395             }
3396             if (s_LoggingEnabled) {
3397                 Logging.PrintInfo(Logging.Sockets, this, SR.GetString(SR.net_log_socket_connected, LocalEndPoint, RemoteEndPoint));
3398                 Logging.Exit(Logging.Sockets, this, "EndConnect", "");
3399             }
3400         }
3401
3402         public void EndDisconnect(IAsyncResult asyncResult) {
3403
3404              if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "EndDisconnect", asyncResult);
3405              if (CleanedUp) {
3406                throw new ObjectDisposedException(this.GetType().FullName);
3407              }
3408
3409 #if FEATURE_PAL && !MONO
3410             throw new PlatformNotSupportedException(SR.GetString(SR.WinNTRequired));
3411 #endif // FEATURE_PAL && !MONO
3412
3413              if (asyncResult==null) {
3414                throw new ArgumentNullException("asyncResult");
3415              }
3416
3417
3418              //get async result and check for errors
3419              LazyAsyncResult castedAsyncResult = asyncResult as LazyAsyncResult;
3420              if (castedAsyncResult==null || castedAsyncResult.AsyncObject!=this) {
3421                throw new ArgumentException(SR.GetString(SR.net_io_invalidasyncresult), "asyncResult");
3422              }
3423              if (castedAsyncResult.EndCalled) {
3424                throw new InvalidOperationException(SR.GetString(SR.net_io_invalidendcall, "EndDisconnect"));
3425              }
3426
3427              //wait for completion if it hasn't occured
3428              castedAsyncResult.InternalWaitForCompletion();
3429              castedAsyncResult.EndCalled = true;
3430
3431
3432              GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::EndDisconnect()");
3433
3434              //
3435              // if the asynchronous native call failed asynchronously
3436              // we'll throw a SocketException
3437              //
3438              if ((SocketError)castedAsyncResult.ErrorCode!=SocketError.Success) {
3439                  //
3440                  // update our internal state after this socket error and throw
3441                  //
3442                 SocketException socketException = new SocketException(castedAsyncResult.ErrorCode);
3443                 UpdateStatusAfterSocketError(socketException);
3444                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets,this,"EndDisconnect", socketException);
3445                 throw socketException;
3446              }
3447
3448              if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "EndDisconnect", null);
3449              return;
3450         }
3451 #endif // !MONO
3452
3453         /*++
3454
3455         Routine Description:
3456
3457            BeginSend - Async implimentation of Send call, mirrored addressFamilyter BeginReceive
3458            This routine may go pending at which time,
3459            but any case the callback Delegate will be called upon completion
3460
3461         Arguments:
3462
3463            WriteBuffer - status line that we wish to parse
3464            Index - Offset into WriteBuffer to begin sending from
3465            Size - Size of Buffer to transmit
3466            Callback - Delegate function that holds callback, called on completeion of I/O
3467            State - State used to track callback, set by caller, not required
3468
3469         Return Value:
3470
3471            IAsyncResult - Async result used to retreive result
3472
3473         --*/
3474
3475         /// <devdoc>
3476         ///    <para>[To be supplied.]</para>
3477         /// </devdoc>
3478
3479         [HostProtection(ExternalThreading=true)]
3480         public IAsyncResult BeginSend(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback, object state)
3481         {
3482             SocketError errorCode;
3483             IAsyncResult result = BeginSend(buffer, offset, size, socketFlags, out errorCode, callback, state);
3484             if(errorCode != SocketError.Success && errorCode !=SocketError.IOPending){
3485                 throw new SocketException(errorCode);
3486             }
3487             return result;
3488         }
3489
3490 #if !MONO
3491         [HostProtection(ExternalThreading=true)]
3492         public IAsyncResult BeginSend(byte[] buffer, int offset, int size, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
3493         {
3494
3495             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "BeginSend", "");
3496
3497             if (CleanedUp) {
3498                 throw new ObjectDisposedException(this.GetType().FullName);
3499             }
3500             //
3501             // parameter validation
3502             //
3503             if (buffer == null)
3504             {
3505                 throw new ArgumentNullException("buffer");
3506             }
3507             if (offset < 0 || offset > buffer.Length)
3508             {
3509                 throw new ArgumentOutOfRangeException("offset");
3510             }
3511             if (size < 0 || size > buffer.Length - offset)
3512             {
3513                 throw new ArgumentOutOfRangeException("size");
3514             }
3515
3516             // We need to flow the context here.  But we don't need to lock the context - we don't use it until the callback.
3517             OverlappedAsyncResult asyncResult = new OverlappedAsyncResult(this, state, callback);
3518             asyncResult.StartPostingAsyncOp(false);
3519
3520             // Run the send with this asyncResult.
3521             errorCode = DoBeginSend(buffer, offset, size, socketFlags, asyncResult);
3522
3523             if(errorCode != SocketError.Success && errorCode !=SocketError.IOPending){
3524                 asyncResult = null;
3525             }
3526             else
3527             {
3528                 // We're not throwing, so finish the async op posting code so we can return to the user.
3529                 // If the operation already finished, the callback will be called from here.
3530                 asyncResult.FinishPostingAsyncOp(ref Caches.SendClosureCache);
3531             }
3532
3533             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "BeginSend", asyncResult);
3534             return asyncResult;
3535         }
3536
3537
3538         internal IAsyncResult UnsafeBeginSend(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback, object state)
3539         {
3540             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "UnsafeBeginSend", "");
3541
3542             if (CleanedUp) {
3543                 throw new ObjectDisposedException(this.GetType().FullName);
3544             }
3545
3546             // No need to flow the context.
3547             OverlappedAsyncResult asyncResult = new OverlappedAsyncResult(this, state, callback);
3548
3549             SocketError errorCode = DoBeginSend(buffer, offset, size, socketFlags, asyncResult);
3550             if(errorCode != SocketError.Success && errorCode !=SocketError.IOPending){
3551                 throw new SocketException(errorCode);
3552             }
3553
3554             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "UnsafeBeginSend", asyncResult);
3555             return asyncResult;
3556         }
3557
3558         private SocketError DoBeginSend(byte[] buffer, int offset, int size, SocketFlags socketFlags, OverlappedAsyncResult asyncResult)
3559         {
3560
3561             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginSend() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " DST:" + ValidationHelper.ToString(RemoteEndPoint) + " size:" + size.ToString());
3562
3563             // Guarantee to call CheckAsyncCallOverlappedResult if we call SetUnamangedStructures with a cache in order to
3564             // avoid a Socket leak in case of error.
3565             SocketError errorCode = SocketError.SocketError;
3566             try
3567             {
3568                 // Set up asyncResult for overlapped WSASend.
3569                 // This call will use completion ports on WinNT and Overlapped IO on Win9x.
3570                 asyncResult.SetUnmanagedStructures(buffer, offset, size, null, false /*don't pin null remoteEP*/, ref Caches.SendOverlappedCache);
3571
3572                 //
3573                 // Get the Send going.
3574                 //
3575                 GlobalLog.Print("BeginSend: asyncResult:" + ValidationHelper.HashString(asyncResult) + " size:" + size.ToString());
3576                 int bytesTransferred;
3577
3578                 // This can throw ObjectDisposedException.
3579                 errorCode = UnsafeNclNativeMethods.OSSOCK.WSASend(
3580                     m_Handle,
3581                     ref asyncResult.m_SingleBuffer,
3582                     1, // only ever 1 buffer being sent
3583                     out bytesTransferred,
3584                     socketFlags,
3585                     asyncResult.OverlappedHandle,
3586                     IntPtr.Zero);
3587
3588                 if (errorCode!=SocketError.Success) {
3589                     errorCode = (SocketError)Marshal.GetLastWin32Error();
3590                 }
3591                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginSend() UnsafeNclNativeMethods.OSSOCK.WSASend returns:" + errorCode.ToString() + " size:" + size.ToString() + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
3592             }
3593             finally
3594             {
3595                 errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode);
3596             }
3597
3598             //
3599             // if the asynchronous native call fails synchronously
3600             // we'll throw a SocketException
3601             //
3602             if (errorCode != SocketError.Success)
3603             {
3604                 asyncResult.ExtractCache(ref Caches.SendOverlappedCache);
3605                 UpdateStatusAfterSocketError(errorCode);
3606                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "BeginSend", new SocketException(errorCode));
3607             }
3608             return errorCode;
3609         }
3610
3611
3612         /// <devdoc>
3613         ///    <para>[To be supplied.]</para>
3614         /// </devdoc>
3615 #if !FEATURE_PAL
3616
3617         [HostProtection(ExternalThreading=true)]
3618         [ResourceExposure(ResourceScope.Machine)]
3619         [ResourceConsumption(ResourceScope.Machine)]
3620         public IAsyncResult BeginSendFile(
3621             string fileName,
3622             byte[] preBuffer,
3623             byte[] postBuffer,
3624             TransmitFileOptions flags,
3625             AsyncCallback callback,
3626             object state)
3627         {
3628
3629             // Start the context flowing.  No lock necessary.
3630             TransmitFileOverlappedAsyncResult asyncResult = new TransmitFileOverlappedAsyncResult(this,state,callback);
3631             asyncResult.StartPostingAsyncOp(false);
3632
3633             // Start the operation.
3634             DoBeginSendFile(fileName, preBuffer, postBuffer, flags, asyncResult);
3635
3636             // Finish the op, collect the context or maybe call the callback.
3637             asyncResult.FinishPostingAsyncOp(ref Caches.SendClosureCache);
3638             return asyncResult;
3639         }
3640
3641         [ResourceExposure(ResourceScope.Machine)]
3642         [ResourceConsumption(ResourceScope.Machine)]
3643         private void DoBeginSendFile(
3644             string fileName,
3645             byte[] preBuffer,
3646             byte[] postBuffer,
3647             TransmitFileOptions flags,
3648             TransmitFileOverlappedAsyncResult asyncResult)
3649         {
3650             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "BeginSendFile", "");
3651
3652             if (CleanedUp) {
3653                 throw new ObjectDisposedException(this.GetType().FullName);
3654             }
3655
3656             if (CleanedUp) {
3657                 throw new ObjectDisposedException(this.GetType().FullName);
3658             }
3659
3660 #if FEATURE_PAL && !MONO
3661             throw new PlatformNotSupportedException(SR.GetString(SR.WinNTRequired));
3662 #endif // FEATURE_PAL && !MONO
3663
3664
3665             if (!Connected) {
3666                 throw new NotSupportedException(SR.GetString(SR.net_notconnected));
3667             }
3668
3669             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginSendFile() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " DST:" + ValidationHelper.ToString(RemoteEndPoint) + " fileName:" + fileName);
3670
3671             FileStream fileStream = null;
3672             if (fileName != null && fileName.Length>0) {
3673                 fileStream = new FileStream(fileName,FileMode.Open,FileAccess.Read,FileShare.Read);
3674             }
3675
3676             SafeHandle fileHandle = null;
3677
3678             if (fileStream != null) {
3679                 ExceptionHelper.UnmanagedPermission.Assert();
3680                 try {
3681                     fileHandle = fileStream.SafeFileHandle;
3682                 }
3683                 finally {
3684                     SecurityPermission.RevertAssert();
3685                 }
3686             }
3687
3688             // Guarantee to call CheckAsyncCallOverlappedResult if we call SetUnamangedStructures with a cache in order to
3689             // avoid a Socket leak in case of error.
3690             SocketError errorCode = SocketError.SocketError;
3691             try
3692             {
3693                 asyncResult.SetUnmanagedStructures(preBuffer, postBuffer, fileStream, flags, ref Caches.SendOverlappedCache);
3694                 bool result = false;
3695
3696                 // This can throw ObjectDisposedException.
3697                 if (fileHandle != null){
3698                     result = UnsafeNclNativeMethods.OSSOCK.TransmitFile(m_Handle,fileHandle,0,0,asyncResult.OverlappedHandle,asyncResult.TransmitFileBuffers,flags);
3699                 }
3700                 else{
3701                     result = UnsafeNclNativeMethods.OSSOCK.TransmitFile2(m_Handle,IntPtr.Zero,0,0,asyncResult.OverlappedHandle,asyncResult.TransmitFileBuffers,flags);
3702                 }
3703                 if(!result)
3704                 {
3705                     errorCode =  (SocketError)Marshal.GetLastWin32Error();
3706                 }
3707                 else
3708                 {
3709                     errorCode = SocketError.Success;
3710                 }
3711             }
3712             finally
3713             {
3714                 errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode);
3715             }
3716
3717             //
3718             // if the native call fails we'll throw a SocketException
3719             //
3720             if (errorCode!=SocketError.Success) {
3721                 //
3722                 // update our internal state after this socket error and throw
3723                 //
3724                 asyncResult.ExtractCache(ref Caches.SendOverlappedCache);
3725                 SocketException socketException = new SocketException(errorCode);
3726                 UpdateStatusAfterSocketError(socketException);
3727
3728                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "BeginSendFile", socketException);
3729                 throw socketException;
3730             }
3731
3732             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginSendFile() UnsafeNclNativeMethods.OSSOCK.send returns:" + errorCode.ToString());
3733
3734             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "BeginSendFile", errorCode);
3735         }
3736
3737 #endif // !FEATURE_PAL
3738 #endif // !MONO
3739
3740         /// <devdoc>
3741         ///    <para>[To be supplied.]</para>
3742         /// </devdoc>
3743         [HostProtection(ExternalThreading=true)]
3744         public IAsyncResult BeginSend(IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, AsyncCallback callback, object state)
3745         {
3746             SocketError errorCode;
3747             IAsyncResult result = BeginSend(buffers, socketFlags, out errorCode, callback, state);
3748             if(errorCode != SocketError.Success && errorCode !=SocketError.IOPending){
3749                 throw new SocketException(errorCode);
3750             }
3751             return result;
3752         }
3753
3754 #if !MONO
3755         [HostProtection(ExternalThreading=true)]
3756         public IAsyncResult BeginSend(IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
3757         {
3758
3759             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "BeginSend", "");
3760
3761             if (CleanedUp) {
3762                 throw new ObjectDisposedException(this.GetType().FullName);
3763             }
3764
3765             //
3766             // parameter validation
3767             //
3768             if (buffers==null) {
3769                 throw new ArgumentNullException("buffers");
3770             }
3771
3772             if(buffers.Count == 0){
3773                 throw new ArgumentException(SR.GetString(SR.net_sockets_zerolist,"buffers"), "buffers");
3774             }
3775
3776             // We need to flow the context here.  But we don't need to lock the context - we don't use it until the callback.
3777             OverlappedAsyncResult asyncResult = new OverlappedAsyncResult(this, state, callback);
3778             asyncResult.StartPostingAsyncOp(false);
3779
3780             // Run the send with this asyncResult.
3781             errorCode = DoBeginSend(buffers, socketFlags, asyncResult);
3782
3783             // We're not throwing, so finish the async op posting code so we can return to the user.
3784             // If the operation already finished, the callback will be called from here.
3785             asyncResult.FinishPostingAsyncOp(ref Caches.SendClosureCache);
3786
3787             if(errorCode != SocketError.Success && errorCode !=SocketError.IOPending){
3788                 asyncResult = null;
3789             }
3790
3791             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "BeginSend", asyncResult);
3792             return asyncResult;
3793         }
3794
3795         private SocketError DoBeginSend(IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, OverlappedAsyncResult asyncResult)
3796         {
3797
3798             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginSend() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " DST:" + ValidationHelper.ToString(RemoteEndPoint) + " buffers:" + buffers);
3799
3800             // Guarantee to call CheckAsyncCallOverlappedResult if we call SetUnamangedStructures with a cache in order to
3801             // avoid a Socket leak in case of error.
3802             SocketError errorCode = SocketError.SocketError;
3803             try
3804             {
3805                 // Set up asyncResult for overlapped WSASend.
3806                 // This call will use completion ports on WinNT and Overlapped IO on Win9x.
3807                 asyncResult.SetUnmanagedStructures(buffers, ref Caches.SendOverlappedCache);
3808
3809                 GlobalLog.Print("BeginSend: asyncResult:" + ValidationHelper.HashString(asyncResult));
3810
3811                 // This can throw ObjectDisposedException.
3812                 int bytesTransferred;
3813                 errorCode = UnsafeNclNativeMethods.OSSOCK.WSASend(
3814                     m_Handle,
3815                     asyncResult.m_WSABuffers,
3816                     asyncResult.m_WSABuffers.Length,
3817                     out bytesTransferred,
3818                     socketFlags,
3819                     asyncResult.OverlappedHandle,
3820                     IntPtr.Zero);
3821
3822                 if (errorCode!=SocketError.Success) {
3823                     errorCode = (SocketError)Marshal.GetLastWin32Error();
3824                 }
3825                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginSend() UnsafeNclNativeMethods.OSSOCK.WSASend returns:" + errorCode.ToString() + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
3826             }
3827             finally
3828             {
3829                 errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode);
3830             }
3831
3832             //
3833             // if the asynchronous native call fails synchronously
3834             // we'll throw a SocketException
3835             //
3836             if (errorCode != SocketError.Success)
3837             {
3838                 asyncResult.ExtractCache(ref Caches.SendOverlappedCache);
3839                 UpdateStatusAfterSocketError(errorCode);
3840                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "BeginSend", new SocketException(errorCode));
3841             }
3842             return errorCode;
3843         }
3844 #endif // !MONO
3845
3846         /*++
3847
3848         Routine Description:
3849
3850            EndSend -  Called by user code addressFamilyter I/O is done or the user wants to wait.
3851                         until Async completion, needed to retrieve error result from call
3852
3853         Arguments:
3854
3855            AsyncResult - the AsyncResult Returned fron BeginSend call
3856
3857         Return Value:
3858
3859            int - Number of bytes transferred
3860
3861         --*/
3862         /// <devdoc>
3863         ///    <para>[To be supplied.]</para>
3864         /// </devdoc>
3865
3866
3867         public int EndSend(IAsyncResult asyncResult) {
3868             SocketError errorCode;
3869             int bytesTransferred = EndSend(asyncResult, out errorCode);
3870             if(errorCode != SocketError.Success){
3871                 throw new SocketException(errorCode);
3872             }
3873             return bytesTransferred;
3874         }
3875
3876 #if !MONO
3877         public int EndSend(IAsyncResult asyncResult, out SocketError errorCode) {
3878             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "EndSend", asyncResult);
3879             if (CleanedUp) {
3880                 throw new ObjectDisposedException(this.GetType().FullName);
3881             }
3882             //
3883             // parameter validation
3884             //
3885             if (asyncResult==null) {
3886                 throw new ArgumentNullException("asyncResult");
3887             }
3888             OverlappedAsyncResult castedAsyncResult = asyncResult as OverlappedAsyncResult;
3889             if (castedAsyncResult==null || castedAsyncResult.AsyncObject!=this) {
3890                 throw new ArgumentException(SR.GetString(SR.net_io_invalidasyncresult), "asyncResult");
3891             }
3892             if (castedAsyncResult.EndCalled) {
3893                 throw new InvalidOperationException(SR.GetString(SR.net_io_invalidendcall, "EndSend"));
3894             }
3895
3896             int bytesTransferred = (int)castedAsyncResult.InternalWaitForCompletion();
3897             castedAsyncResult.EndCalled = true;
3898             castedAsyncResult.ExtractCache(ref Caches.SendOverlappedCache);
3899
3900 #if !FEATURE_PAL // perfcounter
3901             if (s_PerfCountersEnabled)
3902             {
3903                 if (bytesTransferred>0) {
3904                     NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketBytesSent, bytesTransferred);
3905                     if (Transport==TransportType.Udp) {
3906                         NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketDatagramsSent);
3907                     }
3908                 }
3909             }
3910 #endif //!FEATURE_PAL
3911             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::EndSend() bytesTransferred:" + bytesTransferred.ToString());
3912
3913             //
3914             // if the asynchronous native call failed asynchronously
3915             // we'll throw a SocketException
3916             //
3917             errorCode = (SocketError)castedAsyncResult.ErrorCode;
3918             if (errorCode != SocketError.Success) {
3919                 //
3920                 // update our internal state after this socket error and throw
3921                 //
3922                 UpdateStatusAfterSocketError(errorCode);
3923                 if(s_LoggingEnabled){
3924                     Logging.Exception(Logging.Sockets, this, "EndSend", new SocketException(errorCode));
3925                     Logging.Exit(Logging.Sockets, this, "EndSend", 0);
3926                 }
3927                 return 0;
3928            }
3929             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "EndSend", bytesTransferred);
3930             return bytesTransferred;
3931         }
3932
3933 #if !FEATURE_PAL
3934
3935         /// <devdoc>
3936         ///    <para>[To be supplied.]</para>
3937         /// </devdoc>
3938         public void EndSendFile(IAsyncResult asyncResult) {
3939             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "EndSendFile", asyncResult);
3940             if (CleanedUp) {
3941                 throw new ObjectDisposedException(this.GetType().FullName);
3942             }
3943
3944 #if FEATURE_PAL && !MONO
3945             throw new PlatformNotSupportedException(SR.GetString(SR.WinNTRequired));
3946 #endif // FEATURE_PAL && !MONO
3947             //
3948             // parameter validation
3949             //
3950             if (asyncResult==null) {
3951                 throw new ArgumentNullException("asyncResult");
3952             }
3953             TransmitFileOverlappedAsyncResult castedAsyncResult = asyncResult as TransmitFileOverlappedAsyncResult;
3954             if (castedAsyncResult==null || castedAsyncResult.AsyncObject!=this) {
3955                 throw new ArgumentException(SR.GetString(SR.net_io_invalidasyncresult), "asyncResult");
3956             }
3957             if (castedAsyncResult.EndCalled) {
3958                 throw new InvalidOperationException(SR.GetString(SR.net_io_invalidendcall, "EndSendFile"));
3959             }
3960
3961             castedAsyncResult.InternalWaitForCompletion();
3962             castedAsyncResult.EndCalled = true;
3963             castedAsyncResult.ExtractCache(ref Caches.SendOverlappedCache);
3964
3965             if ((castedAsyncResult.Flags & (TransmitFileOptions.Disconnect | TransmitFileOptions.ReuseSocket) )!=0) {
3966                 SetToDisconnected();
3967                 m_RemoteEndPoint = null;
3968             }
3969
3970
3971             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::EndSendFile()");
3972
3973             //
3974             // if the asynchronous native call failed asynchronously
3975             // we'll throw a SocketException
3976             //
3977             if ((SocketError)castedAsyncResult.ErrorCode!=SocketError.Success) {
3978                 //
3979                 // update our internal state after this socket error and throw
3980                 //
3981                 SocketException socketException = new SocketException(castedAsyncResult.ErrorCode);
3982                 UpdateStatusAfterSocketError(socketException);
3983                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "EndSendFile", socketException);
3984                 throw socketException;
3985            }
3986             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "EndSendFile","");
3987         }
3988
3989 #endif // !FEATURE_PAL
3990
3991
3992         /*++
3993
3994         Routine Description:
3995
3996            BeginSendTo - Async implimentation of SendTo,
3997
3998            This routine may go pending at which time,
3999            but any case the callback Delegate will be called upon completion
4000
4001         Arguments:
4002
4003            WriteBuffer - Buffer to transmit
4004            Index - Offset into WriteBuffer to begin sending from
4005            Size - Size of Buffer to transmit
4006            Flags - Specific Socket flags to pass to winsock
4007            remoteEP - EndPoint to transmit To
4008            Callback - Delegate function that holds callback, called on completeion of I/O
4009            State - State used to track callback, set by caller, not required
4010
4011         Return Value:
4012
4013            IAsyncResult - Async result used to retreive result
4014
4015         --*/
4016         /// <devdoc>
4017         ///    <para>[To be supplied.]</para>
4018         /// </devdoc>
4019         [HostProtection(ExternalThreading=true)]
4020         public IAsyncResult BeginSendTo(byte[] buffer, int offset, int size, SocketFlags socketFlags, EndPoint remoteEP, AsyncCallback callback, object state)
4021         {
4022
4023             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "BeginSendTo", "");
4024
4025             if (CleanedUp) {
4026                 throw new ObjectDisposedException(this.GetType().FullName);
4027             }
4028
4029             //
4030             // parameter validation
4031             //
4032             if (buffer==null) {
4033                 throw new ArgumentNullException("buffer");
4034             }
4035             if (remoteEP==null) {
4036                 throw new ArgumentNullException("remoteEP");
4037             }
4038             if (offset<0 || offset>buffer.Length) {
4039                 throw new ArgumentOutOfRangeException("offset");
4040             }
4041             if (size<0 || size>buffer.Length-offset) {
4042                 throw new ArgumentOutOfRangeException("size");
4043             }
4044
4045             // This will check the permissions for connect.
4046             EndPoint endPointSnapshot = remoteEP;
4047             SocketAddress socketAddress = CheckCacheRemote(ref endPointSnapshot, false);
4048
4049             // Set up the async result and indicate to flow the context.
4050             OverlappedAsyncResult asyncResult = new OverlappedAsyncResult(this, state, callback);
4051             asyncResult.StartPostingAsyncOp(false);
4052
4053             // Post the send.
4054             DoBeginSendTo(buffer, offset, size, socketFlags, endPointSnapshot, socketAddress, asyncResult);
4055
4056             // Finish, possibly posting the callback.  The callback won't be posted before this point is reached.
4057             asyncResult.FinishPostingAsyncOp(ref Caches.SendClosureCache);
4058
4059             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "BeginSendTo", asyncResult);
4060             return asyncResult;
4061         }
4062
4063         private void DoBeginSendTo(byte[] buffer, int offset, int size, SocketFlags socketFlags, EndPoint endPointSnapshot, SocketAddress socketAddress, OverlappedAsyncResult asyncResult)
4064         {
4065             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginSendTo() size:" + size.ToString());
4066             EndPoint oldEndPoint = m_RightEndPoint;
4067
4068             // Guarantee to call CheckAsyncCallOverlappedResult if we call SetUnamangedStructures with a cache in order to
4069             // avoid a Socket leak in case of error.
4070             SocketError errorCode = SocketError.SocketError;
4071             try
4072             {
4073                 // Set up asyncResult for overlapped WSASendTo.
4074                 // This call will use completion ports on WinNT and Overlapped IO on Win9x.
4075                 asyncResult.SetUnmanagedStructures(buffer, offset, size, socketAddress, false /* don't pin RemoteEP*/, ref Caches.SendOverlappedCache);
4076
4077                 if (m_RightEndPoint == null)
4078                 {
4079                     m_RightEndPoint = endPointSnapshot;
4080                 }
4081
4082                 int bytesTransferred;
4083                 errorCode = UnsafeNclNativeMethods.OSSOCK.WSASendTo(
4084                     m_Handle,
4085                     ref asyncResult.m_SingleBuffer,
4086                     1, // only ever 1 buffer being sent
4087                     out bytesTransferred,
4088                     socketFlags,
4089                     asyncResult.GetSocketAddressPtr(),
4090                     asyncResult.SocketAddress.Size,
4091                     asyncResult.OverlappedHandle,
4092                     IntPtr.Zero);
4093
4094                 if (errorCode!=SocketError.Success) {
4095                     errorCode = (SocketError)Marshal.GetLastWin32Error();
4096                 }
4097                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginSendTo() UnsafeNclNativeMethods.OSSOCK.WSASend returns:" + errorCode.ToString() + " size:" + size + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
4098             }
4099             catch (ObjectDisposedException)
4100             {
4101                 m_RightEndPoint = oldEndPoint;
4102                 throw;
4103             }
4104             finally
4105             {
4106                 errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode);
4107             }
4108
4109             //
4110             // if the asynchronous native call fails synchronously
4111             // we'll throw a SocketException
4112             //
4113             if (errorCode!=SocketError.Success) {
4114                 //
4115                 // update our internal state after this socket error and throw
4116                 //
4117                 m_RightEndPoint = oldEndPoint;
4118                 asyncResult.ExtractCache(ref Caches.SendOverlappedCache);
4119                 SocketException socketException = new SocketException(errorCode);
4120                 UpdateStatusAfterSocketError(socketException);
4121                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "BeginSendTo", socketException);
4122                 throw socketException;
4123             }
4124
4125             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginSendTo() size:" + size.ToString() + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
4126         }
4127
4128         /*++
4129
4130         Routine Description:
4131
4132            EndSendTo -  Called by user code addressFamilyter I/O is done or the user wants to wait.
4133                         until Async completion, needed to retrieve error result from call
4134
4135         Arguments:
4136
4137            AsyncResult - the AsyncResult Returned fron BeginSend call
4138
4139         Return Value:
4140
4141            int - Number of bytes transferred
4142
4143         --*/
4144         /// <devdoc>
4145         ///    <para>[To be supplied.]</para>
4146         /// </devdoc>
4147         public int EndSendTo(IAsyncResult asyncResult) {
4148             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "EndSendTo", asyncResult);
4149             if (CleanedUp) {
4150                 throw new ObjectDisposedException(this.GetType().FullName);
4151             }
4152             //
4153             // parameter validation
4154             //
4155             if (asyncResult==null) {
4156                 throw new ArgumentNullException("asyncResult");
4157             }
4158             OverlappedAsyncResult castedAsyncResult = asyncResult as OverlappedAsyncResult;
4159             if (castedAsyncResult==null || castedAsyncResult.AsyncObject!=this) {
4160                 throw new ArgumentException(SR.GetString(SR.net_io_invalidasyncresult), "asyncResult");
4161             }
4162             if (castedAsyncResult.EndCalled) {
4163                 throw new InvalidOperationException(SR.GetString(SR.net_io_invalidendcall, "EndSendTo"));
4164             }
4165
4166             int bytesTransferred = (int)castedAsyncResult.InternalWaitForCompletion();
4167             castedAsyncResult.EndCalled = true;
4168             castedAsyncResult.ExtractCache(ref Caches.SendOverlappedCache);
4169
4170 #if !FEATURE_PAL // perfcounter
4171             if (s_PerfCountersEnabled)
4172             {
4173                 if (bytesTransferred>0) {
4174                     NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketBytesSent, bytesTransferred);
4175                     if (Transport==TransportType.Udp) {
4176                         NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketDatagramsSent);
4177                     }
4178                 }
4179             }
4180 #endif //!FEATURE_PAL
4181
4182             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::EndSendTo() bytesTransferred:" + bytesTransferred.ToString());
4183
4184             //
4185             // if the asynchronous native call failed asynchronously
4186             // we'll throw a SocketException
4187             //
4188             if ((SocketError)castedAsyncResult.ErrorCode!=SocketError.Success) {
4189                 //
4190                 // update our internal state after this socket error and throw
4191                 //
4192                 SocketException socketException = new SocketException(castedAsyncResult.ErrorCode);
4193                 UpdateStatusAfterSocketError(socketException);
4194                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "EndSendTo", socketException);
4195                 throw socketException;
4196             }
4197             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "EndSendTo", bytesTransferred);
4198             return bytesTransferred;
4199         }
4200 #endif // !MONO
4201
4202         /*++
4203
4204         Routine Description:
4205
4206            BeginReceive - Async implimentation of Recv call,
4207
4208            Called when we want to start an async receive.
4209            We kick off the receive, and if it completes synchronously we'll
4210            call the callback. Otherwise we'll return an IASyncResult, which
4211            the caller can use to wait on or retrieve the final status, as needed.
4212
4213            Uses Winsock 2 overlapped I/O.
4214
4215         Arguments:
4216
4217            ReadBuffer - status line that we wish to parse
4218            Index - Offset into ReadBuffer to begin reading from
4219            Size - Size of Buffer to recv
4220            Callback - Delegate function that holds callback, called on completeion of I/O
4221            State - State used to track callback, set by caller, not required
4222
4223         Return Value:
4224
4225            IAsyncResult - Async result used to retreive result
4226
4227         --*/
4228
4229
4230         /// <devdoc>
4231         ///    <para>[To be supplied.]</para>
4232         /// </devdoc>
4233
4234         [HostProtection(ExternalThreading=true)]
4235         public IAsyncResult BeginReceive(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback, object state)
4236         {
4237             SocketError errorCode;
4238             IAsyncResult result = BeginReceive(buffer, offset, size, socketFlags, out errorCode, callback, state);
4239             if(errorCode != SocketError.Success && errorCode !=SocketError.IOPending){
4240                 throw new SocketException(errorCode);
4241             }
4242             return result;
4243         }
4244
4245
4246 #if !MONO
4247         [HostProtection(ExternalThreading=true)]
4248         public IAsyncResult BeginReceive(byte[] buffer, int offset, int size, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
4249         {
4250
4251             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "BeginReceive", "");
4252
4253             if (CleanedUp) {
4254                 throw new ObjectDisposedException(this.GetType().FullName);
4255             }
4256
4257             //
4258             // parameter validation
4259             //
4260             if (buffer==null) {
4261                 throw new ArgumentNullException("buffer");
4262             }
4263             if (offset<0 || offset>buffer.Length) {
4264                 throw new ArgumentOutOfRangeException("offset");
4265             }
4266             if (size<0 || size>buffer.Length-offset) {
4267                 throw new ArgumentOutOfRangeException("size");
4268             }
4269
4270             // We need to flow the context here.  But we don't need to lock the context - we don't use it until the callback.
4271             OverlappedAsyncResult asyncResult = new OverlappedAsyncResult(this, state, callback);
4272             asyncResult.StartPostingAsyncOp(false);
4273
4274             // Run the receive with this asyncResult.
4275             errorCode = DoBeginReceive(buffer, offset, size, socketFlags, asyncResult);
4276
4277             if(errorCode != SocketError.Success && errorCode !=SocketError.IOPending){
4278                 asyncResult = null;
4279             }
4280             else
4281             {
4282                 // We're not throwing, so finish the async op posting code so we can return to the user.
4283                 // If the operation already finished, the callback will be called from here.
4284                 asyncResult.FinishPostingAsyncOp(ref Caches.ReceiveClosureCache);
4285             }
4286
4287             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "BeginReceive", asyncResult);
4288             return asyncResult;
4289         }
4290
4291         internal IAsyncResult UnsafeBeginReceive(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback, object state)
4292         {
4293
4294             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "UnsafeBeginReceive", "");
4295
4296             if (CleanedUp) {
4297                 throw new ObjectDisposedException(this.GetType().FullName);
4298             }
4299
4300             // No need to flow the context.
4301             OverlappedAsyncResult asyncResult = new OverlappedAsyncResult(this, state, callback);
4302             DoBeginReceive(buffer, offset, size, socketFlags, asyncResult);
4303
4304             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "UnsafeBeginReceive", asyncResult);
4305             return asyncResult;
4306         }
4307
4308         private SocketError DoBeginReceive(byte[] buffer, int offset, int size, SocketFlags socketFlags, OverlappedAsyncResult asyncResult)
4309         {
4310             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginReceive() size:" + size.ToString());
4311
4312 #if DEBUG
4313             IntPtr lastHandle = m_Handle.DangerousGetHandle();
4314 #endif
4315             // Guarantee to call CheckAsyncCallOverlappedResult if we call SetUnamangedStructures with a cache in order to
4316             // avoid a Socket leak in case of error.
4317             SocketError errorCode = SocketError.SocketError;
4318             try
4319             {
4320                 // Set up asyncResult for overlapped WSARecv.
4321                 // This call will use completion ports on WinNT and Overlapped IO on Win9x.
4322                 asyncResult.SetUnmanagedStructures(buffer, offset, size, null, false /* don't pin null RemoteEP*/, ref Caches.ReceiveOverlappedCache);
4323
4324                 // This can throw ObjectDisposedException.
4325                 int bytesTransferred;
4326                 errorCode = UnsafeNclNativeMethods.OSSOCK.WSARecv(
4327                     m_Handle,
4328                     ref asyncResult.m_SingleBuffer,
4329                     1,
4330                     out bytesTransferred,
4331                     ref socketFlags,
4332                     asyncResult.OverlappedHandle,
4333                     IntPtr.Zero);
4334
4335                 if (errorCode!=SocketError.Success) {
4336                     errorCode = (SocketError)Marshal.GetLastWin32Error();
4337                     GlobalLog.Assert(errorCode != SocketError.Success, "Socket#{0}::DoBeginReceive()|GetLastWin32Error() returned zero.", ValidationHelper.HashString(this));
4338                 }
4339                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginReceive() UnsafeNclNativeMethods.OSSOCK.WSARecv returns:" + errorCode.ToString() + " bytesTransferred:" + bytesTransferred.ToString() + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
4340             }
4341             finally
4342             {
4343                 errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode);
4344             }
4345
4346             //
4347             // if the asynchronous native call fails synchronously
4348             // we'll throw a SocketException
4349             //
4350             if (errorCode != SocketError.Success)
4351             {
4352                 //
4353                 // update our internal state after this socket error and throw
4354                 asyncResult.ExtractCache(ref Caches.ReceiveOverlappedCache);
4355                 UpdateStatusAfterSocketError(errorCode);
4356                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "BeginReceive", new SocketException(errorCode));
4357                 asyncResult.InvokeCallback(new SocketException(errorCode));
4358             }
4359 #if DEBUG
4360             else
4361             {
4362                 m_LastReceiveHandle = lastHandle;
4363                 m_LastReceiveThread = Thread.CurrentThread.ManagedThreadId;
4364                 m_LastReceiveTick = Environment.TickCount;
4365             }
4366 #endif
4367
4368             return errorCode;
4369         }
4370 #endif // !MONO
4371
4372         [HostProtection(ExternalThreading=true)]
4373         public IAsyncResult BeginReceive(IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, AsyncCallback callback, object state)
4374         {
4375             SocketError errorCode;
4376             IAsyncResult result = BeginReceive(buffers, socketFlags, out errorCode, callback, state);
4377             if(errorCode != SocketError.Success && errorCode !=SocketError.IOPending){
4378                 throw new SocketException(errorCode);
4379             }
4380             return result;
4381         }
4382
4383 #if !MONO
4384         [HostProtection(ExternalThreading=true)]
4385         public IAsyncResult BeginReceive(IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
4386         {
4387
4388             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "BeginReceive", "");
4389
4390             if (CleanedUp) {
4391                 throw new ObjectDisposedException(this.GetType().FullName);
4392             }
4393
4394             //
4395             // parameter validation
4396             //
4397             if (buffers==null) {
4398                throw new ArgumentNullException("buffers");
4399             }
4400
4401             if(buffers.Count == 0){
4402                 throw new ArgumentException(SR.GetString(SR.net_sockets_zerolist,"buffers"), "buffers");
4403             }
4404
4405             // We need to flow the context here.  But we don't need to lock the context - we don't use it until the callback.
4406             OverlappedAsyncResult asyncResult = new OverlappedAsyncResult(this, state, callback);
4407             asyncResult.StartPostingAsyncOp(false);
4408
4409             // Run the receive with this asyncResult.
4410             errorCode = DoBeginReceive(buffers, socketFlags, asyncResult);
4411
4412             if(errorCode != SocketError.Success && errorCode !=SocketError.IOPending){
4413                 asyncResult = null;
4414             }
4415             else
4416             {
4417                 // We're not throwing, so finish the async op posting code so we can return to the user.
4418                 // If the operation already finished, the callback will be called from here.
4419                 asyncResult.FinishPostingAsyncOp(ref Caches.ReceiveClosureCache);
4420             }
4421
4422             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "BeginReceive", asyncResult);
4423             return asyncResult;
4424         }
4425
4426         private SocketError DoBeginReceive(IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, OverlappedAsyncResult asyncResult)
4427         {
4428 #if DEBUG
4429             IntPtr lastHandle = m_Handle.DangerousGetHandle();
4430 #endif
4431             // Guarantee to call CheckAsyncCallOverlappedResult if we call SetUnamangedStructures with a cache in order to
4432             // avoid a Socket leak in case of error.
4433             SocketError errorCode = SocketError.SocketError;
4434             try
4435             {
4436                 // Set up asyncResult for overlapped WSASend.
4437                 // This call will use completion ports on WinNT and Overlapped IO on Win9x.
4438                 asyncResult.SetUnmanagedStructures(buffers, ref Caches.ReceiveOverlappedCache);
4439
4440                 // This can throw ObjectDisposedException.
4441                 int bytesTransferred;
4442                 errorCode = UnsafeNclNativeMethods.OSSOCK.WSARecv(
4443                     m_Handle,
4444                     asyncResult.m_WSABuffers,
4445                     asyncResult.m_WSABuffers.Length,
4446                     out bytesTransferred,
4447                     ref socketFlags,
4448                     asyncResult.OverlappedHandle,
4449                     IntPtr.Zero);
4450
4451                 if (errorCode!=SocketError.Success) {
4452                     errorCode = (SocketError)Marshal.GetLastWin32Error();
4453                     GlobalLog.Assert(errorCode != SocketError.Success, "Socket#{0}::DoBeginReceive()|GetLastWin32Error() returned zero.", ValidationHelper.HashString(this));
4454                 }
4455                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginReceive() UnsafeNclNativeMethods.OSSOCK.WSARecv returns:" + errorCode.ToString() + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
4456             }
4457             finally
4458             {
4459                 errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode);
4460             }
4461
4462             //
4463             // if the asynchronous native call fails synchronously
4464             // we'll throw a SocketException
4465             //
4466             if (errorCode != SocketError.Success)
4467             {
4468                 //
4469                 // update our internal state after this socket error and throw
4470                 asyncResult.ExtractCache(ref Caches.ReceiveOverlappedCache);
4471                 UpdateStatusAfterSocketError(errorCode);
4472                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "BeginReceive", new SocketException(errorCode));
4473             }
4474 #if DEBUG
4475             else
4476             {
4477                 m_LastReceiveHandle = lastHandle;
4478                 m_LastReceiveThread = Thread.CurrentThread.ManagedThreadId;
4479                 m_LastReceiveTick = Environment.TickCount;
4480             }
4481 #endif
4482
4483             return errorCode;
4484         }
4485
4486 #if DEBUG
4487         private IntPtr m_LastReceiveHandle;
4488         private int m_LastReceiveThread;
4489         private int m_LastReceiveTick;
4490 #endif
4491
4492 #endif // !MONO
4493
4494         /*++
4495
4496         Routine Description:
4497
4498            EndReceive -  Called when I/O is done or the user wants to wait. If
4499                      the I/O isn't done, we'll wait for it to complete, and then we'll return
4500                      the bytes of I/O done.
4501
4502         Arguments:
4503
4504            AsyncResult - the AsyncResult Returned fron BeginSend call
4505
4506         Return Value:
4507
4508            int - Number of bytes transferred
4509
4510         --*/
4511
4512         /// <devdoc>
4513         ///    <para>[To be supplied.]</para>
4514         /// </devdoc>
4515         public int EndReceive(IAsyncResult asyncResult) {
4516             SocketError errorCode;
4517             int bytesTransferred = EndReceive(asyncResult, out errorCode);
4518             if(errorCode != SocketError.Success){
4519                 throw new SocketException(errorCode);
4520             }
4521             return bytesTransferred;
4522         }
4523
4524 #if !MONO
4525         public int EndReceive(IAsyncResult asyncResult, out SocketError errorCode) {
4526             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "EndReceive", asyncResult);
4527             if (CleanedUp) {
4528                 throw new ObjectDisposedException(this.GetType().FullName);
4529             }
4530             //
4531             // parameter validation
4532             //
4533             if (asyncResult==null) {
4534                 throw new ArgumentNullException("asyncResult");
4535             }
4536             OverlappedAsyncResult castedAsyncResult = asyncResult as OverlappedAsyncResult;
4537             if (castedAsyncResult==null || castedAsyncResult.AsyncObject!=this) {
4538                 throw new ArgumentException(SR.GetString(SR.net_io_invalidasyncresult), "asyncResult");
4539             }
4540             if (castedAsyncResult.EndCalled) {
4541                 throw new InvalidOperationException(SR.GetString(SR.net_io_invalidendcall, "EndReceive"));
4542             }
4543
4544             int bytesTransferred = (int)castedAsyncResult.InternalWaitForCompletion();
4545             castedAsyncResult.EndCalled = true;
4546             castedAsyncResult.ExtractCache(ref Caches.ReceiveOverlappedCache);
4547
4548 #if !FEATURE_PAL // perfcounter
4549             if (s_PerfCountersEnabled)
4550             {
4551                 if (bytesTransferred>0) {
4552                     NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketBytesReceived, bytesTransferred);
4553                     if (Transport==TransportType.Udp) {
4554                         NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketDatagramsReceived);
4555                     }
4556                 }
4557             }
4558 #endif //!FEATURE_PAL
4559
4560 #if TRAVE
4561             try
4562             {
4563                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::EndReceive() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " DST:" + ValidationHelper.ToString(RemoteEndPoint) + " bytesTransferred:" + bytesTransferred.ToString());
4564             }
4565             catch (ObjectDisposedException) { }
4566 #endif
4567
4568             //
4569             // if the asynchronous native call failed asynchronously
4570             // we'll throw a SocketException
4571             //
4572             errorCode = (SocketError)castedAsyncResult.ErrorCode;
4573             if (errorCode!=SocketError.Success) {
4574                 //
4575                 // update our internal state after this socket error and throw
4576                 //
4577                 UpdateStatusAfterSocketError(errorCode);
4578                 if(s_LoggingEnabled){
4579                     Logging.Exception(Logging.Sockets, this, "EndReceive", new SocketException(errorCode));
4580                     Logging.Exit(Logging.Sockets, this, "EndReceive", 0);
4581                 }
4582                 return 0;
4583             }
4584             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "EndReceive", bytesTransferred);
4585             return bytesTransferred;
4586         }
4587
4588
4589
4590         public IAsyncResult BeginReceiveMessageFrom(byte[] buffer, int offset, int size, SocketFlags socketFlags, ref EndPoint remoteEP, AsyncCallback callback, object state) {
4591             if (s_LoggingEnabled) Logging.Enter(Logging.Sockets, this, "BeginReceiveMessageFrom", "");
4592             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginReceiveMessageFrom() size:" + size.ToString());
4593
4594             if (CleanedUp) {
4595                 throw new ObjectDisposedException(this.GetType().FullName);
4596             }
4597             if (buffer==null) {
4598                 throw new ArgumentNullException("buffer");
4599             }
4600             if (remoteEP==null) {
4601                 throw new ArgumentNullException("remoteEP");
4602             }
4603             if (!CanTryAddressFamily(remoteEP.AddressFamily)) {
4604                 throw new ArgumentException(SR.GetString(SR.net_InvalidEndPointAddressFamily, 
4605                     remoteEP.AddressFamily, addressFamily), "remoteEP");
4606             }
4607             if (offset<0 || offset>buffer.Length) {
4608                 throw new ArgumentOutOfRangeException("offset");
4609             }
4610             if (size<0 || size>buffer.Length-offset) {
4611                 throw new ArgumentOutOfRangeException("size");
4612             }
4613             if (m_RightEndPoint==null) {
4614                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustbind));
4615             }
4616
4617
4618             // Set up the result and set it to collect the context.
4619             ReceiveMessageOverlappedAsyncResult asyncResult = new ReceiveMessageOverlappedAsyncResult(this, state, callback);
4620             asyncResult.StartPostingAsyncOp(false);
4621
4622             // Start the ReceiveFrom.
4623             EndPoint oldEndPoint = m_RightEndPoint;
4624
4625             // We don't do a CAS demand here because the contents of remoteEP aren't used by
4626             // WSARecvMsg; all that matters is that we generate a unique-to-this-call SocketAddress
4627             // with the right address family
4628             SocketAddress socketAddress = SnapshotAndSerialize(ref remoteEP);
4629
4630             // Guarantee to call CheckAsyncCallOverlappedResult if we call SetUnamangedStructures with a cache in order to
4631             // avoid a Socket leak in case of error.
4632             SocketError errorCode = SocketError.SocketError;
4633             try
4634             {
4635                 asyncResult.SetUnmanagedStructures(buffer, offset, size, socketAddress, socketFlags, ref Caches.ReceiveOverlappedCache);
4636
4637                 // save a copy of the original EndPoint in the asyncResult
4638                 asyncResult.SocketAddressOriginal = remoteEP.Serialize();
4639
4640                 int bytesTransfered;
4641
4642                 SetReceivingPacketInformation();
4643
4644                 if (m_RightEndPoint == null)
4645                 {
4646                     m_RightEndPoint = remoteEP;
4647                 }
4648
4649                 errorCode = (SocketError) WSARecvMsg(
4650                     m_Handle,
4651                     Marshal.UnsafeAddrOfPinnedArrayElement(asyncResult.m_MessageBuffer,0),
4652                     out bytesTransfered,
4653                     asyncResult.OverlappedHandle,
4654                     IntPtr.Zero);
4655
4656                 if (errorCode!=SocketError.Success) {
4657                     errorCode = (SocketError)Marshal.GetLastWin32Error();
4658
4659                     // I have guarantees from Brad Williamson that WSARecvMsg() will never return WSAEMSGSIZE directly, since a completion
4660                     // is queued in this case.  We wouldn't be able to handle this easily because of assumptions OverlappedAsyncResult
4661                     // makes about whether there would be a completion or not depending on the error code.  If WSAEMSGSIZE would have been
4662                     // normally returned, it returns WSA_IO_PENDING instead.  That same map is implemented here just in case.
4663                     if (errorCode == SocketError.MessageSize)
4664                     {
4665                         GlobalLog.Assert("Socket#" + ValidationHelper.HashString(this) + "::BeginReceiveMessageFrom()|Returned WSAEMSGSIZE!");
4666                         errorCode = SocketError.IOPending;
4667                     }
4668                 }
4669
4670                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginReceiveMessageFrom() UnsafeNclNativeMethods.OSSOCK.WSARecvMsg returns:" + errorCode.ToString() + " size:" + size.ToString() + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
4671             }
4672             catch (ObjectDisposedException)
4673             {
4674                 m_RightEndPoint = oldEndPoint;
4675                 throw;
4676             }
4677             finally
4678             {
4679                 errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode);
4680             }
4681
4682             //
4683             // if the asynchronous native call fails synchronously
4684             // we'll throw a SocketException
4685             //
4686             if (errorCode!=SocketError.Success)
4687             {
4688                 //
4689                 // update our internal state after this socket error and throw
4690                 //
4691                 m_RightEndPoint = oldEndPoint;
4692                 asyncResult.ExtractCache(ref Caches.ReceiveOverlappedCache);
4693                 SocketException socketException = new SocketException(errorCode);
4694                 UpdateStatusAfterSocketError(socketException);
4695                 if (s_LoggingEnabled) Logging.Exception(Logging.Sockets, this, "BeginReceiveMessageFrom", socketException);
4696                 throw socketException;
4697             }
4698
4699             // Capture the context, maybe call the callback, and return.
4700             asyncResult.FinishPostingAsyncOp(ref Caches.ReceiveClosureCache);
4701
4702             if (asyncResult.CompletedSynchronously && !asyncResult.SocketAddressOriginal.Equals(asyncResult.SocketAddress)) {
4703                 try {
4704                     remoteEP = remoteEP.Create(asyncResult.SocketAddress);
4705                 }
4706                 catch {
4707                 }
4708             }
4709
4710             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginReceiveMessageFrom() size:" + size.ToString() + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
4711             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "BeginReceiveMessageFrom", asyncResult);
4712             return asyncResult;
4713         }
4714
4715
4716         public int EndReceiveMessageFrom(IAsyncResult asyncResult, ref SocketFlags socketFlags, ref EndPoint endPoint, out IPPacketInformation ipPacketInformation) {
4717             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "EndReceiveMessageFrom", asyncResult);
4718             if (CleanedUp) {
4719                 throw new ObjectDisposedException(this.GetType().FullName);
4720             }
4721             if (endPoint==null) {
4722                 throw new ArgumentNullException("endPoint");
4723             }
4724             if (!CanTryAddressFamily(endPoint.AddressFamily)) {
4725                 throw new ArgumentException(SR.GetString(SR.net_InvalidEndPointAddressFamily, 
4726                     endPoint.AddressFamily, addressFamily), "endPoint");
4727             }
4728             if (asyncResult==null) {
4729                 throw new ArgumentNullException("asyncResult");
4730             }
4731             ReceiveMessageOverlappedAsyncResult castedAsyncResult = asyncResult as ReceiveMessageOverlappedAsyncResult;
4732             if (castedAsyncResult==null || castedAsyncResult.AsyncObject!=this) {
4733                 throw new ArgumentException(SR.GetString(SR.net_io_invalidasyncresult), "asyncResult");
4734             }
4735             if (castedAsyncResult.EndCalled) {
4736                 throw new InvalidOperationException(SR.GetString(SR.net_io_invalidendcall, "EndReceiveMessageFrom"));
4737             }
4738
4739             SocketAddress socketAddressOriginal = SnapshotAndSerialize(ref endPoint);
4740
4741             int bytesTransferred = (int)castedAsyncResult.InternalWaitForCompletion();
4742             castedAsyncResult.EndCalled = true;
4743             castedAsyncResult.ExtractCache(ref Caches.ReceiveOverlappedCache);
4744
4745             // Update socket address size
4746             castedAsyncResult.SocketAddress.SetSize(castedAsyncResult.GetSocketAddressSizePtr());
4747             
4748             if (!socketAddressOriginal.Equals(castedAsyncResult.SocketAddress)) {
4749                 try {
4750                     endPoint = endPoint.Create(castedAsyncResult.SocketAddress);
4751                 }
4752                 catch {
4753                 }
4754             }
4755
4756 #if !FEATURE_PAL // perfcounter
4757             if (s_PerfCountersEnabled)
4758             {
4759                 if (bytesTransferred>0) {
4760                     NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketBytesReceived, bytesTransferred);
4761                     if (Transport==TransportType.Udp) {
4762                         NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketDatagramsReceived);
4763                     }
4764                 }
4765             }
4766 #endif //!FEATURE_PAL
4767
4768             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::EndReceiveMessageFrom() bytesTransferred:" + bytesTransferred.ToString());
4769
4770             //
4771             // if the asynchronous native call failed asynchronously
4772             // we'll throw a SocketException
4773             //
4774             if ((SocketError)castedAsyncResult.ErrorCode!=SocketError.Success && (SocketError)castedAsyncResult.ErrorCode != SocketError.MessageSize) {
4775                 //
4776                 // update our internal state after this socket error and throw
4777                 //
4778                 SocketException socketException = new SocketException(castedAsyncResult.ErrorCode);
4779                 UpdateStatusAfterSocketError(socketException);
4780                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "EndReceiveMessageFrom", socketException);
4781                 throw socketException;
4782             }
4783
4784             socketFlags = castedAsyncResult.m_flags;
4785             ipPacketInformation = castedAsyncResult.m_IPPacketInformation;
4786
4787             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "EndReceiveMessageFrom", bytesTransferred);
4788             return bytesTransferred;
4789         }
4790
4791
4792
4793         /*++
4794
4795         Routine Description:
4796
4797            BeginReceiveFrom - Async implimentation of RecvFrom call,
4798
4799            Called when we want to start an async receive.
4800            We kick off the receive, and if it completes synchronously we'll
4801            call the callback. Otherwise we'll return an IASyncResult, which
4802            the caller can use to wait on or retrieve the final status, as needed.
4803
4804            Uses Winsock 2 overlapped I/O.
4805
4806         Arguments:
4807
4808            ReadBuffer - status line that we wish to parse
4809            Index - Offset into ReadBuffer to begin reading from
4810            Request - Size of Buffer to recv
4811            Flags - Additonal Flags that may be passed to the underlying winsock call
4812            remoteEP - EndPoint that are to receive from
4813            Callback - Delegate function that holds callback, called on completeion of I/O
4814            State - State used to track callback, set by caller, not required
4815
4816         Return Value:
4817
4818            IAsyncResult - Async result used to retreive result
4819
4820         --*/
4821
4822         /// <devdoc>
4823         ///    <para>[To be supplied.]</para>
4824         /// </devdoc>
4825         [HostProtection(ExternalThreading=true)]
4826         public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset, int size, SocketFlags socketFlags, ref EndPoint remoteEP, AsyncCallback callback, object state) {
4827
4828             if (s_LoggingEnabled) Logging.Enter(Logging.Sockets, this, "BeginReceiveFrom", "");
4829
4830             if (CleanedUp) {
4831                 throw new ObjectDisposedException(this.GetType().FullName);
4832             }
4833             //
4834             // parameter validation
4835             //
4836             if (buffer==null) {
4837                 throw new ArgumentNullException("buffer");
4838             }
4839             if (remoteEP==null) {
4840                 throw new ArgumentNullException("remoteEP");
4841             }
4842             if (!CanTryAddressFamily(remoteEP.AddressFamily)) {
4843                 throw new ArgumentException(SR.GetString(SR.net_InvalidEndPointAddressFamily, 
4844                     remoteEP.AddressFamily, addressFamily), "remoteEP");
4845             }
4846             if (offset<0 || offset>buffer.Length) {
4847                 throw new ArgumentOutOfRangeException("offset");
4848             }
4849             if (size<0 || size>buffer.Length-offset) {
4850                 throw new ArgumentOutOfRangeException("size");
4851             }
4852             if (m_RightEndPoint==null) {
4853                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustbind));
4854             }
4855
4856             // We don't do a CAS demand here because the contents of remoteEP aren't used by
4857             // WSARecvFrom; all that matters is that we generate a unique-to-this-call SocketAddress
4858             // with the right address family
4859             SocketAddress socketAddress = SnapshotAndSerialize(ref remoteEP);
4860
4861             // Set up the result and set it to collect the context.
4862             OverlappedAsyncResult asyncResult = new OverlappedAsyncResult(this, state, callback);
4863             asyncResult.StartPostingAsyncOp(false);
4864
4865             // Start the ReceiveFrom.
4866             DoBeginReceiveFrom(buffer, offset, size, socketFlags, remoteEP, socketAddress, asyncResult);
4867
4868             // Capture the context, maybe call the callback, and return.
4869             asyncResult.FinishPostingAsyncOp(ref Caches.ReceiveClosureCache);
4870
4871             if (asyncResult.CompletedSynchronously && !asyncResult.SocketAddressOriginal.Equals(asyncResult.SocketAddress)) {
4872                 try {
4873                     remoteEP = remoteEP.Create(asyncResult.SocketAddress);
4874                 }
4875                 catch {
4876                 }
4877             }
4878
4879
4880             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "BeginReceiveFrom", asyncResult);
4881             return asyncResult;
4882         }
4883
4884         private void DoBeginReceiveFrom(byte[] buffer, int offset, int size, SocketFlags socketFlags, EndPoint endPointSnapshot, SocketAddress socketAddress, OverlappedAsyncResult asyncResult)
4885         {
4886             EndPoint oldEndPoint = m_RightEndPoint;
4887             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginReceiveFrom() size:" + size.ToString());
4888
4889             // Guarantee to call CheckAsyncCallOverlappedResult if we call SetUnamangedStructures with a cache in order to
4890             // avoid a Socket leak in case of error.
4891             SocketError errorCode = SocketError.SocketError;
4892             try
4893             {
4894                 // Set up asyncResult for overlapped WSARecvFrom.
4895                 // This call will use completion ports on WinNT and Overlapped IO on Win9x.
4896                 asyncResult.SetUnmanagedStructures(buffer, offset, size, socketAddress, true /* pin remoteEP*/, ref Caches.ReceiveOverlappedCache);
4897
4898                 // save a copy of the original EndPoint in the asyncResult
4899                 asyncResult.SocketAddressOriginal = endPointSnapshot.Serialize();
4900
4901                 if (m_RightEndPoint == null) {
4902                     m_RightEndPoint = endPointSnapshot;
4903                 }
4904
4905                 int bytesTransferred;
4906                 errorCode = UnsafeNclNativeMethods.OSSOCK.WSARecvFrom(
4907                     m_Handle,
4908                     ref asyncResult.m_SingleBuffer,
4909                     1,
4910                     out bytesTransferred,
4911                     ref socketFlags,
4912                     asyncResult.GetSocketAddressPtr(),
4913                     asyncResult.GetSocketAddressSizePtr(),
4914                     asyncResult.OverlappedHandle,
4915                     IntPtr.Zero );
4916
4917                 if (errorCode!=SocketError.Success) {
4918                     errorCode = (SocketError)Marshal.GetLastWin32Error();
4919                 }
4920                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginReceiveFrom() UnsafeNclNativeMethods.OSSOCK.WSARecvFrom returns:" + errorCode.ToString() + " size:" + size.ToString() + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
4921             }
4922             catch (ObjectDisposedException)
4923             {
4924                 m_RightEndPoint = oldEndPoint;
4925                 throw;
4926             }
4927             finally
4928             {
4929                 errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode);
4930             }
4931
4932             //
4933             // if the asynchronous native call fails synchronously
4934             // we'll throw a SocketException
4935             //
4936             if (errorCode!=SocketError.Success) {
4937                 //
4938                 // update our internal state after this socket error and throw
4939                 //
4940                 m_RightEndPoint = oldEndPoint;
4941                 asyncResult.ExtractCache(ref Caches.ReceiveOverlappedCache);
4942                 SocketException socketException = new SocketException(errorCode);
4943                 UpdateStatusAfterSocketError(socketException);
4944                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "BeginReceiveFrom", socketException);
4945                 throw socketException;
4946             }
4947
4948             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginReceiveFrom() size:" + size.ToString() + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
4949         }
4950
4951
4952         /*++
4953
4954         Routine Description:
4955
4956            EndReceiveFrom -  Called when I/O is done or the user wants to wait. If
4957                      the I/O isn't done, we'll wait for it to complete, and then we'll return
4958                      the bytes of I/O done.
4959
4960         Arguments:
4961
4962            AsyncResult - the AsyncResult Returned fron BeginReceiveFrom call
4963
4964         Return Value:
4965
4966            int - Number of bytes transferred
4967
4968         --*/
4969
4970         /// <devdoc>
4971         ///    <para>[To be supplied.]</para>
4972         /// </devdoc>
4973         public int EndReceiveFrom(IAsyncResult asyncResult, ref EndPoint endPoint) {
4974             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "EndReceiveFrom", asyncResult);
4975             if (CleanedUp) {
4976                 throw new ObjectDisposedException(this.GetType().FullName);
4977             }
4978             //
4979             // parameter validation
4980             //
4981             if (endPoint==null) {
4982                 throw new ArgumentNullException("endPoint");
4983             }
4984             if (!CanTryAddressFamily(endPoint.AddressFamily)) {
4985                 throw new ArgumentException(SR.GetString(SR.net_InvalidEndPointAddressFamily, 
4986                     endPoint.AddressFamily, addressFamily), "endPoint");
4987             }
4988             if (asyncResult==null) {
4989                 throw new ArgumentNullException("asyncResult");
4990             }
4991             OverlappedAsyncResult castedAsyncResult = asyncResult as OverlappedAsyncResult;
4992             if (castedAsyncResult==null || castedAsyncResult.AsyncObject!=this) {
4993                 throw new ArgumentException(SR.GetString(SR.net_io_invalidasyncresult), "asyncResult");
4994             }
4995             if (castedAsyncResult.EndCalled) {
4996                 throw new InvalidOperationException(SR.GetString(SR.net_io_invalidendcall, "EndReceiveFrom"));
4997             }
4998
4999             SocketAddress socketAddressOriginal = SnapshotAndSerialize(ref endPoint);
5000
5001             int bytesTransferred = (int)castedAsyncResult.InternalWaitForCompletion();
5002             castedAsyncResult.EndCalled = true;
5003             castedAsyncResult.ExtractCache(ref Caches.ReceiveOverlappedCache);
5004
5005             // Update socket address size
5006             castedAsyncResult.SocketAddress.SetSize(castedAsyncResult.GetSocketAddressSizePtr());
5007
5008             if (!socketAddressOriginal.Equals(castedAsyncResult.SocketAddress)) {
5009                 try {
5010                     endPoint = endPoint.Create(castedAsyncResult.SocketAddress);
5011                 }
5012                 catch {
5013                 }
5014             }
5015
5016 #if !FEATURE_PAL // perfcounter
5017             if (s_PerfCountersEnabled)
5018             {
5019                 if (bytesTransferred>0) {
5020                     NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketBytesReceived, bytesTransferred);
5021                     if (Transport==TransportType.Udp) {
5022                         NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketDatagramsReceived);
5023                     }
5024                 }
5025             }
5026 #endif //!FEATURE_PAL
5027
5028             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::EndReceiveFrom() bytesTransferred:" + bytesTransferred.ToString());
5029
5030             //
5031             // if the asynchronous native call failed asynchronously
5032             // we'll throw a SocketException
5033             //
5034             if ((SocketError)castedAsyncResult.ErrorCode!=SocketError.Success) {
5035                 //
5036                 // update our internal state after this socket error and throw
5037                 //
5038                 SocketException socketException = new SocketException(castedAsyncResult.ErrorCode);
5039                 UpdateStatusAfterSocketError(socketException);
5040                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "EndReceiveFrom", socketException);
5041                 throw socketException;
5042             }
5043             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "EndReceiveFrom", bytesTransferred);
5044             return bytesTransferred;
5045         }
5046
5047
5048         /*++
5049
5050         Routine Description:
5051
5052            BeginAccept - Does a async winsock accept, creating a new socket on success
5053
5054             Works by creating a pending accept request the first time,
5055             and subsequent calls are queued so that when the first accept completes,
5056             the next accept can be resubmitted in the callback.
5057             this routine may go pending at which time,
5058             but any case the callback Delegate will be called upon completion
5059
5060         Arguments:
5061
5062            Callback - Async Callback Delegate that is called upon Async Completion
5063            State - State used to track callback, set by caller, not required
5064
5065         Return Value:
5066
5067            IAsyncResult - Async result used to retreive resultant new socket
5068
5069         --*/
5070
5071         /// <devdoc>
5072         ///    <para>[To be supplied.]</para>
5073         /// </devdoc>
5074         [HostProtection(ExternalThreading=true)]
5075         public IAsyncResult BeginAccept(AsyncCallback callback, object state) {
5076
5077 #if !FEATURE_PAL
5078             if (CanUseAcceptEx)
5079             {
5080                 return BeginAccept(0,callback,state);
5081             }
5082 #endif
5083             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "BeginAccept", "");
5084             if (CleanedUp) {
5085                 throw new ObjectDisposedException(this.GetType().FullName);
5086             }
5087
5088             // Set up the context flow.
5089             AcceptAsyncResult asyncResult = new AcceptAsyncResult(this, state, callback);
5090             asyncResult.StartPostingAsyncOp(false);
5091
5092             // Do the accept.
5093             DoBeginAccept(asyncResult);
5094
5095             // Set up for return.
5096             asyncResult.FinishPostingAsyncOp(ref Caches.AcceptClosureCache);
5097
5098             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "BeginAccept", asyncResult);
5099             return asyncResult;
5100         }
5101
5102         private void DoBeginAccept(LazyAsyncResult asyncResult)
5103         {
5104             if (m_RightEndPoint==null) {
5105                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustbind));
5106             }
5107
5108             if(!isListening){
5109                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustlisten));
5110             }
5111
5112             //
5113             // We keep a queue, which lists the set of requests that want to
5114             //  be called when an accept queue completes.  We call accept
5115             //  once, and then as it completes asyncrounsly we pull the
5116             //  requests out of the queue and call their callback.
5117             //
5118             // We start by grabbing Critical Section, then attempt to
5119             //  determine if we haven an empty Queue of Accept Sockets
5120             //  or if its in a Callback on the Callback thread.
5121             //
5122             // If its in the callback thread proocessing of the callback, then we
5123             //  just need to notify the callback by adding an additional request
5124             //   to the queue.
5125             //
5126             // If its an empty queue, and its not in the callback, then
5127             //   we just need to get the Accept going, make it go async
5128             //   and leave.
5129             //
5130             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginAccept()");
5131
5132             bool needFinishedCall = false;
5133             SocketError errorCode = 0;
5134
5135             Queue acceptQueue = GetAcceptQueue();
5136             lock(this)
5137             {
5138                 if (acceptQueue.Count == 0)
5139                 {
5140                     SocketAddress socketAddress = m_RightEndPoint.Serialize();
5141
5142                     GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginAccept() queue is empty calling UnsafeNclNativeMethods.OSSOCK.accept");
5143
5144                     // Check if a socket is already available.  We need to be non-blocking to do this.
5145                     InternalSetBlocking(false);
5146
5147                     SafeCloseSocket acceptedSocketHandle = null;
5148                     try
5149                     {
5150                         acceptedSocketHandle = SafeCloseSocket.Accept(
5151                             m_Handle,
5152                             socketAddress.m_Buffer,
5153                             ref socketAddress.m_Size);
5154                         errorCode = acceptedSocketHandle.IsInvalid ? (SocketError) Marshal.GetLastWin32Error() : SocketError.Success;
5155                     }
5156                     catch (ObjectDisposedException)
5157                     {
5158                         errorCode = SocketError.NotSocket;
5159                     }
5160
5161                     GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginAccept() UnsafeNclNativeMethods.OSSOCK.accept returns:" + errorCode.ToString());
5162
5163                     if (errorCode != SocketError.WouldBlock)
5164                     {
5165                         if (errorCode == SocketError.Success)
5166                         {
5167                             asyncResult.Result = CreateAcceptSocket(acceptedSocketHandle, m_RightEndPoint.Create(socketAddress), false);
5168                         }
5169                         else
5170                         {
5171                             asyncResult.ErrorCode = (int) errorCode;
5172                         }
5173
5174                         // Reset the blocking.
5175                         InternalSetBlocking(true);
5176
5177                         // Continue outside the lock.
5178                         needFinishedCall = true;
5179                     }
5180                     else
5181                     {
5182                         // It would block.  Start listening for accepts, and add ourselves to the queue.
5183                         acceptQueue.Enqueue(asyncResult);
5184                         if (!SetAsyncEventSelect(AsyncEventBits.FdAccept))
5185                         {
5186                             acceptQueue.Dequeue();
5187                             throw new ObjectDisposedException(this.GetType().FullName);
5188                         }
5189                     }
5190                 }
5191                 else {
5192                     acceptQueue.Enqueue(asyncResult);
5193
5194                     GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginAccept() queue is not empty Count:" + acceptQueue.Count.ToString());
5195                 }
5196             }
5197
5198             if (needFinishedCall) {
5199                 if (errorCode == SocketError.Success)
5200                 {
5201                     // Completed synchronously, invoke the callback.
5202                     asyncResult.InvokeCallback();
5203                 }
5204                 else
5205                 {
5206                     //
5207                     // update our internal state after this socket error and throw
5208                     //
5209                     SocketException socketException = new SocketException(errorCode);
5210                     UpdateStatusAfterSocketError(socketException);
5211                     if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "BeginAccept", socketException);
5212                     throw socketException;
5213                 }
5214             }
5215
5216             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginAccept() returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
5217         }
5218
5219         //
5220         // This is a shortcut to AcceptCallback when called from dispose.
5221         // The only business is lock and complete all results with an error
5222         //
5223         private void CompleteAcceptResults(object nullState)
5224         {
5225             Queue acceptQueue = GetAcceptQueue();
5226             bool acceptNeeded = true;
5227             while (acceptNeeded)
5228             {
5229                 LazyAsyncResult asyncResult = null;
5230                 lock (this)
5231                 {
5232                     // If the queue is empty, cancel the select and indicate not to loop anymore.
5233                     if (acceptQueue.Count == 0)
5234                         break;
5235                     asyncResult = (LazyAsyncResult) acceptQueue.Dequeue();
5236
5237                     if (acceptQueue.Count == 0)
5238                         acceptNeeded = false;
5239                 }
5240
5241                 // Notify about the completion outside the lock.
5242                 try {
5243                     asyncResult.InvokeCallback(new SocketException(SocketError.OperationAborted));
5244                 }
5245                 catch {
5246                     // Exception from the user callback,
5247                     // If we need to loop, offload to a different thread and re-throw for debugging
5248                     if (acceptNeeded)
5249                         ThreadPool.UnsafeQueueUserWorkItem(new WaitCallback(CompleteAcceptResults), null);
5250
5251                     throw;
5252                 }
5253             }
5254         }
5255
5256         // This method was originally in an AcceptAsyncResult class but that class got useless.
5257         private void AcceptCallback(object nullState)
5258         {
5259             // We know we need to try completing an accept at first.  Keep going until the queue is empty (inside the lock).
5260             // At that point, BeginAccept() takes control of restarting the pump if necessary.
5261             bool acceptNeeded = true;
5262             Queue acceptQueue = GetAcceptQueue();
5263
5264             while (acceptNeeded)
5265             {
5266                 LazyAsyncResult asyncResult = null;
5267                 SocketError errorCode = SocketError.OperationAborted;
5268                 SocketAddress socketAddress = null;
5269                 SafeCloseSocket acceptedSocket = null;
5270                 Exception otherException = null;
5271                 object result = null;
5272
5273                 lock (this)
5274                 {
5275                     //
5276                     // Accept Callback - called on the callback path, when we expect to release
5277                     //  an accept socket that winsock says has completed.
5278                     //
5279                     //  While we still have items in our Queued list of Accept Requests,
5280                     //   we recall the Winsock accept, to attempt to gather new
5281                     //   results, and then match them again the queued items,
5282                     //   when accept call returns would_block, we reinvoke ourselves
5283                     //   and rewait for the next asyc callback.
5284                     //
5285
5286                     //
5287                     // We may not have items in the queue because of possible ----
5288                     // between re-entering this callback manually and from the thread pool.
5289                     //
5290                     if (acceptQueue.Count == 0)
5291                         break;
5292
5293                     // pick an element from the head of the list
5294                     asyncResult = (LazyAsyncResult) acceptQueue.Peek();
5295
5296                     if (!CleanedUp)
5297                     {
5298                         socketAddress = m_RightEndPoint.Serialize();
5299
5300                         try
5301                         {
5302                             // We know we're in non-blocking because of SetAsyncEventSelect().
5303                             GlobalLog.Assert(!willBlockInternal, "Socket#{0}::AcceptCallback|Socket should be in non-blocking state.", ValidationHelper.HashString(this));
5304                             acceptedSocket = SafeCloseSocket.Accept(
5305                                 m_Handle,
5306                                 socketAddress.m_Buffer,
5307                                 ref socketAddress.m_Size);
5308
5309                             errorCode = acceptedSocket.IsInvalid ? (SocketError) Marshal.GetLastWin32Error() : SocketError.Success;
5310
5311                             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::AcceptCallback() UnsafeNclNativeMethods.OSSOCK.accept returns:" + errorCode.ToString());
5312                         }
5313                         catch (ObjectDisposedException)
5314                         {
5315                             // Listener socket was closed.
5316                             errorCode = SocketError.OperationAborted;
5317                         }
5318                         catch (Exception exception)
5319                         {
5320                             if (NclUtilities.IsFatal(exception)) throw;
5321
5322                             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::AcceptCallback() caught exception:" + exception.Message + " CleanedUp:" + CleanedUp);
5323                             otherException = exception;
5324                         }
5325                     }
5326
5327                     if (errorCode == SocketError.WouldBlock && otherException == null)
5328                     {
5329                         // The accept found no waiting connections, so start listening for more.
5330                         try
5331                         {
5332                             m_AsyncEvent.Reset(); // reset event to wait for the next client.
5333                             if (SetAsyncEventSelect(AsyncEventBits.FdAccept))
5334                                 break;
5335                         }
5336                         catch (ObjectDisposedException)
5337                         { 
5338                             // Handle ---- with Dispose, m_AsyncEvent may have been Close()'d already.
5339                         }
5340                         otherException = new ObjectDisposedException(this.GetType().FullName);
5341                     }
5342
5343                     // CreateAcceptSocket() must be done before InternalSetBlocking() so that the fixup is correct inside
5344                     // UpdateAcceptSocket().  InternalSetBlocking() must happen in the lock.
5345                     if (otherException != null)
5346                     {
5347                         result = otherException;
5348                     }
5349                     else if (errorCode == SocketError.Success)
5350                     {
5351                         result = CreateAcceptSocket(acceptedSocket, m_RightEndPoint.Create(socketAddress), true);
5352                     }
5353                     else
5354                     {
5355                         asyncResult.ErrorCode = (int) errorCode;
5356                     }
5357
5358                     // This request completed, so it can be taken off the queue.
5359                     acceptQueue.Dequeue();
5360
5361                     // If the queue is empty, cancel the select and indicate not to loop anymore.
5362                     if (acceptQueue.Count == 0)
5363                     {
5364                         if (!CleanedUp)
5365                             UnsetAsyncEventSelect();
5366
5367                         acceptNeeded = false;
5368                     }
5369                 }
5370
5371                 // Notify about the completion outside the lock.
5372                 try {
5373                     asyncResult.InvokeCallback(result);
5374                 }
5375                 catch {
5376                     // Exception from the user callback,
5377                     // If we need to loop, offload to a different thread and re-throw for debugging
5378                     if (acceptNeeded)
5379                         ThreadPool.UnsafeQueueUserWorkItem(new WaitCallback(AcceptCallback), nullState);
5380
5381                     throw;
5382                 }
5383             }
5384         }
5385 #endif // !MONO
5386
5387 #if !FEATURE_PAL
5388 #if !MONO
5389         private bool CanUseAcceptEx
5390         {
5391             get
5392             {
5393                 return
5394                     (Thread.CurrentThread.IsThreadPoolThread || SettingsSectionInternal.Section.AlwaysUseCompletionPortsForAccept || m_IsDisconnected);
5395             }
5396         }
5397 #endif // !MONO
5398
5399         /// <devdoc>
5400         ///    <para>[To be supplied.]</para>
5401         /// </devdoc>
5402         [HostProtection(ExternalThreading=true)]
5403         public IAsyncResult BeginAccept(int receiveSize, AsyncCallback callback, object state) {
5404             return BeginAccept(null,receiveSize,callback,state);
5405         }
5406
5407         ///  This is the true async version that uses AcceptEx
5408
5409 #if !MONO
5410         /// <devdoc>
5411         ///    <para>[To be supplied.]</para>
5412         /// </devdoc>
5413         [HostProtection(ExternalThreading=true)]
5414         public IAsyncResult BeginAccept(Socket acceptSocket, int receiveSize, AsyncCallback callback, object state) {
5415             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "BeginAccept", "");
5416             if (CleanedUp) {
5417                 throw new ObjectDisposedException(this.GetType().FullName);
5418             }
5419
5420             //
5421             // parameter validation
5422             //
5423             if (receiveSize<0) {
5424                 throw new ArgumentOutOfRangeException("size");
5425             }
5426
5427             // Set up the async result with flowing.
5428             AcceptOverlappedAsyncResult asyncResult = new AcceptOverlappedAsyncResult(this, state, callback);
5429             asyncResult.StartPostingAsyncOp(false);
5430
5431             // Start the accept.
5432             DoBeginAccept(acceptSocket, receiveSize, asyncResult);
5433
5434             // Finish the flow capture, maybe complete here.
5435             asyncResult.FinishPostingAsyncOp(ref Caches.AcceptClosureCache);
5436
5437             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "BeginAccept", asyncResult);
5438             return asyncResult;
5439         }
5440
5441         private void DoBeginAccept(Socket acceptSocket, int receiveSize, AcceptOverlappedAsyncResult asyncResult)
5442         {
5443             if (m_RightEndPoint==null) {
5444                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustbind));
5445             }
5446
5447             if(!isListening){
5448                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustlisten));
5449             }
5450
5451             // if a acceptSocket isn't specified, then we need to create it.
5452             if (acceptSocket == null) {
5453                 acceptSocket = new Socket(addressFamily,socketType,protocolType);
5454             }
5455             else
5456             {
5457                 if (acceptSocket.m_RightEndPoint != null) {
5458                     throw new InvalidOperationException(SR.GetString(SR.net_sockets_namedmustnotbebound, "acceptSocket"));
5459                 }
5460             }
5461             asyncResult.AcceptSocket = acceptSocket;
5462
5463             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginAccept() AcceptSocket:" + ValidationHelper.HashString(acceptSocket));
5464
5465             //the buffer needs to contain the requested data plus room for two sockaddrs and 16 bytes
5466             //of associated data for each.
5467             int addressBufferSize = m_RightEndPoint.Serialize().Size + 16;
5468             byte[] buffer = new byte[receiveSize + ((addressBufferSize) * 2)];
5469
5470             //
5471             // Set up asyncResult for overlapped AcceptEx.
5472             // This call will use
5473             // completion ports on WinNT
5474             //
5475
5476             asyncResult.SetUnmanagedStructures(buffer, addressBufferSize);
5477
5478             // This can throw ObjectDisposedException.
5479             int bytesTransferred;
5480             SocketError errorCode = SocketError.Success;
5481             if (!AcceptEx(
5482                 m_Handle,
5483                 acceptSocket.m_Handle,
5484                 Marshal.UnsafeAddrOfPinnedArrayElement(asyncResult.Buffer, 0),
5485                 receiveSize,
5486                 addressBufferSize,
5487                 addressBufferSize,
5488                 out bytesTransferred,
5489                 asyncResult.OverlappedHandle))
5490             {
5491                 errorCode = (SocketError)Marshal.GetLastWin32Error();
5492             }
5493             errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode);
5494
5495             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginAccept() UnsafeNclNativeMethods.OSSOCK.AcceptEx returns:" + errorCode.ToString() + ValidationHelper.HashString(asyncResult));
5496
5497             //
5498             // if the asynchronous native call fails synchronously
5499             // we'll throw a SocketException
5500             //
5501             if (errorCode!=SocketError.Success) {
5502                 SocketException socketException = new SocketException(errorCode);
5503                 UpdateStatusAfterSocketError(socketException);
5504                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "BeginAccept", socketException);
5505                 throw socketException;
5506             }
5507         }
5508 #endif // !MONO
5509 #endif // !FEATURE_PAL
5510
5511         /*++
5512
5513         Routine Description:
5514
5515            EndAccept -  Called by user code addressFamilyter I/O is done or the user wants to wait.
5516                         until Async completion, so it provides End handling for aync Accept calls,
5517                         and retrieves new Socket object
5518
5519         Arguments:
5520
5521            AsyncResult - the AsyncResult Returned fron BeginAccept call
5522
5523         Return Value:
5524
5525            Socket - a valid socket if successful
5526
5527         --*/
5528
5529 #if !MONO
5530         /// <devdoc>
5531         ///    <para>[To be supplied.]</para>
5532         /// </devdoc>
5533
5534
5535
5536         public Socket EndAccept(IAsyncResult asyncResult) {
5537             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "EndAccept", asyncResult);
5538             if (CleanedUp) {
5539                 throw new ObjectDisposedException(this.GetType().FullName);
5540             }
5541
5542 #if !FEATURE_PAL
5543             if (asyncResult != null && (asyncResult is AcceptOverlappedAsyncResult)) {
5544                 int bytesTransferred;
5545                 byte[] buffer;
5546                 return EndAccept(out buffer, out bytesTransferred, asyncResult);
5547             }
5548 #endif // !FEATURE_PAL
5549
5550             //
5551             // parameter validation
5552             //
5553             if (asyncResult==null) {
5554                 throw new ArgumentNullException("asyncResult");
5555             }
5556
5557             AcceptAsyncResult castedAsyncResult = asyncResult as AcceptAsyncResult;
5558             if (castedAsyncResult==null || castedAsyncResult.AsyncObject!=this) {
5559                 throw new ArgumentException(SR.GetString(SR.net_io_invalidasyncresult), "asyncResult");
5560             }
5561             if (castedAsyncResult.EndCalled) {
5562                 throw new InvalidOperationException(SR.GetString(SR.net_io_invalidendcall, "EndAccept"));
5563             }
5564
5565             object result = castedAsyncResult.InternalWaitForCompletion();
5566             castedAsyncResult.EndCalled = true;
5567
5568             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::EndAccept() acceptedSocket:" + ValidationHelper.HashString(result));
5569
5570             //
5571             // if the asynchronous native call failed asynchronously
5572             // we'll throw a SocketException
5573             //
5574             Exception exception = result as Exception;
5575             if (exception != null)
5576             {
5577                 throw exception;
5578             }
5579
5580             if ((SocketError)castedAsyncResult.ErrorCode!=SocketError.Success) {
5581                 //
5582                 // update our internal state after this socket error and throw
5583                 //
5584                 SocketException socketException = new SocketException(castedAsyncResult.ErrorCode);
5585                 UpdateStatusAfterSocketError(socketException);
5586                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "EndAccept", socketException);
5587                 throw socketException;
5588             }
5589
5590             Socket acceptedSocket = (Socket)result;
5591
5592             if (s_LoggingEnabled) {
5593                 Logging.PrintInfo(Logging.Sockets, acceptedSocket, 
5594                     SR.GetString(SR.net_log_socket_accepted, acceptedSocket.RemoteEndPoint, acceptedSocket.LocalEndPoint));
5595                 Logging.Exit(Logging.Sockets, this, "EndAccept", result);
5596             }
5597             return acceptedSocket;
5598         }
5599 #endif // !MONO
5600
5601 #if !FEATURE_PAL
5602         /// <devdoc>
5603         ///    <para>[To be supplied.]</para>
5604         /// </devdoc>
5605
5606         public Socket EndAccept( out byte[] buffer, IAsyncResult asyncResult) {
5607             int bytesTransferred;
5608             byte[] innerBuffer;
5609
5610             Socket socket = EndAccept(out innerBuffer,out bytesTransferred, asyncResult);
5611             buffer = new byte[bytesTransferred];
5612             Array.Copy(innerBuffer,buffer,bytesTransferred);
5613             return socket;
5614         }
5615
5616 #if !MONO
5617         /// <devdoc>
5618         ///    <para>[To be supplied.]</para>
5619         /// </devdoc>
5620
5621         public Socket EndAccept( out byte[] buffer, out int bytesTransferred, IAsyncResult asyncResult) {
5622             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "EndAccept", asyncResult);
5623             if (CleanedUp) {
5624                 throw new ObjectDisposedException(this.GetType().FullName);
5625             }
5626
5627             //
5628             // parameter validation
5629             //
5630             if (asyncResult==null) {
5631                 throw new ArgumentNullException("asyncResult");
5632             }
5633             AcceptOverlappedAsyncResult castedAsyncResult = asyncResult as AcceptOverlappedAsyncResult;
5634             if (castedAsyncResult==null || castedAsyncResult.AsyncObject!=this) {
5635                 throw new ArgumentException(SR.GetString(SR.net_io_invalidasyncresult), "asyncResult");
5636             }
5637             if (castedAsyncResult.EndCalled) {
5638                 throw new InvalidOperationException(SR.GetString(SR.net_io_invalidendcall, "EndAccept"));
5639             }
5640
5641             Socket socket = (Socket)castedAsyncResult.InternalWaitForCompletion();
5642             bytesTransferred = (int)castedAsyncResult.BytesTransferred;
5643             buffer = castedAsyncResult.Buffer;
5644
5645             castedAsyncResult.EndCalled = true;
5646
5647 #if !FEATURE_PAL // perfcounter
5648             if (s_PerfCountersEnabled)
5649             {
5650                 if (bytesTransferred>0) {
5651                     NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketBytesReceived, bytesTransferred);
5652                 }
5653             }
5654 #endif
5655             //
5656             // if the asynchronous native call failed asynchronously
5657             // we'll throw a SocketException
5658             //
5659             if ((SocketError)castedAsyncResult.ErrorCode!=SocketError.Success) {
5660                 //
5661                 // update our internal state after this socket error and throw
5662                 //
5663                 SocketException socketException = new SocketException(castedAsyncResult.ErrorCode);
5664                 UpdateStatusAfterSocketError(socketException);
5665                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "EndAccept", socketException);
5666                 throw socketException;
5667             }
5668
5669 #if TRAVE
5670             try
5671             {
5672                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::EndAccept() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " acceptedSocket:" + ValidationHelper.HashString(socket) + " acceptedSocket.SRC:" + ValidationHelper.ToString(socket.LocalEndPoint) + " acceptedSocket.DST:" + ValidationHelper.ToString(socket.RemoteEndPoint) + " bytesTransferred:" + bytesTransferred.ToString());
5673             }
5674             catch (ObjectDisposedException) { }
5675 #endif
5676
5677             if (s_LoggingEnabled) {
5678                 Logging.PrintInfo(Logging.Sockets, socket, SR.GetString(SR.net_log_socket_accepted, socket.RemoteEndPoint, socket.LocalEndPoint));
5679                 Logging.Exit(Logging.Sockets, this, "EndAccept", socket);
5680             }
5681             return socket;
5682         }
5683 #endif // !MONO
5684 #endif // !FEATURE_PAL
5685
5686
5687
5688
5689 #if !MONO
5690         /// <devdoc>
5691         ///    <para>
5692         ///       Disables sends and receives on a socket.
5693         ///    </para>
5694         /// </devdoc>
5695         public void Shutdown(SocketShutdown how) {
5696             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "Shutdown", how);
5697             if (CleanedUp) {
5698                 throw new ObjectDisposedException(this.GetType().FullName);
5699             }
5700
5701             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Shutdown() how:" + how.ToString());
5702
5703             // This can throw ObjectDisposedException.
5704             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.shutdown(m_Handle, (int) how);
5705
5706             //
5707             // if the native call fails we'll throw a SocketException
5708             //
5709             errorCode = errorCode!=SocketError.SocketError ? SocketError.Success : (SocketError)Marshal.GetLastWin32Error();
5710
5711             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Shutdown() UnsafeNclNativeMethods.OSSOCK.shutdown returns errorCode:" + errorCode);
5712
5713             //
5714             // skip good cases: success, socket already closed
5715             //
5716             if (errorCode!=SocketError.Success && errorCode!=SocketError.NotSocket) {
5717                 //
5718                 // update our internal state after this socket error and throw
5719                 //
5720                 SocketException socketException = new SocketException(errorCode);
5721                 UpdateStatusAfterSocketError(socketException);
5722                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "Shutdown", socketException );
5723                 throw socketException;
5724             }
5725
5726             SetToDisconnected();
5727             InternalSetBlocking(willBlockInternal);
5728             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "Shutdown", "");
5729         }
5730 #endif
5731
5732
5733 //************* internal and private properties *************************
5734
5735         private static object InternalSyncObject {
5736             get {
5737                 if (s_InternalSyncObject == null) {
5738                     object o = new object();
5739                     Interlocked.CompareExchange(ref s_InternalSyncObject, o, null);
5740                 }
5741                 return s_InternalSyncObject;
5742             }
5743         }
5744
5745 #if !MONO
5746         private CacheSet Caches
5747         {
5748             get
5749             {
5750                 if (m_Caches == null)
5751                 {
5752                     // It's not too bad if extra of these are created and lost.
5753                     m_Caches = new CacheSet();
5754                 }
5755                 return m_Caches;
5756             }
5757         }
5758
5759         private void EnsureDynamicWinsockMethods()
5760         {
5761             if (m_DynamicWinsockMethods == null)
5762             {
5763                 m_DynamicWinsockMethods = DynamicWinsockMethods.GetMethods(addressFamily, socketType, protocolType);
5764             }
5765         }
5766
5767         private bool AcceptEx(SafeCloseSocket listenSocketHandle,
5768                               SafeCloseSocket acceptSocketHandle,
5769                               IntPtr buffer,
5770                               int len,
5771                               int localAddressLength,
5772                               int remoteAddressLength,
5773                               out int bytesReceived,
5774                               SafeHandle overlapped)
5775         {
5776             EnsureDynamicWinsockMethods();
5777             AcceptExDelegate acceptEx = m_DynamicWinsockMethods.GetDelegate<AcceptExDelegate>(listenSocketHandle);
5778
5779             return acceptEx(listenSocketHandle, 
5780                             acceptSocketHandle, 
5781                             buffer, 
5782                             len, 
5783                             localAddressLength, 
5784                             remoteAddressLength, 
5785                             out bytesReceived, 
5786                             overlapped);
5787         }
5788
5789         internal void GetAcceptExSockaddrs(IntPtr buffer,
5790                                            int receiveDataLength,
5791                                            int localAddressLength,
5792                                            int remoteAddressLength,
5793                                            out IntPtr localSocketAddress,
5794                                            out int localSocketAddressLength,
5795                                            out IntPtr remoteSocketAddress,
5796                                            out int remoteSocketAddressLength)
5797         {
5798             EnsureDynamicWinsockMethods();
5799             GetAcceptExSockaddrsDelegate getAcceptExSockaddrs = m_DynamicWinsockMethods.GetDelegate<GetAcceptExSockaddrsDelegate>(m_Handle);
5800
5801             getAcceptExSockaddrs(buffer,
5802                                  receiveDataLength,
5803                                  localAddressLength,
5804                                  remoteAddressLength,
5805                                  out localSocketAddress,
5806                                  out localSocketAddressLength,
5807                                  out remoteSocketAddress,
5808                                  out remoteSocketAddressLength);
5809         }
5810
5811         private bool DisconnectEx(SafeCloseSocket socketHandle, SafeHandle overlapped, int flags, int reserved)
5812         {
5813             EnsureDynamicWinsockMethods();
5814             DisconnectExDelegate disconnectEx = m_DynamicWinsockMethods.GetDelegate<DisconnectExDelegate>(socketHandle);
5815
5816             return disconnectEx(socketHandle, overlapped, flags, reserved);
5817         }
5818
5819         private bool DisconnectEx_Blocking(IntPtr socketHandle, IntPtr overlapped, int flags, int reserved)
5820         {
5821             EnsureDynamicWinsockMethods();
5822             DisconnectExDelegate_Blocking disconnectEx_Blocking = m_DynamicWinsockMethods.GetDelegate<DisconnectExDelegate_Blocking>(m_Handle);
5823
5824             return disconnectEx_Blocking(socketHandle, overlapped, flags, reserved);
5825         }
5826
5827         private bool ConnectEx(SafeCloseSocket socketHandle, 
5828                                IntPtr socketAddress, 
5829                                int socketAddressSize,
5830                                IntPtr buffer,
5831                                int dataLength,
5832                                out int bytesSent,
5833                                SafeHandle overlapped)
5834         {
5835             EnsureDynamicWinsockMethods();
5836             ConnectExDelegate connectEx = m_DynamicWinsockMethods.GetDelegate<ConnectExDelegate>(socketHandle);
5837
5838             return connectEx(socketHandle, socketAddress, socketAddressSize, buffer, dataLength, out bytesSent, overlapped);
5839         }
5840
5841         private SocketError WSARecvMsg(SafeCloseSocket socketHandle, IntPtr msg, out int bytesTransferred, SafeHandle overlapped, IntPtr completionRoutine)
5842         {
5843             EnsureDynamicWinsockMethods();
5844             WSARecvMsgDelegate recvMsg = m_DynamicWinsockMethods.GetDelegate<WSARecvMsgDelegate>(socketHandle);
5845
5846             return recvMsg(socketHandle, msg, out bytesTransferred, overlapped, completionRoutine);
5847         }
5848
5849         private SocketError WSARecvMsg_Blocking(IntPtr socketHandle, IntPtr msg, out int bytesTransferred, IntPtr overlapped, IntPtr completionRoutine)
5850         {
5851             EnsureDynamicWinsockMethods();
5852             WSARecvMsgDelegate_Blocking recvMsg_Blocking = m_DynamicWinsockMethods.GetDelegate<WSARecvMsgDelegate_Blocking>(m_Handle);
5853
5854             return recvMsg_Blocking(socketHandle, msg, out bytesTransferred, overlapped, completionRoutine);
5855         }
5856
5857         private bool TransmitPackets(SafeCloseSocket socketHandle, IntPtr packetArray, int elementCount, int sendSize, SafeNativeOverlapped overlapped, TransmitFileOptions flags)
5858         {
5859             EnsureDynamicWinsockMethods();
5860             TransmitPacketsDelegate transmitPackets = m_DynamicWinsockMethods.GetDelegate<TransmitPacketsDelegate>(socketHandle);
5861
5862             return transmitPackets(socketHandle, packetArray, elementCount, sendSize, overlapped, flags);
5863         }
5864
5865         private Queue GetAcceptQueue() {
5866             if (m_AcceptQueueOrConnectResult == null)
5867                 Interlocked.CompareExchange(ref m_AcceptQueueOrConnectResult, new Queue(16), null);
5868             return (Queue)m_AcceptQueueOrConnectResult;
5869         }
5870 #endif // !MONO
5871
5872         internal bool CleanedUp {
5873             get {
5874                 return (m_IntCleanedUp == 1);
5875             }
5876         }
5877
5878 #if !MONO
5879         internal TransportType Transport {
5880             get {
5881                 return
5882                     protocolType==Sockets.ProtocolType.Tcp ?
5883                         TransportType.Tcp :
5884                         protocolType==Sockets.ProtocolType.Udp ?
5885                             TransportType.Udp :
5886                             TransportType.All;
5887             }
5888         }
5889
5890
5891 //************* internal and private methods *************************
5892
5893
5894
5895     private void CheckSetOptionPermissions(SocketOptionLevel optionLevel, SocketOptionName optionName) {
5896             // freely allow only those below
5897             if (  !(optionLevel == SocketOptionLevel.Tcp &&
5898                   (optionName == SocketOptionName.NoDelay   ||
5899                    optionName == SocketOptionName.BsdUrgent ||
5900                    optionName == SocketOptionName.Expedited))
5901                   &&
5902                   !(optionLevel == SocketOptionLevel.Udp &&
5903                     (optionName == SocketOptionName.NoChecksum||
5904                      optionName == SocketOptionName.ChecksumCoverage))
5905                   &&
5906                   !(optionLevel == SocketOptionLevel.Socket &&
5907                   (optionName == SocketOptionName.KeepAlive     ||
5908                    optionName == SocketOptionName.Linger        ||
5909                    optionName == SocketOptionName.DontLinger    ||
5910                    optionName == SocketOptionName.SendBuffer    ||
5911                    optionName == SocketOptionName.ReceiveBuffer ||
5912                    optionName == SocketOptionName.SendTimeout   ||
5913                    optionName == SocketOptionName.ExclusiveAddressUse   ||
5914                    optionName == SocketOptionName.ReceiveTimeout))
5915                   &&
5916                   //ipv6 protection level
5917                   !(optionLevel == SocketOptionLevel.IPv6 &&
5918                     optionName == (SocketOptionName)23)){
5919
5920                 ExceptionHelper.UnmanagedPermission.Demand();
5921             }
5922         }
5923
5924         private SocketAddress SnapshotAndSerialize(ref EndPoint remoteEP)
5925         {
5926             IPEndPoint ipSnapshot = remoteEP as IPEndPoint;
5927
5928             if (ipSnapshot != null)
5929             {
5930                 ipSnapshot = ipSnapshot.Snapshot();
5931                 remoteEP = RemapIPEndPoint(ipSnapshot);
5932             }
5933
5934             return CallSerializeCheckDnsEndPoint(remoteEP);
5935         }
5936
5937         // Give a nicer exception for DnsEndPoint in cases where it is not supported
5938         private SocketAddress CallSerializeCheckDnsEndPoint(EndPoint remoteEP)
5939         {
5940             if (remoteEP is DnsEndPoint)
5941             {
5942                 throw new ArgumentException(SR.GetString(SR.net_sockets_invalid_dnsendpoint, "remoteEP"), "remoteEP");
5943             }
5944
5945             return remoteEP.Serialize();
5946         }
5947
5948         // DualMode: Automatically re-map IPv4 addresses to IPv6 addresses
5949         private IPEndPoint RemapIPEndPoint(IPEndPoint input)
5950         {
5951             if (input.AddressFamily == AddressFamily.InterNetwork && IsDualMode)
5952             {
5953                 return new IPEndPoint(input.Address.MapToIPv6(), input.Port);
5954             }
5955             return input;
5956         }
5957
5958         //
5959         // socketAddress must always be the result of remoteEP.Serialize()
5960         //
5961         private SocketAddress CheckCacheRemote(ref EndPoint remoteEP, bool isOverwrite)
5962         {
5963             IPEndPoint ipSnapshot = remoteEP as IPEndPoint;
5964
5965             if (ipSnapshot != null)
5966             {
5967                 // Snapshot to avoid external tampering and malicious derivations if IPEndPoint
5968                 ipSnapshot = ipSnapshot.Snapshot();
5969                 // DualMode: Do the security check on the user input address, but return an IPEndPoint 
5970                 // mapped to an IPv6 address.
5971                 remoteEP = RemapIPEndPoint(ipSnapshot);
5972             }
5973
5974             // This doesn't use SnapshotAndSerialize() because we need the ipSnapshot later.
5975             SocketAddress socketAddress = CallSerializeCheckDnsEndPoint(remoteEP);
5976
5977             // We remember the first peer we have communicated with
5978             SocketAddress permittedRemoteAddress = m_PermittedRemoteAddress;
5979             if (permittedRemoteAddress != null && permittedRemoteAddress.Equals(socketAddress))
5980             {
5981                 return permittedRemoteAddress;
5982             }
5983
5984             //
5985             // for now SocketPermission supports only IPEndPoint
5986             //
5987             if (ipSnapshot != null)
5988             {
5989                 //
5990                 // create the permissions the user would need for the call
5991                 //
5992                 SocketPermission socketPermission
5993                     = new SocketPermission(
5994                         NetworkAccess.Connect,
5995                         Transport,
5996                         ipSnapshot.Address.ToString(),
5997                         ipSnapshot.Port);
5998                 //
5999                 // demand for them
6000                 //
6001                 socketPermission.Demand();
6002             }
6003             else {
6004                 //
6005                 // for V1 we will demand permission to run UnmanagedCode for
6006                 // an EndPoint that is not an IPEndPoint until we figure out how these fit
6007                 // into the whole picture of SocketPermission
6008                 //
6009
6010                 ExceptionHelper.UnmanagedPermission.Demand();
6011             }
6012             //cache only the first peer we communicated with
6013             if (m_PermittedRemoteAddress == null || isOverwrite) {
6014                 m_PermittedRemoteAddress = socketAddress;
6015             }
6016
6017             return socketAddress;
6018         }
6019 #endif
6020
6021         internal static void InitializeSockets() {
6022             if (!s_Initialized) {
6023                 lock(InternalSyncObject){
6024                     if (!s_Initialized) {
6025
6026 #if !MONO
6027                         WSAData wsaData = new WSAData();
6028
6029                         SocketError errorCode =
6030                             UnsafeNclNativeMethods.OSSOCK.WSAStartup(
6031                                 (short)0x0202, // we need 2.2
6032                                 out wsaData );
6033
6034                         if (errorCode!=SocketError.Success) {
6035                             //
6036                             // failed to initialize, throw
6037                             //
6038                             // WSAStartup does not set LastWin32Error
6039                             throw new SocketException(errorCode);
6040                         }
6041 #endif
6042
6043 #if !FEATURE_PAL
6044                         //
6045                         // we're on WinNT4 or greater, we could use CompletionPort if we
6046                         // wanted. check if the user has disabled this functionality in
6047                         // the registry, otherwise use CompletionPort.
6048                         //
6049
6050 #if DEBUG
6051                         BooleanSwitch disableCompletionPortSwitch = new BooleanSwitch("DisableNetCompletionPort", "System.Net disabling of Completion Port");
6052
6053                         //
6054                         // the following will be true if they've disabled the completionPort
6055                         //
6056                         UseOverlappedIO = disableCompletionPortSwitch.Enabled;
6057 #endif
6058                         
6059                         bool   ipv4      = true; 
6060                         bool   ipv6      = true; 
6061
6062 #if MONO
6063                         ipv4 = IsProtocolSupported (System.Net.NetworkInformation.NetworkInterfaceComponent.IPv4);
6064                         ipv6 = IsProtocolSupported (System.Net.NetworkInformation.NetworkInterfaceComponent.IPv6);
6065 #else
6066                         SafeCloseSocket.InnerSafeCloseSocket socketV4 = 
6067                                                              UnsafeNclNativeMethods.OSSOCK.WSASocket(
6068                                                                     AddressFamily.InterNetwork, 
6069                                                                     SocketType.Dgram, 
6070                                                                     ProtocolType.IP, 
6071                                                                     IntPtr.Zero, 
6072                                                                     0, 
6073                                                                     (SocketConstructorFlags) 0);
6074                         if (socketV4.IsInvalid) {
6075                             errorCode = (SocketError) Marshal.GetLastWin32Error();
6076                             if (errorCode == SocketError.AddressFamilyNotSupported)
6077                                 ipv4 = false;
6078                         }
6079
6080                         socketV4.Close();
6081
6082                         SafeCloseSocket.InnerSafeCloseSocket socketV6 = 
6083                                                              UnsafeNclNativeMethods.OSSOCK.WSASocket(
6084                                                                     AddressFamily.InterNetworkV6, 
6085                                                                     SocketType.Dgram, 
6086                                                                     ProtocolType.IP, 
6087                                                                     IntPtr.Zero, 
6088                                                                     0, 
6089                                                                     (SocketConstructorFlags) 0);
6090                         if (socketV6.IsInvalid) {
6091                             errorCode = (SocketError) Marshal.GetLastWin32Error();
6092                             if (errorCode == SocketError.AddressFamilyNotSupported)
6093                                 ipv6 = false;
6094                         }
6095
6096                         socketV6.Close();
6097
6098                         // <
6099 #endif // MONO
6100
6101
6102 #if COMNET_DISABLEIPV6
6103                         //
6104                         // Turn off IPv6 support
6105                         //
6106                         ipv6 = false;
6107 #else
6108                         //
6109                         // Now read the switch as the final check: by checking the current value for IPv6
6110                         // support we may be able to avoid a painful configuration file read.
6111                         //
6112                         if (ipv6) {
6113                             s_OSSupportsIPv6 = true;
6114                             ipv6 = SettingsSectionInternal.Section.Ipv6Enabled;
6115                         }
6116 #endif
6117
6118                     //
6119                     // Update final state
6120                     //
6121                         s_SupportsIPv4 = ipv4;
6122                         s_SupportsIPv6 = ipv6;
6123
6124 #else //!FEATURE_PAL
6125
6126                         s_SupportsIPv4 = true;
6127                         s_SupportsIPv6 = false;
6128
6129 #endif //!FEATURE_PAL
6130
6131                         // Cache some settings locally.
6132
6133 #if !MONO
6134 #if !FEATURE_PAL // perfcounter
6135                         s_PerfCountersEnabled = NetworkingPerfCounters.Instance.Enabled;
6136 #endif
6137 #endif
6138
6139                         s_Initialized = true;
6140                     }
6141                 }
6142             }
6143         }
6144
6145 #if !MONO
6146         internal void InternalConnect(EndPoint remoteEP)
6147         {
6148             EndPoint endPointSnapshot = remoteEP;
6149             SocketAddress socketAddress = SnapshotAndSerialize(ref endPointSnapshot);
6150             DoConnect(endPointSnapshot, socketAddress);
6151         }
6152
6153         private void DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
6154         {
6155             if (s_LoggingEnabled) Logging.Enter(Logging.Sockets, this, "Connect", endPointSnapshot);
6156
6157             // This can throw ObjectDisposedException.
6158             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.WSAConnect(
6159                 m_Handle.DangerousGetHandle(),
6160                 socketAddress.m_Buffer,
6161                 socketAddress.m_Size,
6162                 IntPtr.Zero,
6163                 IntPtr.Zero,
6164                 IntPtr.Zero,
6165                 IntPtr.Zero);
6166
6167 #if TRAVE
6168             try
6169             {
6170                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::InternalConnect() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " DST:" + ValidationHelper.ToString(RemoteEndPoint) + " UnsafeNclNativeMethods.OSSOCK.WSAConnect returns errorCode:" + errorCode);
6171             }
6172             catch (ObjectDisposedException) { }
6173 #endif
6174
6175             //
6176             // if the native call fails we'll throw a SocketException
6177             //
6178             if (errorCode!=SocketError.Success) {
6179                 //
6180                 // update our internal state after this socket error and throw
6181                 //
6182                 SocketException socketException = new SocketException(endPointSnapshot);
6183                 UpdateStatusAfterSocketError(socketException);
6184                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "Connect", socketException);
6185                 throw socketException;
6186             }
6187
6188             if (m_RightEndPoint==null) {
6189                 //
6190                 // save a copy of the EndPoint so we can use it for Create()
6191                 //
6192                 m_RightEndPoint = endPointSnapshot;
6193             }
6194
6195             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoConnect() connection to:" + endPointSnapshot.ToString());
6196
6197             //
6198             // update state and performance counter
6199             //
6200             SetToConnected();
6201             if (s_LoggingEnabled) {
6202                 Logging.PrintInfo(Logging.Sockets, this, SR.GetString(SR.net_log_socket_connected, LocalEndPoint, RemoteEndPoint));
6203                 Logging.Exit(Logging.Sockets, this, "Connect", "");
6204             }
6205         }
6206
6207
6208         protected virtual void Dispose(bool disposing)
6209         {
6210             if (!disposing)
6211             {
6212                 return;
6213             }
6214
6215             try 
6216             {
6217                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Dispose() disposing:true CleanedUp:" + CleanedUp.ToString());
6218                 if (s_LoggingEnabled) Logging.Enter(Logging.Sockets, this, "Dispose", null);
6219             }
6220             catch (Exception exception)
6221             {
6222                 if (NclUtilities.IsFatal(exception)) throw;
6223             }
6224
6225             // make sure we're the first call to Dispose and no SetAsyncEventSelect is in progress
6226             int last;
6227             while ((last = Interlocked.CompareExchange(ref m_IntCleanedUp, 1, 0)) == 2)
6228             {
6229                 Thread.SpinWait(1);
6230             }
6231             if (last == 1)
6232             {
6233                 try {
6234                     if (s_LoggingEnabled) Logging.Exit(Logging.Sockets, this, "Dispose", null);
6235                 }
6236                 catch (Exception exception)
6237                 {
6238                     if (NclUtilities.IsFatal(exception)) throw;
6239                 }
6240                 return;
6241             }
6242
6243             SetToDisconnected();
6244
6245             AsyncEventBits pendingAsync = AsyncEventBits.FdNone;
6246             if (m_BlockEventBits != AsyncEventBits.FdNone)
6247             {
6248                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Dispose() Pending nonblocking operations!  m_BlockEventBits:" + m_BlockEventBits.ToString());
6249                 UnsetAsyncEventSelect();
6250                 if (m_BlockEventBits == AsyncEventBits.FdConnect)
6251                 {
6252                     LazyAsyncResult connectResult = m_AcceptQueueOrConnectResult as LazyAsyncResult;
6253                     if (connectResult != null && !connectResult.InternalPeekCompleted)
6254                         pendingAsync = AsyncEventBits.FdConnect;
6255                 }
6256                 else if (m_BlockEventBits == AsyncEventBits.FdAccept)
6257                 {
6258                     Queue acceptQueue = m_AcceptQueueOrConnectResult as Queue;
6259                     if (acceptQueue != null && acceptQueue.Count != 0)
6260                         pendingAsync = AsyncEventBits.FdAccept;
6261                 }
6262             }
6263             
6264 #if SOCKETTHREADPOOL
6265             if (m_BoundToThreadPool) SocketThreadPool.UnBindHandle(m_Handle);
6266 #endif
6267             // Close the handle in one of several ways depending on the timeout.
6268             // Ignore ObjectDisposedException just in case the handle somehow gets disposed elsewhere.
6269             try
6270             {
6271                 int timeout = m_CloseTimeout;
6272                 if (timeout == 0)
6273                 {
6274                     // Abortive.
6275                     GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Dispose() Calling m_Handle.Dispose()");
6276                     m_Handle.Dispose();
6277                 }
6278                 else
6279                 {
6280                     SocketError errorCode;
6281
6282                     // Go to blocking mode.  We know no WSAEventSelect is pending because of the lock and UnsetAsyncEventSelect() above.
6283                     if (!willBlock || !willBlockInternal)
6284                     {
6285                         int nonBlockCmd = 0;
6286                         errorCode = UnsafeNclNativeMethods.OSSOCK.ioctlsocket(
6287                             m_Handle,
6288                             IoctlSocketConstants.FIONBIO,
6289                             ref nonBlockCmd);
6290                         GlobalLog.Print("SafeCloseSocket::Dispose(handle:" + m_Handle.DangerousGetHandle().ToString("x") + ") ioctlsocket(FIONBIO):" + (errorCode == SocketError.SocketError ? (SocketError) Marshal.GetLastWin32Error() : errorCode).ToString());
6291                     }
6292
6293                     if (timeout < 0)
6294                     {
6295                         // Close with existing user-specified linger option.
6296                         GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Dispose() Calling m_Handle.CloseAsIs()");
6297                         m_Handle.CloseAsIs();
6298                     }
6299                     else
6300                     {
6301                         // Since our timeout is in ms and linger is in seconds, implement our own sortof linger here.
6302                         errorCode = UnsafeNclNativeMethods.OSSOCK.shutdown(m_Handle, (int) SocketShutdown.Send);
6303                         GlobalLog.Print("SafeCloseSocket::Dispose(handle:" + m_Handle.DangerousGetHandle().ToString("x") + ") shutdown():" + (errorCode == SocketError.SocketError ? (SocketError) Marshal.GetLastWin32Error() : errorCode).ToString());
6304
6305                         // This should give us a timeout in milliseconds.
6306                         errorCode = UnsafeNclNativeMethods.OSSOCK.setsockopt(
6307                             m_Handle,
6308                             SocketOptionLevel.Socket,
6309                             SocketOptionName.ReceiveTimeout,
6310                             ref timeout,
6311                             sizeof(int));
6312                         GlobalLog.Print("SafeCloseSocket::Dispose(handle:" + m_Handle.DangerousGetHandle().ToString("x") + ") setsockopt():" + (errorCode == SocketError.SocketError ? (SocketError) Marshal.GetLastWin32Error() : errorCode).ToString());
6313
6314                         if (errorCode != SocketError.Success)
6315                         {
6316                             m_Handle.Dispose();
6317                         }
6318                         else
6319                         {
6320                             unsafe
6321                             {
6322                                 errorCode = (SocketError) UnsafeNclNativeMethods.OSSOCK.recv(m_Handle.DangerousGetHandle(), null, 0, SocketFlags.None);
6323                             }
6324                             GlobalLog.Print("SafeCloseSocket::Dispose(handle:" + m_Handle.DangerousGetHandle().ToString("x") + ") recv():" + errorCode.ToString());
6325
6326                             if (errorCode != (SocketError) 0)
6327                             {
6328                                 // We got a timeout - abort.
6329                                 m_Handle.Dispose();
6330                             }
6331                             else
6332                             {
6333                                 // We got a FIN or data.  Use ioctlsocket to find out which.
6334                                 int dataAvailable = 0;
6335                                 errorCode = UnsafeNclNativeMethods.OSSOCK.ioctlsocket(
6336                                     m_Handle,
6337                                     IoctlSocketConstants.FIONREAD,
6338                                     ref dataAvailable);
6339                                 GlobalLog.Print("SafeCloseSocket::Dispose(handle:" + m_Handle.DangerousGetHandle().ToString("x") + ") ioctlsocket(FIONREAD):" + (errorCode == SocketError.SocketError ? (SocketError) Marshal.GetLastWin32Error() : errorCode).ToString());
6340
6341                                 if (errorCode != SocketError.Success || dataAvailable != 0)
6342                                 {
6343                                     // If we have data or don't know, safest thing is to reset.
6344                                     m_Handle.Dispose();
6345                                 }
6346                                 else
6347                                 {
6348                                     // We got a FIN.  It'd be nice to block for the remainder of the timeout for the handshake to finsh.
6349                                     // Since there's no real way to do that, close the socket with the user's preferences.  This lets
6350                                     // the user decide how best to handle this case via the linger options.
6351                                     m_Handle.CloseAsIs();
6352                                 }
6353                             }
6354                         }
6355                     }
6356                 }
6357             }
6358             catch (ObjectDisposedException)
6359             {
6360                 GlobalLog.Assert("SafeCloseSocket::Dispose(handle:" + m_Handle.DangerousGetHandle().ToString("x") + ")", "Closing the handle threw ObjectDisposedException.");
6361             }
6362
6363 #if !DEBUG
6364             // Clear out the Overlapped caches.
6365             if (m_Caches != null)
6366             {
6367                 OverlappedCache.InterlockedFree(ref m_Caches.SendOverlappedCache);
6368                 OverlappedCache.InterlockedFree(ref m_Caches.ReceiveOverlappedCache);
6369             }
6370 #endif
6371
6372             if (pendingAsync == AsyncEventBits.FdConnect)
6373             {
6374                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Dispose() QueueUserWorkItem for ConnectCallback");
6375                 // This will try to complete connectResult on a different thread
6376                 ThreadPool.UnsafeQueueUserWorkItem(new WaitCallback(((LazyAsyncResult)m_AcceptQueueOrConnectResult).InvokeCallback), new SocketException(SocketError.OperationAborted));
6377             }
6378             else if (pendingAsync == AsyncEventBits.FdAccept)
6379             {
6380                 // This will try to complete all acceptResults on a different thread
6381                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Dispose() QueueUserWorkItem for AcceptCallback");
6382                 ThreadPool.UnsafeQueueUserWorkItem(new WaitCallback(CompleteAcceptResults), null);
6383             }
6384
6385             if (m_AsyncEvent != null)
6386             {
6387                 m_AsyncEvent.Close();
6388             }
6389         }
6390 #endif // !MONO
6391
6392         public void Dispose() {
6393             Dispose(true);
6394             GC.SuppressFinalize(this);
6395         }
6396
6397         ~Socket() {
6398             Dispose(false);
6399         }
6400
6401 #if !MONO
6402         // this version does not throw.
6403         internal void InternalShutdown(SocketShutdown how) {
6404             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::InternalShutdown() how:" + how.ToString());
6405
6406             if (CleanedUp || m_Handle.IsInvalid) {
6407                 return;
6408             }
6409
6410             try
6411             {
6412                 UnsafeNclNativeMethods.OSSOCK.shutdown(m_Handle, (int)how);
6413             }
6414             catch (ObjectDisposedException) { }
6415         }
6416
6417         // Set the socket option to begin receiving packet information if it has not been
6418         // set for this socket previously
6419         internal void SetReceivingPacketInformation()
6420         {
6421             if (!m_ReceivingPacketInformation)
6422             {
6423                 // DualMode: When bound to IPv6Any you must enable both socket options.
6424                 // When bound to an IPv4 mapped IPv6 address you must enable the IPv4 socket option.
6425                 IPEndPoint ipEndPoint = m_RightEndPoint as IPEndPoint;
6426                 IPAddress boundAddress = (ipEndPoint != null ? ipEndPoint.Address : null);
6427                 Debug.Assert(boundAddress != null, "Not Bound");
6428                 if (this.addressFamily == AddressFamily.InterNetwork
6429                     || (boundAddress != null && IsDualMode 
6430                         && (boundAddress.IsIPv4MappedToIPv6 || boundAddress.Equals(IPAddress.IPv6Any))))
6431                 {
6432                     SetSocketOption(SocketOptionLevel.IP, SocketOptionName.PacketInformation, true);
6433                 }
6434
6435                 if (this.addressFamily == AddressFamily.InterNetworkV6
6436                     && (boundAddress == null || !boundAddress.IsIPv4MappedToIPv6))
6437                 {
6438                     SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.PacketInformation, true);
6439                 }
6440
6441                 m_ReceivingPacketInformation = true;
6442             }
6443         }
6444
6445         internal unsafe void SetSocketOption(SocketOptionLevel optionLevel, SocketOptionName optionName, int optionValue, bool silent) {
6446             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SetSocketOption() optionLevel:" + optionLevel + " optionName:" + optionName + " optionValue:" + optionValue + " silent:" + silent);
6447             if (silent && (CleanedUp || m_Handle.IsInvalid)) {
6448                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SetSocketOption() skipping the call");
6449                 return;
6450             }
6451             SocketError errorCode = SocketError.Success;
6452             try {
6453                 // This can throw ObjectDisposedException.
6454                 errorCode = UnsafeNclNativeMethods.OSSOCK.setsockopt(
6455                     m_Handle,
6456                     optionLevel,
6457                     optionName,
6458                     ref optionValue,
6459                     sizeof(int));
6460
6461                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SetSocketOption() UnsafeNclNativeMethods.OSSOCK.setsockopt returns errorCode:" + errorCode);
6462             }
6463             catch {
6464                 if (silent && m_Handle.IsInvalid) {
6465                     return;
6466                 }
6467                 throw;
6468             }
6469
6470             // Keep the internal state in [....] if the user manually resets this
6471             if (optionName == SocketOptionName.PacketInformation && optionValue == 0 && 
6472                 errorCode == SocketError.Success)
6473             {
6474                 m_ReceivingPacketInformation = false;
6475             }
6476
6477             if (silent) {
6478                 return;
6479             }
6480
6481             //
6482             // if the native call fails we'll throw a SocketException
6483             //
6484             if (errorCode==SocketError.SocketError) {
6485                 //
6486                 // update our internal state after this socket error and throw
6487                 //
6488                 SocketException socketException = new SocketException();
6489                 UpdateStatusAfterSocketError(socketException);
6490                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "SetSocketOption", socketException);
6491                 throw socketException;
6492             }
6493         }
6494
6495         private void setMulticastOption(SocketOptionName optionName, MulticastOption MR) {
6496             IPMulticastRequest ipmr = new IPMulticastRequest();
6497
6498             ipmr.MulticastAddress = unchecked((int)MR.Group.m_Address);
6499
6500
6501             if(MR.LocalAddress != null){
6502                 ipmr.InterfaceAddress = unchecked((int)MR.LocalAddress.m_Address);
6503             }
6504             else {  //this structure works w/ interfaces as well
6505                 int ifIndex =IPAddress.HostToNetworkOrder(MR.InterfaceIndex);
6506                 ipmr.InterfaceAddress   = unchecked((int)ifIndex);
6507             }
6508
6509 #if BIGENDIAN
6510             ipmr.MulticastAddress = (int) (((uint) ipmr.MulticastAddress << 24) |
6511                                            (((uint) ipmr.MulticastAddress & 0x0000FF00) << 8) |
6512                                            (((uint) ipmr.MulticastAddress >> 8) & 0x0000FF00) |
6513                                            ((uint) ipmr.MulticastAddress >> 24));
6514
6515             if(MR.LocalAddress != null){
6516                 ipmr.InterfaceAddress = (int) (((uint) ipmr.InterfaceAddress << 24) |
6517                                            (((uint) ipmr.InterfaceAddress & 0x0000FF00) << 8) |
6518                                            (((uint) ipmr.InterfaceAddress >> 8) & 0x0000FF00) |
6519                                            ((uint) ipmr.InterfaceAddress >> 24));
6520             }
6521 #endif  // BIGENDIAN
6522
6523             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::setMulticastOption(): optionName:" + optionName.ToString() + " MR:" + MR.ToString() + " ipmr:" + ipmr.ToString() + " IPMulticastRequest.Size:" + IPMulticastRequest.Size.ToString());
6524
6525             // This can throw ObjectDisposedException.
6526             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.setsockopt(
6527                 m_Handle,
6528                 SocketOptionLevel.IP,
6529                 optionName,
6530                 ref ipmr,
6531                 IPMulticastRequest.Size);
6532
6533             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::setMulticastOption() UnsafeNclNativeMethods.OSSOCK.setsockopt returns errorCode:" + errorCode);
6534
6535             //
6536             // if the native call fails we'll throw a SocketException
6537             //
6538             if (errorCode==SocketError.SocketError) {
6539                 //
6540                 // update our internal state after this socket error and throw
6541                 //
6542                 SocketException socketException = new SocketException();
6543                 UpdateStatusAfterSocketError(socketException);
6544                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "setMulticastOption", socketException);
6545                 throw socketException;
6546             }
6547         }
6548
6549
6550         /// <devdoc>
6551         ///     <para>
6552         ///         IPv6 setsockopt for JOIN / LEAVE multicast group
6553         ///     </para>
6554         /// </devdoc>
6555         private void setIPv6MulticastOption(SocketOptionName optionName, IPv6MulticastOption MR) {
6556             IPv6MulticastRequest ipmr = new IPv6MulticastRequest();
6557
6558             ipmr.MulticastAddress = MR.Group.GetAddressBytes();
6559             ipmr.InterfaceIndex   = unchecked((int)MR.InterfaceIndex);
6560
6561             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::setIPv6MulticastOption(): optionName:" + optionName.ToString() + " MR:" + MR.ToString() + " ipmr:" + ipmr.ToString() + " IPv6MulticastRequest.Size:" + IPv6MulticastRequest.Size.ToString());
6562
6563             // This can throw ObjectDisposedException.
6564             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.setsockopt(
6565                 m_Handle,
6566                 SocketOptionLevel.IPv6,
6567                 optionName,
6568                 ref ipmr,
6569                 IPv6MulticastRequest.Size);
6570
6571             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::setIPv6MulticastOption() UnsafeNclNativeMethods.OSSOCK.setsockopt returns errorCode:" + errorCode);
6572
6573             //
6574             // if the native call fails we'll throw a SocketException
6575             //
6576             if (errorCode==SocketError.SocketError) {
6577                 //
6578                 // update our internal state after this socket error and throw
6579                 //
6580                 SocketException socketException = new SocketException();
6581                 UpdateStatusAfterSocketError(socketException);
6582                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "setIPv6MulticastOption", socketException);
6583                 throw socketException;
6584             }
6585         }
6586
6587         private void setLingerOption(LingerOption lref) {
6588             Linger lngopt = new Linger();
6589             lngopt.OnOff = lref.Enabled ? (ushort)1 : (ushort)0;
6590             lngopt.Time = (ushort)lref.LingerTime;
6591
6592             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::setLingerOption(): lref:" + lref.ToString());
6593
6594             // This can throw ObjectDisposedException.
6595             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.setsockopt(
6596                 m_Handle,
6597                 SocketOptionLevel.Socket,
6598                 SocketOptionName.Linger,
6599                 ref lngopt,
6600                 4);
6601
6602             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::setLingerOption() UnsafeNclNativeMethods.OSSOCK.setsockopt returns errorCode:" + errorCode);
6603
6604             //
6605             // if the native call fails we'll throw a SocketException
6606             //
6607             if (errorCode==SocketError.SocketError) {
6608                 //
6609                 // update our internal state after this socket error and throw
6610                 //
6611                 SocketException socketException = new SocketException();
6612                 UpdateStatusAfterSocketError(socketException);
6613                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "setLingerOption", socketException);
6614                 throw socketException;
6615             }
6616         }
6617
6618         private LingerOption getLingerOpt() {
6619             Linger lngopt = new Linger();
6620             int optlen = 4;
6621
6622             // This can throw ObjectDisposedException.
6623             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.getsockopt(
6624                 m_Handle,
6625                 SocketOptionLevel.Socket,
6626                 SocketOptionName.Linger,
6627                 out lngopt,
6628                 ref optlen);
6629
6630             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::getLingerOpt() UnsafeNclNativeMethods.OSSOCK.getsockopt returns errorCode:" + errorCode);
6631
6632             //
6633             // if the native call fails we'll throw a SocketException
6634             //
6635             if (errorCode==SocketError.SocketError) {
6636                 //
6637                 // update our internal state after this socket error and throw
6638                 //
6639                 SocketException socketException = new SocketException();
6640                 UpdateStatusAfterSocketError(socketException);
6641                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "getLingerOpt", socketException);
6642                 throw socketException;
6643             }
6644
6645             LingerOption lingerOption = new LingerOption(lngopt.OnOff!=0, (int)lngopt.Time);
6646             return lingerOption;
6647         }
6648
6649         private MulticastOption getMulticastOpt(SocketOptionName optionName) {
6650             IPMulticastRequest ipmr = new IPMulticastRequest();
6651             int optlen = IPMulticastRequest.Size;
6652
6653             // This can throw ObjectDisposedException.
6654             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.getsockopt(
6655                 m_Handle,
6656                 SocketOptionLevel.IP,
6657                 optionName,
6658                 out ipmr,
6659                 ref optlen);
6660
6661             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::getMulticastOpt() UnsafeNclNativeMethods.OSSOCK.getsockopt returns errorCode:" + errorCode);
6662
6663             //
6664             // if the native call fails we'll throw a SocketException
6665             //
6666             if (errorCode==SocketError.SocketError) {
6667                 //
6668                 // update our internal state after this socket error and throw
6669                 //
6670                 SocketException socketException = new SocketException();
6671                 UpdateStatusAfterSocketError(socketException);
6672                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "getMulticastOpt", socketException);
6673                 throw socketException;
6674             }
6675
6676 #if BIGENDIAN
6677             ipmr.MulticastAddress = (int) (((uint) ipmr.MulticastAddress << 24) |
6678                                            (((uint) ipmr.MulticastAddress & 0x0000FF00) << 8) |
6679                                            (((uint) ipmr.MulticastAddress >> 8) & 0x0000FF00) |
6680                                            ((uint) ipmr.MulticastAddress >> 24));
6681             ipmr.InterfaceAddress = (int) (((uint) ipmr.InterfaceAddress << 24) |
6682                                            (((uint) ipmr.InterfaceAddress & 0x0000FF00) << 8) |
6683                                            (((uint) ipmr.InterfaceAddress >> 8) & 0x0000FF00) |
6684                                            ((uint) ipmr.InterfaceAddress >> 24));
6685 #endif  // BIGENDIAN
6686
6687             IPAddress multicastAddr = new IPAddress(ipmr.MulticastAddress);
6688             IPAddress multicastIntr = new IPAddress(ipmr.InterfaceAddress);
6689
6690             MulticastOption multicastOption = new MulticastOption(multicastAddr, multicastIntr);
6691
6692             return multicastOption;
6693         }
6694
6695
6696         /// <devdoc>
6697         ///     <para>
6698         ///         IPv6 getsockopt for JOIN / LEAVE multicast group
6699         ///     </para>
6700         /// </devdoc>
6701         private IPv6MulticastOption getIPv6MulticastOpt(SocketOptionName optionName) {
6702             IPv6MulticastRequest ipmr = new IPv6MulticastRequest();
6703
6704             int optlen = IPv6MulticastRequest.Size;
6705
6706             // This can throw ObjectDisposedException.
6707             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.getsockopt(
6708                 m_Handle,
6709                 SocketOptionLevel.IP,
6710                 optionName,
6711                 out ipmr,
6712                 ref optlen);
6713
6714             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::getIPv6MulticastOpt() UnsafeNclNativeMethods.OSSOCK.getsockopt returns errorCode:" + errorCode);
6715
6716             //
6717             // if the native call fails we'll throw a SocketException
6718             //
6719             if (errorCode==SocketError.SocketError) {
6720                 //
6721                 // update our internal state after this socket error and throw
6722                 //
6723                 SocketException socketException = new SocketException();
6724                 UpdateStatusAfterSocketError(socketException);
6725                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "getIPv6MulticastOpt", socketException);
6726                 throw socketException;
6727             }
6728
6729             IPv6MulticastOption multicastOption = new IPv6MulticastOption(new IPAddress(ipmr.MulticastAddress),ipmr.InterfaceIndex);
6730
6731             return multicastOption;
6732         }
6733
6734         //
6735         // this version will ignore failures but it returns the win32
6736         // error code, and it will update internal state on success.
6737         //
6738         private SocketError InternalSetBlocking(bool desired, out bool current) {
6739             GlobalLog.Enter("Socket#" + ValidationHelper.HashString(this) + "::InternalSetBlocking", "desired:" + desired.ToString() + " willBlock:" + willBlock.ToString() + " willBlockInternal:" + willBlockInternal.ToString());
6740
6741             if (CleanedUp) {
6742                 GlobalLog.Leave("Socket#" + ValidationHelper.HashString(this) + "::InternalSetBlocking", "ObjectDisposed");
6743                 current = willBlock;
6744                 return SocketError.Success;
6745             }
6746
6747             int intBlocking = desired ? 0 : -1;
6748
6749             // 
6750             SocketError errorCode;
6751             try
6752             {
6753                 errorCode = UnsafeNclNativeMethods.OSSOCK.ioctlsocket(
6754                     m_Handle,
6755                     IoctlSocketConstants.FIONBIO,
6756                     ref intBlocking);
6757
6758                 if (errorCode == SocketError.SocketError)
6759                 {
6760                     errorCode = (SocketError) Marshal.GetLastWin32Error();
6761                 }
6762             }
6763             catch (ObjectDisposedException)
6764             {
6765                 errorCode = SocketError.NotSocket;
6766             }
6767
6768             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::InternalSetBlocking() UnsafeNclNativeMethods.OSSOCK.ioctlsocket returns errorCode:" + errorCode);
6769
6770             //
6771             // we will update only internal state but only on successfull win32 call
6772             // so if the native call fails, the state will remain the same.
6773             //
6774             if (errorCode==SocketError.Success) {
6775                 //
6776                 // success, update internal state
6777                 //
6778                 willBlockInternal = intBlocking==0;
6779             }
6780
6781             GlobalLog.Leave("Socket#" + ValidationHelper.HashString(this) + "::InternalSetBlocking", "errorCode:" + errorCode.ToString() + " willBlock:" + willBlock.ToString() + " willBlockInternal:" + willBlockInternal.ToString());
6782             current = willBlockInternal;
6783             return errorCode;
6784         }
6785         //
6786         // this version will ignore all failures.
6787         //
6788         internal void InternalSetBlocking(bool desired) {
6789             bool current;
6790             InternalSetBlocking(desired, out current);
6791         }
6792
6793         private static IntPtr[] SocketListToFileDescriptorSet(IList socketList) {
6794             if (socketList==null || socketList.Count==0) {
6795                 return null;
6796             }
6797             IntPtr[] fileDescriptorSet = new IntPtr[socketList.Count + 1];
6798             fileDescriptorSet[0] = (IntPtr)socketList.Count;
6799             for (int current=0; current<socketList.Count; current++) {
6800                 if (!(socketList[current] is Socket)) {
6801                     throw new ArgumentException(SR.GetString(SR.net_sockets_select, socketList[current].GetType().FullName, typeof(System.Net.Sockets.Socket).FullName), "socketList");
6802                 }
6803                 fileDescriptorSet[current + 1] = ((Socket)socketList[current]).m_Handle.DangerousGetHandle();
6804             }
6805             return fileDescriptorSet;
6806         }
6807
6808         //
6809         // Transform the list socketList such that the only sockets left are those
6810         // with a file descriptor contained in the array "fileDescriptorArray"
6811         //
6812         private static void SelectFileDescriptor(IList socketList, IntPtr[] fileDescriptorSet) {
6813             // Walk the list in order
6814             // Note that the counter is not necessarily incremented at each step;
6815             // when the socket is removed, advancing occurs automatically as the
6816             // other elements are shifted down.
6817             if (socketList==null || socketList.Count==0) {
6818                 return;
6819             }
6820             if ((int)fileDescriptorSet[0]==0) {
6821                 // no socket present, will never find any socket, remove them all
6822                 socketList.Clear();
6823                 return;
6824             }
6825             lock (socketList) {
6826                 for (int currentSocket=0; currentSocket<socketList.Count; currentSocket++) {
6827                     Socket socket = socketList[currentSocket] as Socket;
6828                     // Look for the file descriptor in the array
6829                     int currentFileDescriptor;
6830                     for (currentFileDescriptor=0; currentFileDescriptor<(int)fileDescriptorSet[0]; currentFileDescriptor++) {
6831                         if (fileDescriptorSet[currentFileDescriptor + 1]==socket.m_Handle.DangerousGetHandle()) {
6832                             break;
6833                         }
6834                     }
6835                     if (currentFileDescriptor==(int)fileDescriptorSet[0]) {
6836                         // descriptor not found: remove the current socket and start again
6837                         socketList.RemoveAt(currentSocket--);
6838                     }
6839                 }
6840             }
6841         }
6842
6843
6844         private static void MicrosecondsToTimeValue(long microSeconds, ref TimeValue socketTime) {
6845             socketTime.Seconds   = (int) (microSeconds / microcnv);
6846             socketTime.Microseconds  = (int) (microSeconds % microcnv);
6847         }
6848         //Implements ConnectEx - this provides completion port IO and support for
6849         //disconnect and reconnects
6850
6851         // Since this is private, the unsafe mode is specified with a flag instead of an overload.
6852         private IAsyncResult BeginConnectEx(EndPoint remoteEP, bool flowContext, AsyncCallback callback, object state)
6853         {
6854             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "BeginConnectEx", "");
6855
6856             // This will check the permissions for connect.
6857             EndPoint endPointSnapshot = remoteEP;
6858             SocketAddress socketAddress = flowContext ? CheckCacheRemote(ref endPointSnapshot, true) : SnapshotAndSerialize(ref endPointSnapshot);
6859
6860             //socket must be bound first
6861             //the calling method BeginConnect will ensure that this method is only
6862             //called if m_RightEndPoint is not null, of that the endpoint is an ipendpoint
6863             if (m_RightEndPoint==null){
6864                 GlobalLog.Assert(endPointSnapshot.GetType() == typeof(IPEndPoint), "Socket#{0}::BeginConnectEx()|Socket not bound and endpoint not IPEndPoint.", ValidationHelper.HashString(this));
6865                 if (endPointSnapshot.AddressFamily == AddressFamily.InterNetwork)
6866                     InternalBind(new IPEndPoint(IPAddress.Any, 0));
6867                 else
6868                     InternalBind(new IPEndPoint(IPAddress.IPv6Any, 0));
6869             }
6870
6871             //
6872             // Allocate the async result and the event we'll pass to the
6873             // thread pool.
6874             //
6875             ConnectOverlappedAsyncResult asyncResult = new ConnectOverlappedAsyncResult(this, endPointSnapshot, state, callback);
6876
6877             // If context flowing is enabled, set it up here.  No need to lock since the context isn't used until the callback.
6878             if (flowContext)
6879             {
6880                 asyncResult.StartPostingAsyncOp(false);
6881             }
6882
6883             // This will pin socketAddress buffer
6884             asyncResult.SetUnmanagedStructures(socketAddress.m_Buffer);
6885
6886             //we should fix this in Whidbey.
6887             EndPoint oldEndPoint = m_RightEndPoint;
6888             if (m_RightEndPoint == null) {
6889                   m_RightEndPoint = endPointSnapshot;
6890             }
6891
6892             SocketError errorCode=SocketError.Success;
6893
6894             int ignoreBytesSent;
6895
6896             try
6897             {
6898                 if (!ConnectEx(
6899                     m_Handle,
6900                     Marshal.UnsafeAddrOfPinnedArrayElement(socketAddress.m_Buffer, 0),
6901                     socketAddress.m_Size,
6902                     IntPtr.Zero,
6903                     0,
6904                     out ignoreBytesSent,
6905                     asyncResult.OverlappedHandle))
6906                 {
6907                     errorCode = (SocketError)Marshal.GetLastWin32Error();
6908                 }
6909             }
6910             catch
6911             {
6912                 //
6913                 // Bug 152350: If ConnectEx throws we need to unpin the socketAddress buffer.
6914                 // m_RightEndPoint will always equal oldEndPoint anyways...
6915                 //
6916                 asyncResult.InternalCleanup();
6917                 m_RightEndPoint = oldEndPoint;
6918                 throw;
6919             }
6920
6921
6922             if (errorCode == SocketError.Success) {
6923                 SetToConnected();
6924             }
6925
6926             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginConnectEx() UnsafeNclNativeMethods.OSSOCK.connect returns:" + errorCode.ToString());
6927
6928             errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode);
6929
6930             //
6931             // if the asynchronous native call fails synchronously
6932             // we'll throw a SocketException
6933             //
6934             if (errorCode != SocketError.Success) {
6935                 //
6936                 // update our internal state after this socket error and throw
6937                 //
6938                 m_RightEndPoint = oldEndPoint;
6939                 SocketException socketException = new SocketException(errorCode);
6940                 UpdateStatusAfterSocketError(socketException);
6941                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "BeginConnectEx", socketException);
6942                 throw socketException;
6943             }
6944
6945             // We didn't throw, so indicate that we're returning this result to the user.  This may call the callback.
6946             // This is a nop if the context isn't being flowed.
6947             asyncResult.FinishPostingAsyncOp(ref Caches.ConnectClosureCache);
6948
6949             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginConnectEx() to:" + endPointSnapshot.ToString() + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
6950             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "BeginConnectEx", asyncResult);
6951             return asyncResult;
6952         }
6953
6954
6955         internal void MultipleSend(BufferOffsetSize[] buffers, SocketFlags socketFlags) {
6956             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "MultipleSend", "");
6957             if (CleanedUp) {
6958                 throw new ObjectDisposedException(this.GetType().FullName);
6959             }
6960             //
6961             // parameter validation
6962             //
6963             GlobalLog.Assert(buffers != null, "Socket#{0}::MultipleSend()|buffers == null", ValidationHelper.HashString(this));
6964             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::MultipleSend() buffers.Length:" + buffers.Length.ToString());
6965
6966             WSABuffer[] WSABuffers = new WSABuffer[buffers.Length];
6967             GCHandle[] objectsToPin = null;
6968             int bytesTransferred;
6969             SocketError errorCode;
6970
6971             try {
6972                 objectsToPin = new GCHandle[buffers.Length];
6973                 for (int i = 0; i < buffers.Length; ++i)
6974                 {
6975                     objectsToPin[i] = GCHandle.Alloc(buffers[i].Buffer, GCHandleType.Pinned);
6976                     WSABuffers[i].Length = buffers[i].Size;
6977                     WSABuffers[i].Pointer = Marshal.UnsafeAddrOfPinnedArrayElement(buffers[i].Buffer, buffers[i].Offset);
6978                 }
6979
6980                 // This can throw ObjectDisposedException.
6981                 errorCode = UnsafeNclNativeMethods.OSSOCK.WSASend_Blocking(
6982                     m_Handle.DangerousGetHandle(),
6983                     WSABuffers,
6984                     WSABuffers.Length,
6985                     out bytesTransferred,
6986                     socketFlags,
6987                     SafeNativeOverlapped.Zero,
6988                     IntPtr.Zero);
6989
6990                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::MultipleSend() UnsafeNclNativeMethods.OSSOCK.WSASend returns:" + errorCode.ToString() + " size:" + buffers.Length.ToString());
6991
6992             }
6993             finally {
6994                 if (objectsToPin != null)
6995                     for (int i = 0; i < objectsToPin.Length; ++i)
6996                         if (objectsToPin[i].IsAllocated)
6997                             objectsToPin[i].Free();
6998             }
6999
7000             if (errorCode!=SocketError.Success) {
7001                 SocketException socketException = new SocketException();
7002                 UpdateStatusAfterSocketError(socketException);
7003                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "MultipleSend", socketException);
7004                 throw socketException;
7005             }
7006
7007             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "MultipleSend", "");
7008         }
7009
7010
7011         private static void DnsCallback(IAsyncResult result){
7012             if (result.CompletedSynchronously)
7013                 return;
7014
7015             bool invokeCallback = false;
7016
7017             MultipleAddressConnectAsyncResult context = (MultipleAddressConnectAsyncResult) result.AsyncState;
7018             try
7019             {
7020                 invokeCallback = DoDnsCallback(result, context);
7021             }
7022             catch (Exception exception)
7023             {
7024                 context.InvokeCallback(exception);
7025             }
7026
7027             // Invoke the callback outside of the try block so we don't catch user Exceptions
7028             if (invokeCallback)
7029             {
7030                 context.InvokeCallback();
7031             }
7032         }
7033
7034         private static bool DoDnsCallback(IAsyncResult result, MultipleAddressConnectAsyncResult context)
7035         {
7036             IPAddress[] addresses = Dns.EndGetHostAddresses(result);
7037             context.addresses = addresses;
7038             return DoMultipleAddressConnectCallback(PostOneBeginConnect(context), context);
7039         }
7040
7041         private class MultipleAddressConnectAsyncResult : ContextAwareResult
7042         {
7043             internal MultipleAddressConnectAsyncResult(IPAddress[] addresses, int port, Socket socket, object myState, AsyncCallback myCallBack) :
7044                 base(socket, myState, myCallBack)
7045             {
7046                 this.addresses = addresses;
7047                 this.port = port;
7048                 this.socket = socket;
7049             }
7050
7051             internal Socket socket;   // Keep this member just to avoid all the casting.
7052             internal IPAddress[] addresses;
7053             internal int index;
7054             internal int port;
7055             internal Exception lastException;
7056
7057             internal EndPoint RemoteEndPoint {
7058                 get {
7059                     if (addresses != null && index > 0 && index < addresses.Length) {
7060                         return new IPEndPoint(addresses[index], port);
7061                     } else  {
7062                         return null;
7063                     }
7064                 }
7065             }
7066         }
7067
7068         private static object PostOneBeginConnect(MultipleAddressConnectAsyncResult context)
7069         {
7070             IPAddress currentAddressSnapshot = context.addresses[context.index];
7071
7072             if (!context.socket.CanTryAddressFamily(currentAddressSnapshot.AddressFamily))
7073             {
7074                 return context.lastException != null ? context.lastException : new ArgumentException(SR.GetString(SR.net_invalidAddressList), "context");
7075             }
7076
7077             try
7078             {
7079                 EndPoint endPoint = new IPEndPoint(currentAddressSnapshot, context.port);
7080                 // MSRC 11081 - Do the necessary security demand
7081                 context.socket.CheckCacheRemote(ref endPoint, true);
7082
7083                 IAsyncResult connectResult = context.socket.UnsafeBeginConnect(endPoint, 
7084                     new AsyncCallback(MultipleAddressConnectCallback), context);
7085
7086                 if (connectResult.CompletedSynchronously)
7087                 {
7088                     return connectResult;
7089                 }
7090             }
7091             catch (Exception exception)
7092             {
7093                 if (exception is OutOfMemoryException || exception is StackOverflowException || exception is ThreadAbortException)
7094                     throw;
7095
7096                 return exception;
7097             }
7098
7099             return null;
7100         }
7101
7102         private static void MultipleAddressConnectCallback(IAsyncResult result)
7103         {
7104             if (result.CompletedSynchronously)
7105                 return;
7106
7107             bool invokeCallback = false;
7108
7109             MultipleAddressConnectAsyncResult context = (MultipleAddressConnectAsyncResult) result.AsyncState;
7110             try
7111             {
7112                 invokeCallback = DoMultipleAddressConnectCallback(result, context);
7113             }
7114             catch (Exception exception)
7115             {
7116                 context.InvokeCallback(exception);
7117             }
7118
7119             // Invoke the callback outside of the try block so we don't catch user Exceptions
7120             if (invokeCallback)
7121             {
7122                 context.InvokeCallback();
7123             }
7124         }
7125
7126         // This is like a regular async callback worker, except the result can be an exception.  This is a useful pattern when
7127         // processing should continue whether or not an async step failed.
7128         private static bool DoMultipleAddressConnectCallback(object result, MultipleAddressConnectAsyncResult context)
7129         {
7130             while (result != null)
7131             {
7132                 Exception ex = result as Exception;
7133                 if (ex == null)
7134                 {
7135                     try
7136                     {
7137                         context.socket.EndConnect((IAsyncResult) result);
7138                     }
7139                     catch (Exception exception)
7140                     {
7141                         ex = exception;
7142                     }
7143                 }
7144
7145                 if (ex == null)
7146                 {
7147                     // Don't invoke the callback from here, because we're probably inside
7148                     // a catch-all block that would eat exceptions from the callback.
7149                     // Instead tell our caller to invoke the callback outside of its catchall.
7150                     return true;
7151                 }
7152                 else
7153                 {
7154                     if (++context.index >= context.addresses.Length)
7155                         throw ex;
7156
7157                     context.lastException = ex;
7158                     result = PostOneBeginConnect(context);
7159                 }
7160             }
7161
7162             // Don't invoke the callback at all, because we've posted another async connection attempt
7163             return false;
7164         }
7165
7166
7167         internal IAsyncResult BeginMultipleSend(BufferOffsetSize[] buffers, SocketFlags socketFlags, AsyncCallback callback, object state) {
7168             // Set up the async result and start the flow.
7169             OverlappedAsyncResult asyncResult = new OverlappedAsyncResult(this, state, callback);
7170             asyncResult.StartPostingAsyncOp(false);
7171
7172             // Start the send.
7173             DoBeginMultipleSend(buffers, socketFlags, asyncResult);
7174
7175             // Finish it up (capture, complete).
7176             asyncResult.FinishPostingAsyncOp(ref Caches.SendClosureCache);
7177             return asyncResult;
7178         }
7179
7180         internal IAsyncResult UnsafeBeginMultipleSend(BufferOffsetSize[] buffers, SocketFlags socketFlags, AsyncCallback callback, object state)
7181         {
7182             // Unsafe - don't flow.
7183             OverlappedAsyncResult asyncResult = new OverlappedAsyncResult(this, state, callback);
7184             DoBeginMultipleSend(buffers, socketFlags, asyncResult);
7185             return asyncResult;
7186         }
7187
7188         private void DoBeginMultipleSend(BufferOffsetSize[] buffers, SocketFlags socketFlags, OverlappedAsyncResult asyncResult)
7189         {
7190             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "BeginMultipleSend", "");
7191             if (CleanedUp) {
7192                 throw new ObjectDisposedException(this.GetType().FullName);
7193             }
7194             //
7195             // parameter validation
7196             //
7197             GlobalLog.Assert(buffers != null, "Socket#{0}::DoBeginMultipleSend()|buffers == null", ValidationHelper.HashString(this));
7198             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginMultipleSend() buffers.Length:" + buffers.Length.ToString());
7199
7200             // Guarantee to call CheckAsyncCallOverlappedResult if we call SetUnamangedStructures with a cache in order to
7201             // avoid a Socket leak in case of error.
7202             SocketError errorCode = SocketError.SocketError;
7203             try
7204             {
7205                 // Set up asyncResult for overlapped WSASend.
7206                 // This call will use completion ports on WinNT and Overlapped IO on Win9x.
7207                 asyncResult.SetUnmanagedStructures(buffers, ref Caches.SendOverlappedCache);
7208
7209                 // This can throw ObjectDisposedException.
7210                 int bytesTransferred;
7211                 errorCode = UnsafeNclNativeMethods.OSSOCK.WSASend(
7212                     m_Handle,
7213                     asyncResult.m_WSABuffers,
7214                     asyncResult.m_WSABuffers.Length,
7215                     out bytesTransferred,
7216                     socketFlags,
7217                     asyncResult.OverlappedHandle,
7218                     IntPtr.Zero);
7219
7220                 if (errorCode!=SocketError.Success) {
7221                     errorCode = (SocketError)Marshal.GetLastWin32Error();
7222                 }
7223                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginMultipleSend() UnsafeNclNativeMethods.OSSOCK.WSASend returns:" + errorCode.ToString() + " size:" + buffers.Length.ToString() + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
7224             }
7225             finally
7226             {
7227                 errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode);
7228             }
7229
7230             //
7231             // if the asynchronous native call fails synchronously
7232             // we'll throw a SocketException
7233             //
7234             if (errorCode!=SocketError.Success) {
7235                 //
7236                 // update our internal state after this socket error and throw
7237                 //
7238                 asyncResult.ExtractCache(ref Caches.SendOverlappedCache);
7239                 SocketException socketException = new SocketException(errorCode);
7240                 UpdateStatusAfterSocketError(socketException);
7241                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "BeginMultipleSend", socketException);
7242                 throw socketException;
7243            }
7244             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "BeginMultipleSend", asyncResult);
7245         }
7246
7247         internal int EndMultipleSend(IAsyncResult asyncResult) {
7248             if(s_LoggingEnabled)Logging.Enter(Logging.Sockets, this, "EndMultipleSend", asyncResult);
7249             //
7250             // parameter validation
7251             //
7252             GlobalLog.Assert(asyncResult != null, "Socket#{0}::EndMultipleSend()|asyncResult == null", ValidationHelper.HashString(this));
7253
7254             OverlappedAsyncResult castedAsyncResult = asyncResult as OverlappedAsyncResult;
7255
7256             GlobalLog.Assert(castedAsyncResult != null, "Socket#{0}::EndMultipleSend()|castedAsyncResult == null", ValidationHelper.HashString(this));
7257             GlobalLog.Assert(castedAsyncResult.AsyncObject == this, "Socket#{0}::EndMultipleSend()|castedAsyncResult.AsyncObject != this", ValidationHelper.HashString(this));
7258             GlobalLog.Assert(!castedAsyncResult.EndCalled, "Socket#{0}::EndMultipleSend()|castedAsyncResult.EndCalled", ValidationHelper.HashString(this));
7259
7260             int bytesTransferred = (int)castedAsyncResult.InternalWaitForCompletion();
7261             castedAsyncResult.EndCalled = true;
7262             castedAsyncResult.ExtractCache(ref Caches.SendOverlappedCache);
7263
7264 #if !FEATURE_PAL // perfcounter
7265             if (s_PerfCountersEnabled)
7266             {
7267                 if (bytesTransferred>0) {
7268                     NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketBytesSent, bytesTransferred);
7269                     if (Transport==TransportType.Udp) {
7270                         NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketDatagramsSent);
7271                     }
7272                 }
7273             }
7274 #endif //!FEATURE_PAL
7275
7276             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::EndMultipleSend() bytesTransferred:" + bytesTransferred.ToString());
7277
7278             //
7279             // if the asynchronous native call failed asynchronously
7280             // we'll throw a SocketException
7281             //
7282             if ((SocketError)castedAsyncResult.ErrorCode!=SocketError.Success) {
7283                 //
7284                 // update our internal state after this socket error and throw
7285                 //
7286                 SocketException socketException = new SocketException(castedAsyncResult.ErrorCode);
7287                 if(s_LoggingEnabled)Logging.Exception(Logging.Sockets, this, "EndMultipleSend", socketException);
7288                 throw socketException;
7289             }
7290             if(s_LoggingEnabled)Logging.Exit(Logging.Sockets, this, "EndMultipleSend", bytesTransferred);
7291             return bytesTransferred;
7292         }
7293
7294          //
7295         // CreateAcceptSocket - pulls unmanaged results and assembles them
7296         //   into a new Socket object
7297         //
7298         private Socket CreateAcceptSocket(SafeCloseSocket fd, EndPoint remoteEP, bool needCancelSelect) {
7299             //
7300             // Internal state of the socket is inherited from listener
7301             //
7302             Socket socket           = new Socket(fd);
7303             return UpdateAcceptSocket(socket,remoteEP, needCancelSelect);
7304          }
7305
7306         internal Socket UpdateAcceptSocket(Socket socket, EndPoint remoteEP, bool needCancelSelect) {
7307             //
7308             // Internal state of the socket is inherited from listener
7309             //
7310             socket.addressFamily    = addressFamily;
7311             socket.socketType       = socketType;
7312             socket.protocolType     = protocolType;
7313             socket.m_RightEndPoint  = m_RightEndPoint;
7314             socket.m_RemoteEndPoint = remoteEP;
7315             //
7316             // the socket is connected
7317             //
7318             socket.SetToConnected();
7319             //
7320             // if the socket is returned by an Endb), the socket might have
7321             // inherited the WSAEventSelect() call from the accepting socket.
7322             // we need to cancel this otherwise the socket will be in non-blocking
7323             // mode and we cannot force blocking mode using the ioctlsocket() in
7324             // Socket.set_Blocking(), since it fails returing 10022 as documented in MSDN.
7325             // (note that the m_AsyncEvent event will not be created in this case.
7326             //
7327
7328             socket.willBlock = willBlock;
7329             if (needCancelSelect) {
7330                 socket.UnsetAsyncEventSelect();
7331             }
7332             else {
7333                 // We need to make sure the Socket is in the right blocking state
7334                 // even if we don't have to call UnsetAsyncEventSelect
7335                 socket.InternalSetBlocking(willBlock);
7336             }
7337
7338             return socket;
7339         }
7340
7341
7342
7343         //
7344         // SetToConnected - updates the status of the socket to connected
7345         //
7346         internal void SetToConnected() {
7347             if (m_IsConnected) {
7348                 //
7349                 // socket was already connected
7350                 //
7351                 return;
7352             }
7353             //
7354             // update the status: this socket was indeed connected at
7355             // some point in time update the perf counter as well.
7356             //
7357             m_IsConnected = true;
7358             m_IsDisconnected = false;
7359             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SetToConnected() now connected SRC:" + ValidationHelper.ToString(LocalEndPoint) + " DST:" + ValidationHelper.ToString(RemoteEndPoint));
7360 #if !FEATURE_PAL // perfcounter
7361             if (s_PerfCountersEnabled)
7362             {
7363                 NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketConnectionsEstablished);
7364             }
7365 #endif //!FEATURE_PAL
7366         }
7367
7368         //
7369         // SetToDisconnected - updates the status of the socket to disconnected
7370         //
7371         internal void SetToDisconnected() {
7372             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SetToDisconnected()");
7373             if (!m_IsConnected) {
7374                 //
7375                 // socket was already disconnected
7376                 //
7377                 return;
7378             }
7379             //
7380             // update the status: this socket was indeed disconnected at
7381             // some point in time, clear any async select bits.
7382             //
7383             m_IsConnected = false;
7384             m_IsDisconnected = true;
7385
7386             if (!CleanedUp) {
7387                 //
7388                 // if socket is still alive cancel WSAEventSelect()
7389                 //
7390                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SetToDisconnected()");
7391
7392                 UnsetAsyncEventSelect();
7393             }
7394         }
7395
7396         //
7397         // UpdateStatusAfterSocketError(socketException) - updates the status of a connected socket
7398         // on which a failure occured. it'll go to winsock and check if the connection
7399         // is still open and if it needs to update our internal state.
7400         //
7401         internal void UpdateStatusAfterSocketError(SocketException socketException){
7402             UpdateStatusAfterSocketError((SocketError) socketException.NativeErrorCode);
7403         }
7404
7405         internal void UpdateStatusAfterSocketError(SocketError errorCode)
7406         {
7407             //
7408             // if we already know the socket is disconnected
7409             // we don't need to do anything else.
7410             //
7411             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::UpdateStatusAfterSocketError(socketException)");
7412             if (s_LoggingEnabled) Logging.PrintError(Logging.Sockets, this, "UpdateStatusAfterSocketError", errorCode.ToString());
7413
7414             if (m_IsConnected && (m_Handle.IsInvalid || (errorCode != SocketError.WouldBlock &&
7415                     errorCode != SocketError.IOPending && errorCode != SocketError.NoBufferSpaceAvailable && 
7416                     errorCode != SocketError.TimedOut)))
7417             {
7418                 //
7419                 //
7420                 // the socket is no longer a valid socket
7421                 //
7422                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::UpdateStatusAfterSocketError(socketException) Invalidating socket.");
7423                 SetToDisconnected();
7424             }
7425         }
7426
7427
7428         //
7429         // Does internal initalization before async winsock
7430         // call to BeginConnect() or BeginAccept().
7431         //
7432         private void UnsetAsyncEventSelect()
7433         {
7434             GlobalLog.Enter("Socket#" + ValidationHelper.HashString(this) + "::UnsetAsyncEventSelect", "m_BlockEventBits:" + m_BlockEventBits.ToString() + " willBlockInternal:" + willBlockInternal.ToString());
7435
7436             RegisteredWaitHandle registeredWait = m_RegisteredWait;
7437             if (registeredWait != null)
7438             {
7439                 m_RegisteredWait = null;
7440                 registeredWait.Unregister(null);
7441             }
7442
7443             SocketError errorCode = SocketError.NotSocket;
7444             try {
7445                 errorCode = UnsafeNclNativeMethods.OSSOCK.WSAEventSelect(m_Handle, IntPtr.Zero, AsyncEventBits.FdNone);
7446             }
7447             catch (Exception e)
7448             {
7449                 if (NclUtilities.IsFatal(e))
7450                     throw;
7451                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::UnsetAsyncEventSelect() !!! (ignoring) Exception: " + e.ToString());
7452                 GlobalLog.Assert(CleanedUp, "Socket#{0}::UnsetAsyncEventSelect|Got exception and CleanedUp not set.", ValidationHelper.HashString(this));
7453             }
7454
7455             //
7456             // May be re-used in future, reset if the event got signalled after registeredWait.Unregister call
7457             //
7458             if (m_AsyncEvent != null)
7459             {
7460                 try
7461                 {
7462                     m_AsyncEvent.Reset();
7463                 }
7464                 catch (ObjectDisposedException) { }
7465             }
7466
7467             if (errorCode == SocketError.SocketError)
7468             {
7469                 //
7470                 // update our internal state after this socket error
7471                 // we won't throw since this is an internal method
7472                 //
7473                 UpdateStatusAfterSocketError(errorCode);
7474             }
7475
7476             // The call to WSAEventSelect will always put us into non-blocking mode.  
7477             // Revert back to what the user has requested.
7478             InternalSetBlocking(willBlock);
7479
7480             GlobalLog.Leave("Socket#" + ValidationHelper.HashString(this) + "::UnsetAsyncEventSelect", "m_BlockEventBits:" + m_BlockEventBits.ToString() + " willBlockInternal:" + willBlockInternal.ToString());
7481         }
7482
7483         private bool SetAsyncEventSelect(AsyncEventBits blockEventBits)
7484         {
7485             GlobalLog.Enter("Socket#" + ValidationHelper.HashString(this) + "::SetAsyncEventSelect", "blockEventBits:" + blockEventBits.ToString() + " m_BlockEventBits:" + m_BlockEventBits.ToString() + " willBlockInternal:" + willBlockInternal.ToString());
7486             GlobalLog.Assert(blockEventBits != AsyncEventBits.FdNone, "Socket#{0}::SetAsyncEventSelect|Use UnsetAsyncEventSelect for FdNone.", ValidationHelper.HashString(this));
7487             GlobalLog.Assert(m_BlockEventBits == AsyncEventBits.FdNone || m_BlockEventBits == blockEventBits, "Socket#{0}::SetAsyncEventSelect|Can't change from one active wait to another.", ValidationHelper.HashString(this));
7488             GlobalLog.Assert(m_RegisteredWait == null, "Socket#{0}::SetAsyncEventSelect|Already actively waiting on an op.", ValidationHelper.HashString(this));
7489
7490             // This check is bogus, too late diggin into a historical reason for it.
7491             // Make sure the upper level will fail with ObjectDisposedException
7492             if (m_RegisteredWait != null)
7493                 return false;
7494
7495             //
7496             // This will put us into non-blocking mode.  Create the event if it isn't, and register a wait.
7497             //
7498             if (m_AsyncEvent == null)
7499             {
7500                 Interlocked.CompareExchange<ManualResetEvent>(ref m_AsyncEvent, new ManualResetEvent(false), null);
7501                 if (s_RegisteredWaitCallback == null)
7502                     s_RegisteredWaitCallback = new WaitOrTimerCallback(RegisteredWaitCallback);
7503             }
7504
7505             //
7506             // Try to win over Dispose is there is a ----
7507             //
7508             if (Interlocked.CompareExchange(ref m_IntCleanedUp, 2, 0) != 0)
7509             {
7510                 GlobalLog.Leave("Socket#" + ValidationHelper.HashString(this) + "::SetAsyncEventSelect() Already Cleaned up, returning ... ", string.Empty);
7511                 return false;
7512             }
7513
7514             try
7515             {
7516                 m_BlockEventBits = blockEventBits;
7517                 m_RegisteredWait = ThreadPool.UnsafeRegisterWaitForSingleObject(m_AsyncEvent, s_RegisteredWaitCallback, this, Timeout.Infinite, true);
7518             }
7519             finally
7520             {
7521                 //
7522                 // Release dispose if any is waiting
7523                 //
7524                 Interlocked.Exchange(ref m_IntCleanedUp, 0);
7525             }
7526
7527             SocketError errorCode = SocketError.NotSocket;
7528             //
7529             // issue the native call
7530             //
7531             try {
7532                 errorCode = UnsafeNclNativeMethods.OSSOCK.WSAEventSelect(m_Handle, m_AsyncEvent.SafeWaitHandle, blockEventBits);
7533             }
7534             catch (Exception e)
7535             {
7536                 if (NclUtilities.IsFatal(e))
7537                     throw;
7538                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SetAsyncEventSelect() !!! (converting to ObjectDisposed) Exception :" + e.ToString());
7539                 GlobalLog.Assert(CleanedUp, "Socket#{0}::SetAsyncEventSelect|WSAEventSelect got exception and CleanedUp not set.", ValidationHelper.HashString(this));
7540             }
7541
7542             if (errorCode==SocketError.SocketError) {
7543                 //
7544                 // update our internal state after this socket error
7545                 // we won't throw since this is an internal method
7546                 //
7547                 UpdateStatusAfterSocketError(errorCode);
7548             }
7549
7550             //
7551             // the call to WSAEventSelect will put us in non-blocking mode, 
7552             // hence we need update internal status
7553             //
7554             willBlockInternal = false;
7555
7556             GlobalLog.Leave("Socket#" + ValidationHelper.HashString(this) + "::SetAsyncEventSelect", "m_BlockEventBits:" + m_BlockEventBits.ToString() + " willBlockInternal:" + willBlockInternal.ToString());
7557             return errorCode == SocketError.Success;
7558         }
7559
7560         private static void RegisteredWaitCallback(object state, bool timedOut)
7561         {
7562             GlobalLog.Enter("Socket#" + ValidationHelper.HashString(state) + "::RegisteredWaitCallback", "m_BlockEventBits:" + ((Socket)state).m_BlockEventBits.ToString());
7563 #if DEBUG
7564             // GlobalLog.SetThreadSource(ThreadKinds.Worker);  Because of change 1077887, need logic to determine thread type here.
7565             using (GlobalLog.SetThreadKind(ThreadKinds.System)) {
7566 #endif
7567             Socket me = (Socket)state;
7568
7569             // Interlocked to avoid a race condition with DoBeginConnect
7570             if (Interlocked.Exchange(ref me.m_RegisteredWait, null) != null)
7571             {
7572                 switch (me.m_BlockEventBits)
7573                 {
7574                     case AsyncEventBits.FdConnect:
7575                         me.ConnectCallback();
7576                         break;
7577
7578                     case AsyncEventBits.FdAccept:
7579                         me.AcceptCallback(null);
7580                         break;
7581                 }
7582             }
7583 #if DEBUG
7584             }
7585 #endif
7586             GlobalLog.Leave("Socket#" + ValidationHelper.HashString(state) + "::RegisteredWaitCallback", "m_BlockEventBits:" + ((Socket)state).m_BlockEventBits.ToString());
7587         }
7588
7589         //
7590         // ValidateBlockingMode - called before synchronous calls to validate
7591         // the fact that we are in blocking mode (not in non-blocking mode) so the
7592         // call will actually be synchronous
7593         //
7594         private void ValidateBlockingMode() {
7595             if (willBlock && !willBlockInternal) {
7596                 throw new InvalidOperationException(SR.GetString(SR.net_invasync));
7597             }
7598         }
7599
7600
7601         //
7602         // This Method binds the Socket Win32 Handle to the ThreadPool's CompletionPort
7603         // (make sure we only bind once per socket)
7604         //
7605         [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.UnmanagedCode)]
7606         internal void BindToCompletionPort()
7607         {
7608             //
7609             // Check to see if the socket native m_Handle is already
7610             // bound to the ThreadPool's completion port.
7611             //
7612             if (!m_BoundToThreadPool && !UseOverlappedIO) {
7613                 lock (this) {
7614                     if (!m_BoundToThreadPool) {
7615 #if SOCKETTHREADPOOL 
7616                         // bind the socket native m_Handle to prototype SocketThreadPool
7617                         GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BindToCompletionPort() calling SocketThreadPool.BindHandle()");
7618                         SocketThreadPool.BindHandle(m_Handle);
7619                         m_BoundToThreadPool = true;
7620 #else
7621                         //
7622                         // bind the socket native m_Handle to the ThreadPool
7623                         //
7624                         GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BindToCompletionPort() calling ThreadPool.BindHandle()");
7625
7626                         try
7627                         {
7628                             ThreadPool.BindHandle(m_Handle);
7629                             m_BoundToThreadPool = true;
7630                         }
7631                         catch (Exception exception)
7632                         {
7633                             if (NclUtilities.IsFatal(exception)) throw;
7634                             Close(0);
7635                             throw;
7636                         }
7637 #endif
7638                     }
7639                 }
7640             }
7641         }
7642
7643 #if TRAVE
7644         [System.Diagnostics.Conditional("TRAVE")]
7645         internal void DebugMembers() {
7646             GlobalLog.Print("m_Handle:" + m_Handle.DangerousGetHandle().ToString("x") );
7647             GlobalLog.Print("m_IsConnected: " + m_IsConnected);
7648         }
7649 #endif
7650
7651         //
7652         // AcceptAsync
7653         //        
7654         public bool AcceptAsync(SocketAsyncEventArgs e) {
7655
7656             bool retval;
7657
7658             if(s_LoggingEnabled) Logging.Enter(Logging.Sockets, this, "AcceptAsync", "");
7659        
7660             // Throw if socket disposed
7661             if(CleanedUp) {
7662                throw new ObjectDisposedException(GetType().FullName);
7663             }
7664             
7665             // Throw if multiple buffers specified.
7666             if(e.m_BufferList != null) {
7667                 throw new ArgumentException(SR.GetString(SR.net_multibuffernotsupported), "BufferList");
7668             }
7669             
7670             // Throw if not bound.
7671             if(m_RightEndPoint == null) {
7672                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustbind));
7673             }
7674
7675             // Throw if not listening.
7676             if(!isListening) {
7677                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustlisten));
7678             }
7679
7680             // Handle AcceptSocket property.
7681             if(e.AcceptSocket == null) {
7682                 // Accept socket not specified - create it.
7683                 e.AcceptSocket = new Socket(addressFamily, socketType, protocolType);
7684             } else {
7685                 // Validate accept socket for use here.
7686                 if(e.AcceptSocket.m_RightEndPoint != null && !e.AcceptSocket.m_IsDisconnected) {
7687                     throw new InvalidOperationException(SR.GetString(SR.net_sockets_namedmustnotbebound, "AcceptSocket"));
7688                 }
7689             }
7690
7691             // Prepare for the native call.
7692             e.StartOperationCommon(this);
7693             e.StartOperationAccept();
7694             BindToCompletionPort();
7695
7696             // Local variables for [....] completion.
7697             int bytesTransferred;
7698             SocketError socketError = SocketError.Success;
7699
7700             // Make the native call.
7701             try {
7702                 if(!AcceptEx(
7703                         m_Handle,
7704                         e.AcceptSocket.m_Handle,
7705                         (e.m_PtrSingleBuffer != IntPtr.Zero) ? e.m_PtrSingleBuffer : e.m_PtrAcceptBuffer,
7706                         (e.m_PtrSingleBuffer != IntPtr.Zero) ? e.Count - e.m_AcceptAddressBufferCount : 0,
7707                         e.m_AcceptAddressBufferCount / 2,
7708                         e.m_AcceptAddressBufferCount / 2,
7709                         out bytesTransferred,
7710                         e.m_PtrNativeOverlapped)) {
7711                     socketError = (SocketError)Marshal.GetLastWin32Error();
7712                 }
7713             }
7714             catch (Exception ex) {
7715                 // clear in-use on event arg object 
7716                 e.Complete();
7717                 throw ex;
7718             }
7719
7720             // Handle completion when completion port is not posted.
7721             if(socketError != SocketError.Success && socketError != SocketError.IOPending) {
7722                 e.FinishOperationSyncFailure(socketError, bytesTransferred, SocketFlags.None);
7723                 retval = false;
7724             } else {
7725                 retval = true;
7726             }
7727
7728             if(s_LoggingEnabled) Logging.Exit(Logging.Sockets, this, "AcceptAsync", retval);
7729             return retval;
7730         }
7731
7732         //
7733         // ConnectAsync
7734         // 
7735         public bool ConnectAsync(SocketAsyncEventArgs e) {
7736
7737             bool retval;
7738
7739             if(s_LoggingEnabled) Logging.Enter(Logging.Sockets, this, "ConnectAsync", "");
7740
7741             // Throw if socket disposed
7742             if(CleanedUp) {
7743                throw new ObjectDisposedException(GetType().FullName);
7744             }
7745
7746             // Throw if multiple buffers specified.
7747             if(e.m_BufferList != null) {
7748                 throw new ArgumentException(SR.GetString(SR.net_multibuffernotsupported), "BufferList");
7749             }
7750
7751             // Throw if RemoteEndPoint is null.
7752             if(e.RemoteEndPoint == null) {
7753                 throw new ArgumentNullException("remoteEP");
7754             }
7755             // Throw if listening.
7756             if(isListening) {
7757                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustnotlisten));
7758             }
7759             
7760
7761             // Check permissions for connect and prepare SocketAddress.
7762             EndPoint endPointSnapshot = e.RemoteEndPoint;
7763             DnsEndPoint dnsEP = endPointSnapshot as DnsEndPoint;
7764
7765             if (dnsEP != null) {
7766                 if (s_LoggingEnabled) Logging.PrintInfo(Logging.Sockets, "Socket#" + ValidationHelper.HashString(this) 
7767                     + "::ConnectAsync " + SR.GetString(SR.net_log_socket_connect_dnsendpoint));
7768
7769                 if (dnsEP.AddressFamily != AddressFamily.Unspecified && !CanTryAddressFamily(dnsEP.AddressFamily)) {
7770                     throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
7771                 }
7772
7773                 MultipleConnectAsync multipleConnectAsync = new SingleSocketMultipleConnectAsync(this, true);
7774
7775                 e.StartOperationCommon(this);
7776                 e.StartOperationWrapperConnect(multipleConnectAsync);
7777
7778                 retval = multipleConnectAsync.StartConnectAsync(e, dnsEP);
7779             } 
7780             else {
7781                 // Throw if remote address family doesn't match socket.
7782                 if (!CanTryAddressFamily(e.RemoteEndPoint.AddressFamily)) {
7783                     throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
7784                 }
7785                 
7786                 e.m_SocketAddress = CheckCacheRemote(ref endPointSnapshot, false);
7787
7788                 // Do wildcard bind if socket not bound.
7789                 if(m_RightEndPoint == null) {
7790                     if(endPointSnapshot.AddressFamily == AddressFamily.InterNetwork)
7791                         InternalBind(new IPEndPoint(IPAddress.Any, 0));
7792                     else
7793                         InternalBind(new IPEndPoint(IPAddress.IPv6Any, 0));
7794                 }
7795
7796                 // Save the old RightEndPoint and prep new RightEndPoint.           
7797                 EndPoint oldEndPoint = m_RightEndPoint;
7798                 if(m_RightEndPoint == null) {
7799                     m_RightEndPoint = endPointSnapshot;
7800                 }
7801
7802                 // Prepare for the native call.
7803                 e.StartOperationCommon(this);
7804                 e.StartOperationConnect();
7805                 BindToCompletionPort();
7806
7807
7808                 // Make the native call.
7809                 int bytesTransferred;
7810                 SocketError socketError = SocketError.Success;
7811                 try {
7812                     if(!ConnectEx(
7813                             m_Handle,
7814                             e.m_PtrSocketAddressBuffer,
7815                             e.m_SocketAddress.m_Size,
7816                             e.m_PtrSingleBuffer,
7817                             e.Count,
7818                             out bytesTransferred,
7819                             e.m_PtrNativeOverlapped)) {
7820                         socketError = (SocketError)Marshal.GetLastWin32Error();
7821                     }
7822                 }
7823                 catch (Exception ex) {
7824                     m_RightEndPoint = oldEndPoint;
7825                     // clear in-use on event arg object 
7826                     e.Complete();
7827                     throw ex;
7828                 }
7829
7830                 // Handle failure where completion port is not posted.
7831                 if(socketError != SocketError.Success && socketError != SocketError.IOPending) {
7832                     e.FinishOperationSyncFailure(socketError, bytesTransferred, SocketFlags.None);
7833                     retval = false;
7834                 } else {
7835                     retval = true;
7836                 }
7837             }
7838
7839             if(s_LoggingEnabled) Logging.Exit(Logging.Sockets, this, "ConnectAsync", retval);
7840             return retval;
7841         }
7842
7843         public static bool ConnectAsync(SocketType socketType, ProtocolType protocolType, SocketAsyncEventArgs e) {
7844
7845             bool retval;
7846
7847             if (s_LoggingEnabled) Logging.Enter(Logging.Sockets, null, "ConnectAsync", "");
7848
7849             // Throw if multiple buffers specified.
7850             if (e.m_BufferList != null) {
7851                 throw new ArgumentException(SR.GetString(SR.net_multibuffernotsupported), "BufferList");
7852             }
7853
7854             // Throw if RemoteEndPoint is null.
7855             if (e.RemoteEndPoint == null) {
7856                 throw new ArgumentNullException("remoteEP");
7857             }
7858
7859             EndPoint endPointSnapshot = e.RemoteEndPoint;
7860             DnsEndPoint dnsEP = endPointSnapshot as DnsEndPoint;
7861
7862             if (dnsEP != null) {
7863                 Socket attemptSocket = null;
7864                 MultipleConnectAsync multipleConnectAsync = null;
7865                 if (dnsEP.AddressFamily == AddressFamily.Unspecified) {
7866                     multipleConnectAsync = new MultipleSocketMultipleConnectAsync(socketType, protocolType);
7867                 } else {
7868                     attemptSocket = new Socket(dnsEP.AddressFamily, socketType, protocolType);
7869                     multipleConnectAsync = new SingleSocketMultipleConnectAsync(attemptSocket, false);
7870                 }
7871
7872                 e.StartOperationCommon(attemptSocket);
7873                 e.StartOperationWrapperConnect(multipleConnectAsync);
7874
7875                 retval = multipleConnectAsync.StartConnectAsync(e, dnsEP);
7876             } else {
7877                 Socket attemptSocket = new Socket(endPointSnapshot.AddressFamily, socketType, protocolType);
7878                 retval = attemptSocket.ConnectAsync(e);
7879             }
7880
7881             if (s_LoggingEnabled) Logging.Exit(Logging.Sockets, null, "ConnectAsync", retval);
7882             return retval;
7883         }
7884
7885         public static void CancelConnectAsync(SocketAsyncEventArgs e) {
7886
7887             if (e == null) {
7888                 throw new ArgumentNullException("e");
7889             }
7890             e.CancelConnectAsync();
7891         }
7892
7893         //
7894         // DisconnectAsync
7895         // 
7896         public bool DisconnectAsync(SocketAsyncEventArgs e) {
7897
7898             bool retval;
7899             
7900             if(s_LoggingEnabled) Logging.Enter(Logging.Sockets, this, "DisconnectAsync", "");
7901
7902             // Throw if socket disposed
7903             if(CleanedUp) {
7904                 throw new ObjectDisposedException(GetType().FullName);
7905             }
7906
7907             // Prepare for the native call.
7908             e.StartOperationCommon(this);
7909             e.StartOperationDisconnect();
7910             BindToCompletionPort();
7911
7912             // Make the native call.
7913             SocketError socketError = SocketError.Success;
7914             try {
7915                 if(!DisconnectEx(
7916                         m_Handle,
7917                         e.m_PtrNativeOverlapped,
7918                         (int)(e.DisconnectReuseSocket ? TransmitFileOptions.ReuseSocket : 0),
7919                         0)) {
7920                     socketError = (SocketError)Marshal.GetLastWin32Error();
7921                 }
7922             }
7923             catch(Exception ex) {
7924                 // clear in-use on event arg object 
7925                 e.Complete();
7926                 throw ex;
7927             }
7928
7929             // Handle completion when completion port is not posted.
7930             if(socketError != SocketError.Success && socketError != SocketError.IOPending) {
7931                 e.FinishOperationSyncFailure(socketError, 0, SocketFlags.None);
7932                 retval = false;
7933             } else {
7934                 retval = true;
7935             }
7936
7937             if(s_LoggingEnabled) Logging.Exit(Logging.Sockets, this, "DisconnectAsync", retval);
7938
7939             return retval;
7940         }
7941
7942         //
7943         // ReceiveAsync
7944         // 
7945         public bool ReceiveAsync(SocketAsyncEventArgs e) {
7946
7947             bool retval;
7948
7949             if(s_LoggingEnabled) Logging.Enter(Logging.Sockets, this, "ReceiveAsync", "");
7950
7951             // Throw if socket disposed
7952             if(CleanedUp) {
7953                 throw new ObjectDisposedException(GetType().FullName);
7954             }
7955
7956             // Prepare for the native call.
7957             e.StartOperationCommon(this);
7958             e.StartOperationReceive();
7959             BindToCompletionPort();
7960
7961             // Local vars for [....] completion of native call.
7962             SocketFlags flags = e.m_SocketFlags;
7963             int bytesTransferred;
7964             SocketError socketError;
7965
7966             // Wrap native methods with try/catch so event args object can be cleaned up
7967             try {
7968                 if(e.m_Buffer != null) {
7969                     // Single buffer case
7970                     socketError = UnsafeNclNativeMethods.OSSOCK.WSARecv(
7971                         m_Handle,
7972                         ref e.m_WSABuffer,
7973                         1,
7974                         out bytesTransferred,
7975                         ref flags,
7976                         e.m_PtrNativeOverlapped,
7977                         IntPtr.Zero);
7978                 } else {
7979                     // Multi buffer case
7980                     socketError = UnsafeNclNativeMethods.OSSOCK.WSARecv(
7981                         m_Handle,
7982                         e.m_WSABufferArray,
7983                         e.m_WSABufferArray.Length,
7984                         out bytesTransferred,
7985                         ref flags,
7986                         e.m_PtrNativeOverlapped,
7987                         IntPtr.Zero);
7988                 }
7989             }
7990             catch(Exception ex) {
7991                 // clear in-use on event arg object 
7992                 e.Complete();
7993                 throw ex;
7994             }
7995
7996             // Native method emits single catch-all error code when error occurs.
7997             // Must get Win32 error for specific error code.
7998             if(socketError != SocketError.Success) {
7999                 socketError = (SocketError)Marshal.GetLastWin32Error();
8000             }
8001
8002             // Handle completion when completion port is not posted.
8003             if(socketError != SocketError.Success && socketError != SocketError.IOPending) {
8004                 e.FinishOperationSyncFailure(socketError, bytesTransferred, flags);
8005                 retval = false;
8006             } else {
8007                 retval = true;
8008             }
8009
8010             if(s_LoggingEnabled) Logging.Exit(Logging.Sockets, this, "ReceiveAsync", retval);
8011             return retval;
8012         }
8013
8014         //
8015         // ReceiveFromAsync
8016         // 
8017         public bool ReceiveFromAsync(SocketAsyncEventArgs e) {
8018
8019             bool retval;
8020
8021             if(s_LoggingEnabled) Logging.Enter(Logging.Sockets, this, "ReceiveFromAsync", "");
8022
8023             // Throw if socket disposed
8024             if(CleanedUp) {
8025                 throw new ObjectDisposedException(GetType().FullName);
8026             }
8027
8028             // Throw if remote endpoint property is null.
8029             if(e.RemoteEndPoint == null) {
8030                 throw new ArgumentNullException("RemoteEndPoint");
8031             }
8032
8033             if(!CanTryAddressFamily(e.RemoteEndPoint.AddressFamily)) {
8034                 throw new ArgumentException(SR.GetString(SR.net_InvalidEndPointAddressFamily, 
8035                     e.RemoteEndPoint.AddressFamily, addressFamily), "RemoteEndPoint");
8036             }
8037
8038             // We don't do a CAS demand here because the contents of remoteEP aren't used by
8039             // WSARecvFrom; all that matters is that we generate a unique-to-this-call SocketAddress
8040             // with the right address family
8041             EndPoint endPointSnapshot = e.RemoteEndPoint;
8042             e.m_SocketAddress = SnapshotAndSerialize(ref endPointSnapshot);
8043             // DualMode may have updated the endPointSnapshot, and it has to have the same AddressFamily as 
8044             // e.m_SocketAddres for Create to work later.
8045             e.RemoteEndPoint = endPointSnapshot;
8046             
8047             // Prepare for the native call.
8048             e.StartOperationCommon(this);
8049             e.StartOperationReceiveFrom();
8050             BindToCompletionPort();
8051
8052             // Make the native call.
8053             SocketFlags flags = e.m_SocketFlags;
8054             int bytesTransferred;
8055             SocketError socketError;
8056
8057             try {
8058                 if(e.m_Buffer != null) {
8059                     socketError = UnsafeNclNativeMethods.OSSOCK.WSARecvFrom(
8060                                     m_Handle,
8061                                     ref e.m_WSABuffer,
8062                                     1,
8063                                     out bytesTransferred,
8064                                     ref flags,
8065                                     e.m_PtrSocketAddressBuffer,
8066                                     e.m_PtrSocketAddressBufferSize,
8067                                     e.m_PtrNativeOverlapped,
8068                                     IntPtr.Zero);
8069                 } else {
8070                     socketError = UnsafeNclNativeMethods.OSSOCK.WSARecvFrom(
8071                                     m_Handle,
8072                                     e.m_WSABufferArray,
8073                                     e.m_WSABufferArray.Length,
8074                                     out bytesTransferred,
8075                                     ref flags,
8076                                     e.m_PtrSocketAddressBuffer,
8077                                     e.m_PtrSocketAddressBufferSize,
8078                                     e.m_PtrNativeOverlapped,
8079                                     IntPtr.Zero);
8080                 }
8081             }
8082             catch(Exception ex) {
8083                 // clear in-use on event arg object 
8084                 e.Complete();
8085                 throw ex;
8086             }
8087
8088             // Native method emits single catch-all error code when error occurs.
8089             // Must get Win32 error for specific error code.
8090             if(socketError != SocketError.Success) {
8091                 socketError = (SocketError)Marshal.GetLastWin32Error();
8092             }
8093
8094             // Handle completion when completion port is not posted.
8095             if(socketError != SocketError.Success && socketError != SocketError.IOPending) {
8096                 e.FinishOperationSyncFailure(socketError, bytesTransferred, flags);
8097                 retval = false;
8098             } else {
8099                 retval = true;
8100             }
8101
8102             if(s_LoggingEnabled) Logging.Exit(Logging.Sockets, this, "ReceiveFromAsync", retval);
8103             return retval;
8104         }
8105
8106         //
8107         // ReceiveMessageFromAsync
8108         // 
8109         public bool ReceiveMessageFromAsync(SocketAsyncEventArgs e) {
8110
8111             bool retval;
8112
8113             if(s_LoggingEnabled) Logging.Enter(Logging.Sockets, this, "ReceiveMessageFromAsync", "");
8114           
8115             // Throw if socket disposed
8116             if(CleanedUp) {
8117                 throw new ObjectDisposedException(GetType().FullName);
8118             }
8119
8120             // Throw if remote endpoint property is null.
8121             if(e.RemoteEndPoint == null) {
8122                 throw new ArgumentNullException("RemoteEndPoint");
8123             }
8124
8125             if(!CanTryAddressFamily(e.RemoteEndPoint.AddressFamily)) {
8126                 throw new ArgumentException(SR.GetString(SR.net_InvalidEndPointAddressFamily, 
8127                     e.RemoteEndPoint.AddressFamily, addressFamily), "RemoteEndPoint");
8128             }
8129
8130             // We don't do a CAS demand here because the contents of remoteEP aren't used by
8131             // WSARecvMsg; all that matters is that we generate a unique-to-this-call SocketAddress
8132             // with the right address family
8133             EndPoint endPointSnapshot = e.RemoteEndPoint;
8134             e.m_SocketAddress = SnapshotAndSerialize(ref endPointSnapshot);
8135             // DualMode may have updated the endPointSnapshot, and it has to have the same AddressFamily as 
8136             // e.m_SocketAddres for Create to work later.
8137             e.RemoteEndPoint = endPointSnapshot;
8138
8139             SetReceivingPacketInformation();
8140
8141             // Prepare for the native call.
8142             e.StartOperationCommon(this);
8143             e.StartOperationReceiveMessageFrom();
8144             BindToCompletionPort();
8145
8146             
8147             // Make the native call.
8148             int bytesTransferred;
8149             SocketError socketError;
8150
8151             try {
8152                 socketError = WSARecvMsg(
8153                     m_Handle,
8154                     e.m_PtrWSAMessageBuffer,
8155                     out bytesTransferred,
8156                     e.m_PtrNativeOverlapped,
8157                     IntPtr.Zero);
8158             }
8159             catch(Exception ex) {
8160                 // clear in-use on event arg object 
8161                 e.Complete();
8162                 throw ex;
8163             }
8164             
8165             // Native method emits single catch-all error code when error occurs.
8166             // Must get Win32 error for specific error code.
8167             if(socketError != SocketError.Success) {
8168                 socketError = (SocketError)Marshal.GetLastWin32Error();
8169             }
8170
8171             // Handle completion when completion port is not posted.
8172             if(socketError != SocketError.Success && socketError != SocketError.IOPending) {
8173                 e.FinishOperationSyncFailure(socketError, bytesTransferred, SocketFlags.None);
8174                 retval = false;
8175             } else {
8176                 retval = true;
8177             }
8178
8179             if(s_LoggingEnabled) Logging.Exit(Logging.Sockets, this, "ReceiveMessageFromAsync", retval);
8180             
8181             return retval;
8182         }
8183
8184         //
8185         // SendAsync
8186         // 
8187         public bool SendAsync(SocketAsyncEventArgs e) {
8188
8189             bool retval;
8190
8191             if(s_LoggingEnabled) Logging.Enter(Logging.Sockets, this, "SendAsync", "");
8192
8193             // Throw if socket disposed
8194             if(CleanedUp) {
8195                 throw new ObjectDisposedException(GetType().FullName);
8196             }
8197
8198             // Prepare for the native call.
8199             e.StartOperationCommon(this);
8200             e.StartOperationSend();
8201             BindToCompletionPort();
8202
8203             
8204             // Local vars for [....] completion of native call.
8205             int bytesTransferred;
8206             SocketError socketError;
8207
8208             // Wrap native methods with try/catch so event args object can be cleaned up
8209             try {
8210                 if(e.m_Buffer != null) {
8211                     // Single buffer case
8212                     socketError = UnsafeNclNativeMethods.OSSOCK.WSASend(
8213                         m_Handle,
8214                         ref e.m_WSABuffer,
8215                         1,
8216                         out bytesTransferred,
8217                         e.m_SocketFlags,
8218                         e.m_PtrNativeOverlapped,
8219                         IntPtr.Zero);
8220                 } else {
8221                     // Multi buffer case
8222                     socketError = UnsafeNclNativeMethods.OSSOCK.WSASend(
8223                         m_Handle,
8224                         e.m_WSABufferArray,
8225                         e.m_WSABufferArray.Length,
8226                         out bytesTransferred,
8227                         e.m_SocketFlags,
8228                         e.m_PtrNativeOverlapped,
8229                         IntPtr.Zero);
8230                 }
8231             }
8232             catch(Exception ex) {
8233                 // clear in-use on event arg object 
8234                 e.Complete();
8235                 throw ex;
8236             }
8237
8238             // Native method emits single catch-all error code when error occurs.
8239             // Must get Win32 error for specific error code.
8240             if(socketError != SocketError.Success) {
8241                 socketError = (SocketError)Marshal.GetLastWin32Error();
8242             }
8243
8244             // Handle completion when completion port is not posted.
8245             if(socketError != SocketError.Success && socketError != SocketError.IOPending) {
8246                 e.FinishOperationSyncFailure(socketError, bytesTransferred, SocketFlags.None);
8247                 retval = false;
8248             } else {
8249                 retval = true;
8250             }
8251
8252             if(s_LoggingEnabled) Logging.Enter(Logging.Sockets, this, "SendAsync", retval);
8253
8254             return retval;
8255         }
8256
8257         //
8258         // SendPacketsAsync
8259         // 
8260         public bool SendPacketsAsync(SocketAsyncEventArgs e) {
8261
8262             bool retval;
8263
8264             if(s_LoggingEnabled) Logging.Enter(Logging.Sockets, this, "SendPacketsAsync", "");
8265
8266             // Throw if socket disposed
8267             if(CleanedUp) {
8268                 throw new ObjectDisposedException(GetType().FullName);
8269             }
8270
8271             // Throw if not connected.
8272             if(!Connected) {
8273                 throw new NotSupportedException(SR.GetString(SR.net_notconnected));
8274             }
8275
8276             // Prepare for the native call.
8277             e.StartOperationCommon(this);
8278             e.StartOperationSendPackets();
8279             BindToCompletionPort();
8280
8281             // Make the native call.
8282             SocketError socketError;
8283             bool result;
8284
8285             if (e.m_SendPacketsDescriptor.Length > 0) {
8286                 try {
8287                     result = TransmitPackets(
8288                                 m_Handle, 
8289                                 e.m_PtrSendPacketsDescriptor,
8290                                 e.m_SendPacketsDescriptor.Length, 
8291                                 e.m_SendPacketsSendSize,
8292                                 e.m_PtrNativeOverlapped, 
8293                                 e.m_SendPacketsFlags); 
8294                 }
8295                catch(Exception) {
8296                     // clear in-use on event arg object 
8297                     e.Complete();
8298                     throw;
8299                 }
8300
8301                 if(!result) {
8302                     socketError = (SocketError)Marshal.GetLastWin32Error();
8303                 } else {
8304                     socketError = SocketError.Success;
8305                 }
8306
8307                 // Handle completion when completion port is not posted.
8308                 if(socketError != SocketError.Success && socketError != SocketError.IOPending) {
8309                     e.FinishOperationSyncFailure(socketError, 0, SocketFlags.None);
8310                     retval = false;
8311                 } else {
8312                     retval = true;
8313                 }
8314             }
8315             else {
8316                 // No buffers or files to send.
8317                 e.FinishOperationSuccess(SocketError.Success, 0, SocketFlags.None);
8318                 retval = false;
8319             }
8320
8321
8322             if(s_LoggingEnabled) Logging.Exit(Logging.Sockets, this, "SendPacketsAsync", retval);
8323
8324             return retval;
8325         }
8326
8327         //
8328         // SendToAsync
8329         // 
8330         public bool SendToAsync(SocketAsyncEventArgs e) {
8331
8332             bool retval;
8333
8334             if(s_LoggingEnabled) Logging.Enter(Logging.Sockets, this, "SendToAsync", "");
8335
8336             // Throw if socket disposed
8337             if(CleanedUp) {
8338                 throw new ObjectDisposedException(GetType().FullName);
8339             }
8340
8341             // Throw if remote endpoint property is null.
8342             if(e.RemoteEndPoint == null) {
8343                 throw new ArgumentNullException("RemoteEndPoint");
8344             }
8345
8346             // Check permissions for connect and prepare SocketAddress
8347             EndPoint endPointSnapshot = e.RemoteEndPoint;
8348             e.m_SocketAddress = CheckCacheRemote(ref endPointSnapshot, false);
8349
8350             // Prepare for the native call.
8351             e.StartOperationCommon(this);
8352             e.StartOperationSendTo();
8353             BindToCompletionPort();
8354
8355             // Make the native call.
8356             int bytesTransferred;
8357             SocketError socketError;
8358
8359             // Wrap native methods with try/catch so event args object can be cleaned up
8360             try {
8361                 if(e.m_Buffer != null) {
8362                     // Single buffer case
8363                     socketError = UnsafeNclNativeMethods.OSSOCK.WSASendTo(
8364                                     m_Handle,
8365                                     ref e.m_WSABuffer,
8366                                     1,
8367                                     out bytesTransferred,
8368                                     e.m_SocketFlags,
8369                                     e.m_PtrSocketAddressBuffer,
8370                                     e.m_SocketAddress.m_Size,
8371                                     e.m_PtrNativeOverlapped,
8372                                     IntPtr.Zero);
8373                 } else {
8374                     socketError = UnsafeNclNativeMethods.OSSOCK.WSASendTo(
8375                                     m_Handle,
8376                                     e.m_WSABufferArray,
8377                                     e.m_WSABufferArray.Length,
8378                                     out bytesTransferred,
8379                                     e.m_SocketFlags,
8380                                     e.m_PtrSocketAddressBuffer,
8381                                     e.m_SocketAddress.m_Size,
8382                                     e.m_PtrNativeOverlapped,
8383                                     IntPtr.Zero);
8384
8385
8386                 }
8387             }
8388             catch(Exception ex) {
8389                 // clear in-use on event arg object 
8390                 e.Complete();
8391                 throw ex;
8392             }
8393
8394             // Native method emits single catch-all error code when error occurs.
8395             // Must get Win32 error for specific error code.
8396             if(socketError != SocketError.Success) {
8397                 socketError = (SocketError)Marshal.GetLastWin32Error();
8398             }
8399
8400             // Handle completion when completion port is not posted.
8401             if(socketError != SocketError.Success && socketError != SocketError.IOPending) {
8402                 e.FinishOperationSyncFailure(socketError, bytesTransferred, SocketFlags.None);
8403                 retval = false;
8404             } else {
8405                 retval = true;
8406             }
8407
8408             if(s_LoggingEnabled) Logging.Exit(Logging.Sockets, this, "SendToAsync", retval);
8409
8410             return retval;
8411         }
8412 #endif // !MONO
8413     }  // end of class Socket
8414
8415 #if !MONO
8416     internal class ConnectAsyncResult:ContextAwareResult{
8417         private EndPoint m_EndPoint;
8418         internal ConnectAsyncResult(object myObject, EndPoint endPoint, object myState, AsyncCallback myCallBack):base(myObject, myState, myCallBack) {
8419             m_EndPoint = endPoint;
8420         }
8421         internal EndPoint RemoteEndPoint {
8422             get { return m_EndPoint; }
8423         }
8424     }
8425
8426     internal class AcceptAsyncResult:ContextAwareResult{
8427         internal AcceptAsyncResult(object myObject, object myState, AsyncCallback myCallBack):base(myObject, myState, myCallBack) {
8428         }
8429     }
8430 #endif
8431
8432     public enum SocketAsyncOperation {
8433         None = 0,
8434         Accept,
8435         Connect,
8436         Disconnect,
8437         Receive,
8438         ReceiveFrom,
8439         ReceiveMessageFrom,
8440         Send,
8441         SendPackets,
8442         SendTo
8443     }
8444
8445     // class that wraps the semantics of a winsock TRANSMIT_PACKETS_ELEMENTS struct
8446     public class SendPacketsElement {
8447         internal string m_FilePath;
8448         internal byte [] m_Buffer;
8449         internal int m_Offset;
8450         internal int m_Count;
8451 #if MONO
8452         bool m_endOfPacket;
8453 #else
8454         internal UnsafeNclNativeMethods.OSSOCK.TransmitPacketsElementFlags m_Flags;
8455 #endif
8456
8457         // hide default constructor
8458         private SendPacketsElement() {}
8459
8460         // constructors for file elements
8461         public SendPacketsElement(string filepath) :
8462             this(filepath, 0, 0, false) { }
8463
8464         public SendPacketsElement(string filepath, int offset, int count) : 
8465             this(filepath, offset, count, false) { }
8466
8467         public SendPacketsElement(string filepath, int offset, int count, bool endOfPacket) {
8468             // We will validate if the file exists on send
8469             if (filepath == null) {
8470                 throw new ArgumentNullException("filepath");
8471             }
8472             // The native API will validate the file length on send
8473             if (offset < 0) {
8474                 throw new ArgumentOutOfRangeException("offset");
8475             }
8476             if (count < 0) {
8477                 throw new ArgumentOutOfRangeException("count");
8478             }
8479             Contract.EndContractBlock();
8480
8481 #if MONO
8482             Initialize(filepath, null, offset, count, /*UnsafeNclNativeMethods.OSSOCK.TransmitPacketsElementFlags.File,*/
8483                 endOfPacket);
8484 #else
8485             Initialize(filepath, null, offset, count, UnsafeNclNativeMethods.OSSOCK.TransmitPacketsElementFlags.File,
8486                 endOfPacket);
8487 #endif
8488         }
8489
8490         // constructors for buffer elements
8491         public SendPacketsElement(byte[] buffer) : 
8492             this(buffer, 0, (buffer != null ? buffer.Length : 0), false) { }
8493
8494         public SendPacketsElement(byte[] buffer, int offset, int count) :
8495             this(buffer, offset, count, false) { }
8496
8497         public SendPacketsElement(byte[] buffer, int offset, int count, bool endOfPacket) {
8498             if (buffer == null) {
8499                 throw new ArgumentNullException("buffer");
8500             }
8501             if (offset < 0 || offset > buffer.Length) {
8502                 throw new ArgumentOutOfRangeException("offset");
8503             }
8504             if (count < 0 || count > (buffer.Length - offset)) {
8505                 throw new ArgumentOutOfRangeException("count");
8506             }
8507             Contract.EndContractBlock();
8508
8509 #if MONO
8510             Initialize(null, buffer, offset, count, /*UnsafeNclNativeMethods.OSSOCK.TransmitPacketsElementFlags.Memory,*/
8511                 endOfPacket);
8512 #else
8513             Initialize(null, buffer, offset, count, UnsafeNclNativeMethods.OSSOCK.TransmitPacketsElementFlags.Memory, 
8514                 endOfPacket);
8515 #endif
8516         }
8517
8518         private void Initialize(string filePath, byte[] buffer, int offset, int count, 
8519             /*UnsafeNclNativeMethods.OSSOCK.TransmitPacketsElementFlags flags,*/ bool endOfPacket) {
8520
8521             m_FilePath = filePath;
8522             m_Buffer = buffer;
8523             m_Offset = offset;
8524             m_Count = count;
8525 #if MONO
8526             m_endOfPacket = endOfPacket;
8527 #else
8528             m_Flags = flags;
8529             if (endOfPacket) {
8530                 m_Flags |= UnsafeNclNativeMethods.OSSOCK.TransmitPacketsElementFlags.EndOfPacket;
8531             }
8532 #endif
8533         }
8534
8535         // Filename property
8536         public string FilePath {
8537             get { return m_FilePath; }
8538         }
8539         
8540         // Buffer property
8541         public byte[] Buffer {
8542             get { return m_Buffer; }
8543         }
8544
8545         // Count property
8546         public int Count {
8547             get { return m_Count; }
8548         }
8549
8550         // Offset property
8551         public int Offset {
8552             get { return m_Offset; }
8553         }
8554
8555         // EndOfPacket property
8556         public bool EndOfPacket {
8557             get {
8558 #if MONO
8559                 return m_endOfPacket;
8560 #else
8561                 return (m_Flags & UnsafeNclNativeMethods.OSSOCK.TransmitPacketsElementFlags.EndOfPacket) != 0;
8562 #endif
8563              }
8564         }
8565     }
8566
8567     #region designer support for System.Windows.dll
8568     //introduced for supporting design-time loading of System.Windows.dll
8569     [Obsolete("This API supports the .NET Framework infrastructure and is not intended to be used directly from your code.", true)]
8570     [EditorBrowsable(EditorBrowsableState.Never)]
8571     public enum SocketClientAccessPolicyProtocol
8572     {
8573         Tcp,
8574         Http
8575     }
8576     #endregion        
8577
8578 #if !MONO
8579     public class SocketAsyncEventArgs : EventArgs, IDisposable {
8580
8581         // Struct sizes needed for some custom marshalling.
8582         internal static readonly int s_ControlDataSize = Marshal.SizeOf(typeof(UnsafeNclNativeMethods.OSSOCK.ControlData));
8583         internal static readonly int s_ControlDataIPv6Size = Marshal.SizeOf(typeof(UnsafeNclNativeMethods.OSSOCK.ControlDataIPv6));
8584         internal static readonly int s_WSAMsgSize = Marshal.SizeOf(typeof(UnsafeNclNativeMethods.OSSOCK.WSAMsg));
8585
8586         // AcceptSocket property variables.
8587         internal Socket m_AcceptSocket;
8588         private  Socket m_ConnectSocket;
8589        
8590         // Buffer,Offset,Count property variables.
8591         internal byte[] m_Buffer;
8592         internal WSABuffer m_WSABuffer;
8593         internal IntPtr m_PtrSingleBuffer;
8594         internal int m_Count;
8595         internal int m_Offset;
8596
8597         // BufferList property variables.
8598         internal IList<ArraySegment<byte> > m_BufferList;
8599         private bool m_BufferListChanged;
8600         internal WSABuffer[] m_WSABufferArray;
8601
8602         // BytesTransferred property variables.
8603         private int m_BytesTransferred;
8604
8605         // Completed event property variables.
8606         private event EventHandler<SocketAsyncEventArgs> m_Completed;
8607         private bool m_CompletedChanged;
8608
8609         // DisconnectReuseSocket propery variables.
8610         private bool m_DisconnectReuseSocket;
8611         
8612         // LastOperation property variables.
8613         private SocketAsyncOperation m_CompletedOperation;
8614
8615         // ReceiveMessageFromPacketInfo property variables.
8616         private IPPacketInformation m_ReceiveMessageFromPacketInfo;
8617
8618         // RemoteEndPoint property variables.
8619         private EndPoint m_RemoteEndPoint;
8620
8621         // SendPacketsFlags property variable.
8622         internal TransmitFileOptions m_SendPacketsFlags;
8623
8624         // SendPacketsSendSize property variable.
8625         internal int m_SendPacketsSendSize;
8626
8627         // SendPacketsElements property variables.
8628         internal SendPacketsElement[] m_SendPacketsElements;
8629         private SendPacketsElement[] m_SendPacketsElementsInternal;
8630         internal int m_SendPacketsElementsFileCount;
8631         internal int m_SendPacketsElementsBufferCount;
8632
8633         // SocketError property variables.
8634         private SocketError m_SocketError;
8635         private Exception   m_ConnectByNameError;
8636
8637         // SocketFlags property variables.
8638         internal SocketFlags m_SocketFlags;
8639
8640         // UserToken property variables.
8641         private object m_UserToken;
8642
8643         // Internal buffer for AcceptEx when Buffer not supplied.
8644         internal byte[] m_AcceptBuffer;
8645         internal int m_AcceptAddressBufferCount;
8646         internal IntPtr m_PtrAcceptBuffer;
8647                
8648         // Internal SocketAddress buffer
8649         internal SocketAddress m_SocketAddress;
8650         private GCHandle m_SocketAddressGCHandle;
8651         private SocketAddress m_PinnedSocketAddress;
8652         internal IntPtr m_PtrSocketAddressBuffer;
8653         internal IntPtr m_PtrSocketAddressBufferSize;
8654         
8655         // Internal buffers for WSARecvMsg
8656         private byte[] m_WSAMessageBuffer;
8657         private GCHandle m_WSAMessageBufferGCHandle;
8658         internal IntPtr m_PtrWSAMessageBuffer;
8659         private byte[] m_ControlBuffer;
8660         private GCHandle m_ControlBufferGCHandle;
8661         internal IntPtr m_PtrControlBuffer;
8662         private WSABuffer[] m_WSARecvMsgWSABufferArray;
8663         private GCHandle m_WSARecvMsgWSABufferArrayGCHandle;
8664         private IntPtr m_PtrWSARecvMsgWSABufferArray;
8665
8666         // Internal variables for SendPackets
8667         internal FileStream[] m_SendPacketsFileStreams;
8668         internal SafeHandle[] m_SendPacketsFileHandles;
8669         internal UnsafeNclNativeMethods.OSSOCK.TransmitPacketsElement[] m_SendPacketsDescriptor;
8670         internal IntPtr m_PtrSendPacketsDescriptor;
8671         
8672         // Misc state variables.
8673         private ExecutionContext m_Context;
8674         private ExecutionContext m_ContextCopy;
8675         private ContextCallback m_ExecutionCallback;
8676         private Socket m_CurrentSocket;
8677         private bool m_DisposeCalled;
8678
8679         // Controls thread safety via Interlocked
8680         private const int Configuring = -1;
8681         private const int Free = 0;
8682         private const int InProgress = 1;
8683         private const int Disposed = 2;
8684         private int m_Operating;
8685
8686         // Overlapped object related variables.
8687         internal SafeNativeOverlapped m_PtrNativeOverlapped;
8688         private Overlapped m_Overlapped;
8689         private object[] m_ObjectsToPin;
8690         private enum PinState {
8691             None = 0,
8692             NoBuffer,
8693             SingleAcceptBuffer,
8694             SingleBuffer,
8695             MultipleBuffer,
8696             SendPackets
8697         }
8698         private PinState m_PinState;
8699         private byte[] m_PinnedAcceptBuffer;
8700         private byte[] m_PinnedSingleBuffer;
8701         private int m_PinnedSingleBufferOffset;
8702         private int m_PinnedSingleBufferCount;
8703
8704         private MultipleConnectAsync m_MultipleConnect;
8705
8706         private static bool s_LoggingEnabled = Logging.On;
8707
8708         #region designer support for System.Windows.dll
8709         //introduced for supporting design-time loading of System.Windows.dll
8710         [Obsolete("This API supports the .NET Framework infrastructure and is not intended to be used directly from your code.", true)]
8711         [EditorBrowsable(EditorBrowsableState.Never)]
8712         public SocketClientAccessPolicyProtocol SocketClientAccessPolicyProtocol { get; set; }        
8713         #endregion          
8714
8715
8716         // Public constructor.
8717         public SocketAsyncEventArgs() {
8718
8719             // Create callback delegate
8720             m_ExecutionCallback = new ContextCallback(ExecutionCallback);
8721             
8722             // Zero tells TransmitPackets to select a default send size.
8723             m_SendPacketsSendSize = 0;
8724         }
8725
8726         // AcceptSocket property.
8727         public Socket AcceptSocket {
8728             get { return m_AcceptSocket; }
8729             set { m_AcceptSocket = value; }
8730         }
8731
8732         public Socket ConnectSocket {
8733             get { return m_ConnectSocket; }
8734         }
8735
8736         // Buffer property.
8737         public byte[] Buffer {
8738             get { return m_Buffer; }
8739         }
8740
8741         // Offset property.
8742         public int Offset {
8743             get { return m_Offset; }
8744         }
8745
8746         // Count property.
8747         public int Count {
8748             get { return m_Count; }
8749         }
8750
8751         // BufferList property.
8752         // Mutually exclusive with Buffer.
8753         // Setting this property with an existing non-null Buffer will throw.    
8754         public IList<ArraySegment<byte> > BufferList {
8755             get { return m_BufferList; }
8756             set {
8757                 StartConfiguring();
8758                 try {
8759                     if(value != null && m_Buffer != null) {
8760                         throw new ArgumentException(SR.GetString(SR.net_ambiguousbuffers, "Buffer"));
8761                     }
8762                     m_BufferList = value;
8763                     m_BufferListChanged = true;
8764                     CheckPinMultipleBuffers();
8765                 } finally {
8766                     Complete();
8767                 }
8768             }
8769         }
8770
8771         // BytesTransferred property.
8772         public int BytesTransferred {
8773             get { return m_BytesTransferred; }
8774         }
8775
8776         // Completed property.
8777         public event EventHandler<SocketAsyncEventArgs> Completed {
8778             add {
8779                 m_Completed += value;
8780                 m_CompletedChanged = true;
8781             }
8782             remove {
8783                 m_Completed -= value;
8784                 m_CompletedChanged = true;
8785             }
8786         }
8787         
8788         // Method to raise Completed event.
8789         protected virtual void OnCompleted(SocketAsyncEventArgs e) {
8790             EventHandler<SocketAsyncEventArgs> handler = m_Completed;
8791             if(handler != null) {
8792                 handler(e.m_CurrentSocket, e);
8793             }
8794         }
8795
8796         // DisconnectResuseSocket property.
8797         public bool DisconnectReuseSocket {
8798             get { return m_DisconnectReuseSocket; }
8799             set { m_DisconnectReuseSocket = value; }
8800         }
8801
8802         // LastOperation property.
8803         public SocketAsyncOperation LastOperation {
8804             get { return m_CompletedOperation; }
8805         }
8806
8807          // ReceiveMessageFromPacketInfo property.
8808         public IPPacketInformation ReceiveMessageFromPacketInfo {
8809             get { return m_ReceiveMessageFromPacketInfo; }
8810         }
8811
8812         // RemoteEndPoint property.
8813         public EndPoint RemoteEndPoint {
8814             get { return m_RemoteEndPoint; }
8815             set { m_RemoteEndPoint = value; }
8816         }
8817
8818         // SendPacketsElements property.
8819         public SendPacketsElement[] SendPacketsElements {
8820             get { return m_SendPacketsElements; }
8821             set {
8822                 StartConfiguring();
8823                 try {
8824                     m_SendPacketsElements = value;
8825                     m_SendPacketsElementsInternal = null;
8826                 } finally {
8827                     Complete();
8828                 }
8829             }
8830         }
8831
8832         // SendPacketsFlags property.
8833         public TransmitFileOptions SendPacketsFlags {
8834             get { return m_SendPacketsFlags; }
8835             set { m_SendPacketsFlags = value; }
8836         }
8837
8838         // SendPacketsSendSize property.
8839         public int SendPacketsSendSize {
8840             get { return m_SendPacketsSendSize; }
8841             set { m_SendPacketsSendSize = value; }
8842         }
8843         
8844         // SocketError property.
8845         public SocketError SocketError {
8846             get { return m_SocketError; }
8847             set { m_SocketError = value; }
8848         }
8849
8850         public Exception ConnectByNameError {
8851             get { return m_ConnectByNameError; }
8852         }
8853
8854         // SocketFlags property.
8855         public SocketFlags SocketFlags {
8856             get { return m_SocketFlags; }
8857             set { m_SocketFlags = value; }
8858         }
8859
8860         // UserToken property.
8861         public object UserToken {
8862             get { return m_UserToken; }
8863             set { m_UserToken = value; }
8864         }
8865
8866         // SetBuffer(byte[], int, int) method.
8867         public void SetBuffer(byte [] buffer, int offset, int count) {
8868             SetBufferInternal(buffer, offset, count);
8869         }
8870
8871         // SetBuffer(int, int) method.
8872         public void SetBuffer(int offset, int count) {
8873             SetBufferInternal(m_Buffer, offset, count);
8874         }
8875
8876         private void SetBufferInternal(byte [] buffer, int offset, int count) {
8877             StartConfiguring();
8878             try {
8879                 if (buffer == null) {
8880
8881                     // Clear out existing buffer.
8882                     m_Buffer = null;
8883                     m_Offset = 0;
8884                     m_Count = 0;
8885
8886                 } else {
8887                     // Can't have both Buffer and BufferList
8888                     if(m_BufferList != null) {
8889                         throw new ArgumentException(SR.GetString(SR.net_ambiguousbuffers, "BufferList"));
8890                     }
8891                     // Offset and count can't be negative and the 
8892                     // combination must be in bounds of the array.
8893                     if (offset < 0 || offset > buffer.Length) {
8894                         throw new ArgumentOutOfRangeException("offset");
8895                     }
8896                     if (count < 0 || count > (buffer.Length - offset)) {
8897                         throw new ArgumentOutOfRangeException("count");
8898                     }
8899                     m_Buffer = buffer;
8900                     m_Offset = offset;
8901                     m_Count = count;
8902                 }
8903
8904                 // Pin new or unpin old buffer.
8905                 CheckPinSingleBuffer(true);
8906             } finally {
8907                 Complete();
8908             }
8909        }
8910             
8911
8912
8913         // Method to update internal state after [....] or async completion.
8914         internal void SetResults(SocketError socketError, int bytesTransferred, SocketFlags flags) {
8915             m_SocketError = socketError;
8916             m_ConnectByNameError = null;
8917             m_BytesTransferred = bytesTransferred;
8918             m_SocketFlags = flags;            
8919         }
8920
8921         internal void SetResults(Exception exception, int bytesTransferred, SocketFlags flags) {
8922             m_ConnectByNameError = exception;
8923             m_BytesTransferred = bytesTransferred;
8924             m_SocketFlags = flags;
8925
8926             if (exception == null) {
8927                 m_SocketError = SocketError.Success;
8928             }
8929             else {
8930                 SocketException socketException = exception as SocketException;
8931                 if (socketException != null) {
8932                     m_SocketError = socketException.SocketErrorCode;
8933                 }
8934                 else {
8935                     m_SocketError = SocketError.SocketError;
8936                 }
8937             }
8938         }
8939
8940         // Context callback delegate.
8941         private void ExecutionCallback(object ignored) {
8942             OnCompleted(this);
8943         }
8944
8945         // Method to mark this object as no longer "in-use".
8946         // Will also execute a Dispose deferred because I/O was in progress.  
8947         internal void Complete() {
8948
8949             // Mark as not in-use            
8950             m_Operating = Free;
8951
8952             // Check for deferred Dispose().
8953             // The deferred Dispose is not guaranteed if Dispose is called while an operation is in progress. 
8954             // The m_DisposeCalled variable is not managed in a thread-safe manner on purpose for performance.
8955             if (m_DisposeCalled) {
8956                 Dispose();
8957             }
8958         }
8959
8960         // Dispose call to implement IDisposable.
8961         public void Dispose() {
8962
8963             // Remember that Dispose was called.
8964             m_DisposeCalled = true;
8965
8966             // Check if this object is in-use for an async socket operation.
8967             if(Interlocked.CompareExchange(ref m_Operating, Disposed, Free) != Free) {
8968                 // Either already disposed or will be disposed when current operation completes.
8969                 return;
8970             }
8971
8972             // OK to dispose now.
8973             // Free native overlapped data.
8974             FreeOverlapped(false);
8975
8976             // Don't bother finalizing later.
8977             GC.SuppressFinalize(this);
8978         }
8979
8980         // Finalizer
8981         ~SocketAsyncEventArgs() {
8982             FreeOverlapped(true);
8983         }
8984
8985         // Us a try/Finally to make sure Complete is called when you're done
8986         private void StartConfiguring() {
8987             int status = Interlocked.CompareExchange(ref m_Operating, Configuring, Free);
8988             if (status == InProgress || status == Configuring) {
8989                 throw new InvalidOperationException(SR.GetString(SR.net_socketopinprogress));
8990             }
8991             else if (status == Disposed)
8992             {
8993                 throw new ObjectDisposedException(GetType().FullName);
8994             }
8995         }
8996
8997         // Method called to prepare for a native async socket call.
8998         // This method performs the tasks common to all socket operations.
8999         internal void StartOperationCommon(Socket socket) {
9000
9001             // Change status to "in-use".
9002             if(Interlocked.CompareExchange(ref m_Operating, InProgress, Free) != Free) {
9003
9004                 // If it was already "in-use" check if Dispose was called.
9005                 if(m_DisposeCalled) {
9006
9007                     // Dispose was called - throw ObjectDisposed.
9008                     throw new ObjectDisposedException(GetType().FullName);
9009                 }
9010
9011                 // Only one at a time.
9012                 throw new InvalidOperationException(SR.GetString(SR.net_socketopinprogress));
9013             }
9014
9015             // Prepare execution context for callback.
9016
9017             if (ExecutionContext.IsFlowSuppressed()) {
9018
9019                 // Fast path for when flow is suppressed.
9020
9021                 m_Context = null;
9022                 m_ContextCopy = null;
9023
9024             } else {
9025
9026                 // Flow is not suppressed.
9027
9028                 // If event delegates have changed or socket has changed
9029                 // then discard any existing context.
9030
9031                 if (m_CompletedChanged || socket != m_CurrentSocket) {
9032
9033                     m_CompletedChanged = false;
9034                     m_Context = null;
9035                     m_ContextCopy = null;
9036                 }
9037                 
9038                 // Capture execution context if none already.
9039
9040                 if (m_Context == null) {
9041                     m_Context = ExecutionContext.Capture();
9042                 }
9043
9044                 // If there is an execution context we need a fresh copy for each completion.
9045                 
9046                 if(m_Context != null) {
9047                     m_ContextCopy = m_Context.CreateCopy();
9048                 }
9049             }
9050
9051             // Remember current socket.
9052             m_CurrentSocket = socket;
9053         }
9054
9055         internal void StartOperationAccept() {
9056             // Remember the operation type.
9057             m_CompletedOperation = SocketAsyncOperation.Accept;
9058
9059             // AcceptEx needs a single buffer with room for two special sockaddr data structures.
9060             // It can also take additional buffer space in front of those special sockaddr 
9061             // structures that can be filled in with initial data coming in on a connection.
9062             
9063             // First calculate the special AcceptEx address buffer size.
9064             // It is the size of two native sockaddr buffers with 16 extra bytes each.
9065             // The native sockaddr buffers vary by address family so must reference the current socket.
9066             m_AcceptAddressBufferCount = 2 * (m_CurrentSocket.m_RightEndPoint.Serialize().Size + 16);
9067             
9068             // If our caller specified a buffer (willing to get received data with the Accept) then
9069             // it needs to be large enough for the two special sockaddr buffers that AcceptEx requires.
9070             // Throw if that buffer is not large enough.  
9071             if(m_Buffer != null) {
9072             
9073                 // Caller specified a buffer - see if it is large enough
9074                 if(m_Count < m_AcceptAddressBufferCount) {
9075                     throw new ArgumentException(SR.GetString(SR.net_buffercounttoosmall, "Count"));
9076                 }
9077                 // Buffer is already pinned.
9078             
9079             } else {
9080             
9081                 // Caller didn't specify a buffer so use an internal one.
9082                 // See if current internal one is big enough, otherwise create a new one.
9083                 if(m_AcceptBuffer == null || m_AcceptBuffer.Length < m_AcceptAddressBufferCount) {
9084                     m_AcceptBuffer = new byte[m_AcceptAddressBufferCount];
9085                 }
9086                 CheckPinSingleBuffer(false);
9087             }
9088         }
9089
9090         internal void StartOperationConnect() {
9091             // Remember the operation type.
9092             m_CompletedOperation = SocketAsyncOperation.Connect;
9093             m_MultipleConnect = null;
9094             m_ConnectSocket = null;
9095             
9096             // ConnectEx uses a sockaddr buffer containing he remote address to which to connect.
9097             // It can also optionally take a single buffer of data to send after the connection is complete.
9098             //
9099             // The sockaddr is pinned with a GCHandle to avoid having to use the object array form of UnsafePack.
9100             // The optional buffer is pinned using the Overlapped.UnsafePack method that takes a single object to pin.
9101
9102             PinSocketAddressBuffer();
9103             CheckPinNoBuffer();
9104         }
9105
9106         internal void StartOperationWrapperConnect(MultipleConnectAsync args) {
9107             m_CompletedOperation = SocketAsyncOperation.Connect;
9108             m_MultipleConnect = args;
9109             m_ConnectSocket = null;
9110         }
9111
9112         internal void CancelConnectAsync() {
9113             if (m_Operating == InProgress && m_CompletedOperation == SocketAsyncOperation.Connect) {
9114
9115                 if (m_MultipleConnect != null) {
9116                     // if a multiple connect is in progress, abort it
9117                     m_MultipleConnect.Cancel();
9118                 }
9119                 else {
9120                     // otherwise we're doing a normal ConnectAsync - cancel it by closing the socket
9121                     // m_CurrentSocket will only be null if m_MultipleConnect was set, so we don't have to check
9122                     GlobalLog.Assert(m_CurrentSocket != null, "SocketAsyncEventArgs::CancelConnectAsync - CurrentSocket and MultipleConnect both null!");
9123                     m_CurrentSocket.Close();
9124                 }
9125             }
9126         }
9127         
9128         internal void StartOperationDisconnect() {
9129             // Remember the operation type.
9130             m_CompletedOperation = SocketAsyncOperation.Disconnect;
9131             CheckPinNoBuffer();
9132         }
9133
9134         internal void StartOperationReceive() {
9135             // Remember the operation type.
9136             m_CompletedOperation = SocketAsyncOperation.Receive;
9137
9138             // WWSARecv uses a WSABuffer array describing buffers of data to send.
9139             // Single and multiple buffers are handled differently so as to optimize
9140             // performance for the more common single buffer case.  
9141             // For a single buffer:
9142             //   The Overlapped.UnsafePack method is used that takes a single object to pin.
9143             //   A single WSABuffer that pre-exists in SocketAsyncEventArgs is used.
9144             // For multiple buffers:
9145             //   The Overlapped.UnsafePack method is used that takes an array of objects to pin.
9146             //   An array to reference the multiple buffer is allocated.
9147             //   An array of WSABuffer descriptors is allocated.
9148         }
9149
9150         internal void StartOperationReceiveFrom() {
9151             // Remember the operation type.
9152             m_CompletedOperation = SocketAsyncOperation.ReceiveFrom;
9153
9154             // WSARecvFrom uses e a WSABuffer array describing buffers in which to 
9155             // receive data and from which to send data respectively. Single and multiple buffers
9156             // are handled differently so as to optimize performance for the more common single buffer case.
9157             // For a single buffer:
9158             //   The Overlapped.UnsafePack method is used that takes a single object to pin.
9159             //   A single WSABuffer that pre-exists in SocketAsyncEventArgs is used.
9160             // For multiple buffers:
9161             //   The Overlapped.UnsafePack method is used that takes an array of objects to pin.
9162             //   An array to reference the multiple buffer is allocated.
9163             //   An array of WSABuffer descriptors is allocated.
9164             // WSARecvFrom and WSASendTo also uses a sockaddr buffer in which to store the address from which the data was received.
9165             // The sockaddr is pinned with a GCHandle to avoid having to use the object array form of UnsafePack.
9166             PinSocketAddressBuffer();
9167         }
9168         
9169         internal void StartOperationReceiveMessageFrom() {
9170             // Remember the operation type.
9171             m_CompletedOperation = SocketAsyncOperation.ReceiveMessageFrom;
9172
9173             // WSARecvMsg uses a WSAMsg descriptor.
9174             // The WSAMsg buffer is pinned with a GCHandle to avoid complicating the use of Overlapped.
9175             // WSAMsg contains a pointer to a sockaddr.  
9176             // The sockaddr is pinned with a GCHandle to avoid complicating the use of Overlapped.
9177             // WSAMsg contains a pointer to a WSABuffer array describing data buffers.
9178             // WSAMsg also contains a single WSABuffer describing a control buffer.
9179             // 
9180             PinSocketAddressBuffer();
9181             
9182             // Create and pin a WSAMessageBuffer if none already.
9183             if(m_WSAMessageBuffer == null) {
9184                 m_WSAMessageBuffer = new byte[s_WSAMsgSize];
9185                 m_WSAMessageBufferGCHandle = GCHandle.Alloc(m_WSAMessageBuffer, GCHandleType.Pinned);
9186                 m_PtrWSAMessageBuffer = Marshal.UnsafeAddrOfPinnedArrayElement(m_WSAMessageBuffer, 0);
9187             }
9188
9189             // Create and pin an appropriately sized control buffer if none already
9190             IPAddress ipAddress = (m_SocketAddress.Family == AddressFamily.InterNetworkV6
9191                 ? m_SocketAddress.GetIPAddress() : null);
9192             bool ipv4 = (m_CurrentSocket.AddressFamily == AddressFamily.InterNetwork
9193                 || (ipAddress != null && ipAddress.IsIPv4MappedToIPv6)); // DualMode
9194             bool ipv6 = m_CurrentSocket.AddressFamily == AddressFamily.InterNetworkV6;
9195
9196             if(ipv4 && (m_ControlBuffer == null || m_ControlBuffer.Length != s_ControlDataSize)) {
9197                 if(m_ControlBufferGCHandle.IsAllocated) {
9198                     m_ControlBufferGCHandle.Free();
9199                 }
9200                 m_ControlBuffer = new byte[s_ControlDataSize];
9201             } else if(ipv6 && (m_ControlBuffer == null || m_ControlBuffer.Length != s_ControlDataIPv6Size)) {
9202                 if(m_ControlBufferGCHandle.IsAllocated) {
9203                     m_ControlBufferGCHandle.Free();
9204                 }
9205                 m_ControlBuffer = new byte[s_ControlDataIPv6Size];
9206             }
9207             if(!m_ControlBufferGCHandle.IsAllocated) {
9208                 m_ControlBufferGCHandle = GCHandle.Alloc(m_ControlBuffer, GCHandleType.Pinned);
9209                 m_PtrControlBuffer = Marshal.UnsafeAddrOfPinnedArrayElement(m_ControlBuffer, 0);
9210             }
9211
9212             // If single buffer we need a pinned 1 element WSABuffer.
9213             if(m_Buffer != null) {
9214                 if(m_WSARecvMsgWSABufferArray == null) {
9215                     m_WSARecvMsgWSABufferArray = new WSABuffer[1];
9216                 }
9217                 m_WSARecvMsgWSABufferArray[0].Pointer = m_PtrSingleBuffer;
9218                 m_WSARecvMsgWSABufferArray[0].Length = m_Count;
9219                 m_WSARecvMsgWSABufferArrayGCHandle = GCHandle.Alloc(m_WSARecvMsgWSABufferArray, GCHandleType.Pinned);
9220                 m_PtrWSARecvMsgWSABufferArray = Marshal.UnsafeAddrOfPinnedArrayElement(m_WSARecvMsgWSABufferArray, 0);
9221             } else {
9222                 // just pin the multi-buffer WSABuffer
9223                 m_WSARecvMsgWSABufferArrayGCHandle = GCHandle.Alloc(m_WSABufferArray, GCHandleType.Pinned);
9224                 m_PtrWSARecvMsgWSABufferArray = Marshal.UnsafeAddrOfPinnedArrayElement(m_WSABufferArray, 0);
9225             }
9226
9227             // Fill in WSAMessageBuffer
9228             unsafe {
9229                 UnsafeNclNativeMethods.OSSOCK.WSAMsg* pMessage = (UnsafeNclNativeMethods.OSSOCK.WSAMsg*)m_PtrWSAMessageBuffer;;
9230                 pMessage->socketAddress = m_PtrSocketAddressBuffer;
9231                 pMessage->addressLength = (uint)m_SocketAddress.Size;
9232                 pMessage->buffers = m_PtrWSARecvMsgWSABufferArray;
9233                 if(m_Buffer != null) {
9234                     pMessage->count = (uint)1;
9235                 } else {
9236                     pMessage->count = (uint)m_WSABufferArray.Length;
9237                 }
9238                 if(m_ControlBuffer != null) {
9239                     pMessage->controlBuffer.Pointer = m_PtrControlBuffer;
9240                     pMessage->controlBuffer.Length = m_ControlBuffer.Length;
9241                 }
9242                 pMessage->flags = m_SocketFlags;
9243             }
9244         }
9245         
9246         internal void StartOperationSend() {
9247             // Remember the operation type.
9248             m_CompletedOperation = SocketAsyncOperation.Send;
9249             
9250             // WSASend uses a WSABuffer array describing buffers of data to send.
9251             // Single and multiple buffers are handled differently so as to optimize
9252             // performance for the more common single buffer case.  
9253             // For a single buffer:
9254             //   The Overlapped.UnsafePack method is used that takes a single object to pin.
9255             //   A single WSABuffer that pre-exists in SocketAsyncEventArgs is used.
9256             // For multiple buffers:
9257             //   The Overlapped.UnsafePack method is used that takes an array of objects to pin.
9258             //   An array to reference the multiple buffer is allocated.
9259             //   An array of WSABuffer descriptors is allocated.
9260         }
9261
9262         internal void StartOperationSendPackets() {
9263             // Remember the operation type.
9264             m_CompletedOperation = SocketAsyncOperation.SendPackets;
9265
9266             // Prevent mutithreaded manipulation of the list.
9267             if (m_SendPacketsElements != null) {
9268                 m_SendPacketsElementsInternal = (SendPacketsElement[])m_SendPacketsElements.Clone();
9269             }
9270
9271             // TransmitPackets uses an array of TRANSMIT_PACKET_ELEMENT structs as
9272             // descriptors for buffers and files to be sent.  It also takes a send size
9273             // and some flags.  The TRANSMIT_PACKET_ELEMENT for a file contains a native file handle.
9274             // This function basically opens the files to get the file handles, pins down any buffers
9275             // specified and builds the native TRANSMIT_PACKET_ELEMENT array that will be passed
9276             // to TransmitPackets.
9277             
9278             // Scan the elements to count files and buffers
9279             m_SendPacketsElementsFileCount = 0;
9280             m_SendPacketsElementsBufferCount = 0;
9281             foreach (SendPacketsElement spe in m_SendPacketsElementsInternal) {
9282                 if(spe != null) {
9283                     if(spe.m_FilePath != null) {
9284                         m_SendPacketsElementsFileCount++;
9285                     }
9286                     if(spe.m_Buffer != null && spe.m_Count > 0) {
9287                         m_SendPacketsElementsBufferCount++;
9288                     }
9289                 }
9290             }
9291
9292             // Attempt to open the files if any
9293             if(m_SendPacketsElementsFileCount > 0) {
9294
9295                 // Create arrays for streams and handles
9296                 m_SendPacketsFileStreams = new FileStream[m_SendPacketsElementsFileCount];
9297                 m_SendPacketsFileHandles = new SafeHandle[m_SendPacketsElementsFileCount];
9298
9299                 // Loop through the elements attempting to open each files and get its handle
9300                 int index = 0;
9301                 foreach(SendPacketsElement spe in m_SendPacketsElementsInternal) {
9302                     if(spe != null && spe.m_FilePath != null) {
9303                         Exception fileStreamException = null;
9304                         try {
9305                             // Create a FileStream to open the file
9306                             m_SendPacketsFileStreams[index] = 
9307                                 new FileStream(spe.m_FilePath,FileMode.Open,FileAccess.Read,FileShare.Read);
9308                         }
9309                         catch (Exception ex) {
9310                             // Save the exception to throw after closing any previous successful file opens
9311                             fileStreamException = ex;                            
9312                         }
9313                         if (fileStreamException != null) {
9314                             // Got exception opening a file - do some cleanup then throw
9315                             for(int i = 0; i < m_SendPacketsElementsFileCount; i++) {
9316                                 // Dereference handles
9317                                 m_SendPacketsFileHandles[i] = null;
9318                                 // Close any open streams
9319                                 if(m_SendPacketsFileStreams[i] != null) {
9320                                     m_SendPacketsFileStreams[i].Close();
9321                                     m_SendPacketsFileStreams[i] = null;
9322                                 }
9323                             }
9324                             throw fileStreamException;
9325                         }
9326                         // Get the file handle from the stream
9327                         ExceptionHelper.UnmanagedPermission.Assert();
9328                         try {
9329                             m_SendPacketsFileHandles[index] = m_SendPacketsFileStreams[index].SafeFileHandle;
9330                         }
9331                         finally {
9332                             SecurityPermission.RevertAssert();
9333                         }
9334                         index++;
9335                     }
9336                 }
9337             }
9338
9339             CheckPinSendPackets();
9340         }
9341         
9342         internal void StartOperationSendTo() {
9343             // Remember the operation type.
9344             m_CompletedOperation = SocketAsyncOperation.SendTo;
9345             
9346             // WSASendTo uses a WSABuffer array describing buffers in which to 
9347             // receive data and from which to send data respectively. Single and multiple buffers
9348             // are handled differently so as to optimize performance for the more common single buffer case.
9349             // For a single buffer:
9350             //   The Overlapped.UnsafePack method is used that takes a single object to pin.
9351             //   A single WSABuffer that pre-exists in SocketAsyncEventArgs is used.
9352             // For multiple buffers:
9353             //   The Overlapped.UnsafePack method is used that takes an array of objects to pin.
9354             //   An array to reference the multiple buffer is allocated.
9355             //   An array of WSABuffer descriptors is allocated.
9356             // WSARecvFrom and WSASendTo also uses a sockaddr buffer in which to store the address from which the data was received.
9357             // The sockaddr is pinned with a GCHandle to avoid having to use the object array form of UnsafePack.
9358             PinSocketAddressBuffer();
9359         }
9360
9361         // Method to ensure Overlapped object exists for operations that need no data buffer.
9362         private void CheckPinNoBuffer() {
9363
9364             if (m_PinState == PinState.None) {
9365                 SetupOverlappedSingle(true);
9366             }
9367         }
9368
9369         // Method to maintain pinned state of single buffer
9370         private void CheckPinSingleBuffer(bool pinUsersBuffer) {
9371
9372             if (pinUsersBuffer) {
9373
9374                 // Using app supplied buffer.
9375
9376                 if (m_Buffer == null) {
9377                     
9378                     // No user buffer is set so unpin any existing single buffer pinning.
9379                     if(m_PinState == PinState.SingleBuffer) {
9380                         FreeOverlapped(false);
9381                     }
9382                     
9383                 } else {
9384                 
9385                     if(m_PinState == PinState.SingleBuffer && m_PinnedSingleBuffer == m_Buffer) {
9386                         // This buffer is already pinned - update if offset or count has changed.
9387                         if (m_Offset != m_PinnedSingleBufferOffset) {
9388                             m_PinnedSingleBufferOffset = m_Offset;
9389                             m_PtrSingleBuffer = Marshal.UnsafeAddrOfPinnedArrayElement(m_Buffer, m_Offset);
9390                             m_WSABuffer.Pointer = m_PtrSingleBuffer;
9391                         }
9392                         if (m_Count != m_PinnedSingleBufferCount) {
9393                             m_PinnedSingleBufferCount = m_Count;
9394                             m_WSABuffer.Length = m_Count;
9395                         }
9396                     } else {
9397                         FreeOverlapped(false);
9398                         SetupOverlappedSingle(true);
9399                     }
9400                 }
9401             } else {
9402
9403                 // Using internal accept buffer.
9404             
9405                 if(!(m_PinState == PinState.SingleAcceptBuffer) || !(m_PinnedSingleBuffer == m_AcceptBuffer)) {
9406
9407                     // Not already pinned - so pin it.
9408                     FreeOverlapped(false);
9409                     SetupOverlappedSingle(false);
9410                 }
9411             }
9412         }
9413
9414         // Method to ensure Overlapped object exists with appropriate multiple buffers pinned.
9415         private void CheckPinMultipleBuffers() {
9416
9417             if (m_BufferList == null) {
9418
9419                 // No buffer list is set so unpin any existing multiple buffer pinning.
9420
9421                 if(m_PinState == PinState.MultipleBuffer) {
9422                     FreeOverlapped(false);
9423                 }
9424             } else {
9425
9426                 if(!(m_PinState == PinState.MultipleBuffer) || m_BufferListChanged) {
9427                     // Need to setup new Overlapped
9428                     m_BufferListChanged = false;  
9429                     FreeOverlapped(false);
9430                     try
9431                     {
9432                         SetupOverlappedMultiple();
9433                     }
9434                     catch (Exception)
9435                     {
9436                         FreeOverlapped(false);
9437                         throw;
9438                     }
9439                 }
9440             }
9441         }
9442         
9443         // Method to ensure Overlapped object exists with appropriate buffers pinned.
9444         private void CheckPinSendPackets() {
9445             if(m_PinState != PinState.None) {
9446                 FreeOverlapped(false);
9447             }
9448             SetupOverlappedSendPackets();
9449         }
9450
9451         // Method to ensure appropriate SocketAddress buffer is pinned.
9452         private void PinSocketAddressBuffer() {
9453             // Check if already pinned.
9454             if(m_PinnedSocketAddress == m_SocketAddress) {
9455                 return;
9456             }
9457
9458             // Unpin any existing.
9459             if(m_SocketAddressGCHandle.IsAllocated) {
9460                 m_SocketAddressGCHandle.Free();
9461             }
9462
9463             // Pin down the new one.
9464             m_SocketAddressGCHandle = GCHandle.Alloc(m_SocketAddress.m_Buffer, GCHandleType.Pinned);
9465             m_SocketAddress.CopyAddressSizeIntoBuffer();
9466             m_PtrSocketAddressBuffer = Marshal.UnsafeAddrOfPinnedArrayElement(m_SocketAddress.m_Buffer, 0);
9467             m_PtrSocketAddressBufferSize = Marshal.UnsafeAddrOfPinnedArrayElement(m_SocketAddress.m_Buffer, m_SocketAddress.GetAddressSizeOffset());
9468             m_PinnedSocketAddress = m_SocketAddress;
9469         }
9470
9471         // Method to clean up any existing Overlapped object and related state variables.
9472         private void FreeOverlapped(bool checkForShutdown) {
9473             if (!checkForShutdown || !NclUtilities.HasShutdownStarted) {
9474
9475                 // Free the overlapped object
9476
9477                 if(m_PtrNativeOverlapped != null && !m_PtrNativeOverlapped.IsInvalid) {
9478                     m_PtrNativeOverlapped.Dispose();
9479                     m_PtrNativeOverlapped = null;
9480                     m_Overlapped = null;
9481                     m_PinState = PinState.None;
9482                     m_PinnedAcceptBuffer = null;
9483                     m_PinnedSingleBuffer = null;
9484                     m_PinnedSingleBufferOffset = 0;
9485                     m_PinnedSingleBufferCount = 0;
9486                 }
9487
9488                 // Free any alloc'd GCHandles
9489                 
9490                 if(m_SocketAddressGCHandle.IsAllocated) {
9491                     m_SocketAddressGCHandle.Free();
9492                 }
9493                 if(m_WSAMessageBufferGCHandle.IsAllocated) {
9494                     m_WSAMessageBufferGCHandle.Free();
9495                 }
9496                 if(m_WSARecvMsgWSABufferArrayGCHandle.IsAllocated) {
9497                     m_WSARecvMsgWSABufferArrayGCHandle.Free();
9498                 }
9499                 if(m_ControlBufferGCHandle.IsAllocated) {
9500                     m_ControlBufferGCHandle.Free();
9501                 }
9502             }
9503         }
9504
9505
9506         // Method to setup an Overlapped object with either m_Buffer or m_AcceptBuffer pinned.        
9507         unsafe private void SetupOverlappedSingle(bool pinSingleBuffer) {
9508             
9509             // Alloc new Overlapped.
9510             m_Overlapped = new Overlapped();
9511
9512             // Pin buffer, get native pointers, and fill in WSABuffer descriptor.
9513             if(pinSingleBuffer) {
9514                 if(m_Buffer != null) {
9515 #if SOCKETTHREADPOOL
9516                     m_Overlapped.AsyncResult = new DummyAsyncResult(CompletionPortCallback);
9517                     m_PtrNativeOverlapped = new SafeNativeOverlapped(m_Overlapped.UnsafePack(null, m_Buffer));
9518 #else
9519                     m_PtrNativeOverlapped = new SafeNativeOverlapped(m_Overlapped.UnsafePack(CompletionPortCallback, m_Buffer));
9520 #endif
9521                     m_PinnedSingleBuffer = m_Buffer;
9522                     m_PinnedSingleBufferOffset = m_Offset;
9523                     m_PinnedSingleBufferCount = m_Count;
9524                     m_PtrSingleBuffer = Marshal.UnsafeAddrOfPinnedArrayElement(m_Buffer, m_Offset);
9525                     m_PtrAcceptBuffer = IntPtr.Zero;
9526                     m_WSABuffer.Pointer = m_PtrSingleBuffer;
9527                     m_WSABuffer.Length = m_Count;
9528                     m_PinState = PinState.SingleBuffer;
9529                 } else {
9530 #if SOCKETTHREADPOOL
9531                     m_Overlapped.AsyncResult = new DummyAsyncResult(CompletionPortCallback);
9532                     m_PtrNativeOverlapped = new SafeNativeOverlapped(m_Overlapped.UnsafePack(null, null));
9533 #else
9534                     m_PtrNativeOverlapped = new SafeNativeOverlapped(m_Overlapped.UnsafePack(CompletionPortCallback, null));
9535 #endif
9536                     m_PinnedSingleBuffer = null;
9537                     m_PinnedSingleBufferOffset = 0;
9538                     m_PinnedSingleBufferCount = 0;
9539                     m_PtrSingleBuffer = IntPtr.Zero;
9540                     m_PtrAcceptBuffer = IntPtr.Zero;
9541                     m_WSABuffer.Pointer = m_PtrSingleBuffer;
9542                     m_WSABuffer.Length = m_Count;
9543                     m_PinState = PinState.NoBuffer;
9544                 }
9545             } else {
9546 #if SOCKETTHREADPOOL
9547                 m_Overlapped.AsyncResult = new DummyAsyncResult(CompletionPortCallback);
9548                 m_PtrNativeOverlapped = new SafeNativeOverlapped(m_Overlapped.UnsafePack(null, m_AcceptBuffer));
9549 #else
9550                 m_PtrNativeOverlapped = new SafeNativeOverlapped(m_Overlapped.UnsafePack(CompletionPortCallback, m_AcceptBuffer));
9551 #endif
9552                 m_PinnedAcceptBuffer = m_AcceptBuffer;
9553                 m_PtrAcceptBuffer = Marshal.UnsafeAddrOfPinnedArrayElement(m_AcceptBuffer, 0);
9554                 m_PtrSingleBuffer = IntPtr.Zero;
9555                 m_PinState = PinState.SingleAcceptBuffer;
9556             }
9557         }
9558
9559         // Method to setup an Overlapped object with with multiple buffers pinned.        
9560         unsafe private void SetupOverlappedMultiple() {
9561             
9562             ArraySegment<byte>[] tempList = new ArraySegment<byte>[m_BufferList.Count];
9563             m_BufferList.CopyTo(tempList, 0);
9564
9565             // Alloc new Overlapped.
9566             m_Overlapped = new Overlapped();
9567
9568             // Number of things to pin is number of buffers.
9569             // Ensure we have properly sized object array.
9570             if(m_ObjectsToPin == null || (m_ObjectsToPin.Length != tempList.Length)) {
9571                 m_ObjectsToPin = new object[tempList.Length];
9572             }
9573
9574             // Fill in object array.
9575             for(int i = 0; i < (tempList.Length); i++) {
9576                 m_ObjectsToPin[i] = tempList[i].Array;
9577             }
9578
9579             if(m_WSABufferArray == null || m_WSABufferArray.Length != tempList.Length) {
9580                 m_WSABufferArray = new WSABuffer[tempList.Length];
9581             }
9582
9583             // Pin buffers and fill in WSABuffer descriptor pointers and lengths
9584 #if SOCKETTHREADPOOL
9585             m_Overlapped.AsyncResult = new DummyAsyncResult(CompletionPortCallback);
9586             m_PtrNativeOverlapped = new SafeNativeOverlapped(m_Overlapped.UnsafePack(null, m_ObjectsToPin));
9587 #else
9588             m_PtrNativeOverlapped = new SafeNativeOverlapped(m_Overlapped.UnsafePack(CompletionPortCallback, m_ObjectsToPin));
9589 #endif
9590             for(int i = 0; i < tempList.Length; i++) {
9591                 ArraySegment<byte> localCopy = tempList[i];
9592                 ValidationHelper.ValidateSegment(localCopy);
9593                 m_WSABufferArray[i].Pointer = Marshal.UnsafeAddrOfPinnedArrayElement(localCopy.Array, localCopy.Offset);
9594                 m_WSABufferArray[i].Length = localCopy.Count;
9595             }
9596             m_PinState = PinState.MultipleBuffer;
9597         }
9598
9599         // Method to setup an Overlapped object for SendPacketsAsync.        
9600         unsafe private void SetupOverlappedSendPackets() {
9601
9602             int index;
9603
9604             // Alloc new Overlapped.
9605             m_Overlapped = new Overlapped();
9606
9607             // Alloc native descriptor.
9608             m_SendPacketsDescriptor = 
9609                 new UnsafeNclNativeMethods.OSSOCK.TransmitPacketsElement[m_SendPacketsElementsFileCount + m_SendPacketsElementsBufferCount];
9610
9611             // Number of things to pin is number of buffers + 1 (native descriptor).
9612             // Ensure we have properly sized object array.
9613             if(m_ObjectsToPin == null || (m_ObjectsToPin.Length != m_SendPacketsElementsBufferCount + 1)) {
9614                 m_ObjectsToPin = new object[m_SendPacketsElementsBufferCount + 1];
9615             }
9616
9617             // Fill in objects to pin array. Native descriptor buffer first and then user specified buffers.
9618             m_ObjectsToPin[0] = m_SendPacketsDescriptor;
9619             index = 1;
9620             foreach(SendPacketsElement spe in m_SendPacketsElementsInternal) {                
9621                 if(spe != null && spe.m_Buffer != null && spe.m_Count > 0) {
9622                     m_ObjectsToPin[index] = spe.m_Buffer;
9623                     index++;
9624                 }
9625             }
9626
9627             // Pin buffers
9628 #if SOCKETTHREADPOOL
9629             m_Overlapped.AsyncResult = new DummyAsyncResult(CompletionPortCallback);
9630             m_PtrNativeOverlapped = new SafeNativeOverlapped(m_Overlapped.UnsafePack(null, m_ObjectsToPin));
9631 #else
9632             m_PtrNativeOverlapped = new SafeNativeOverlapped(m_Overlapped.UnsafePack(CompletionPortCallback, m_ObjectsToPin));
9633 #endif
9634
9635             // Get pointer to native descriptor.
9636             m_PtrSendPacketsDescriptor = Marshal.UnsafeAddrOfPinnedArrayElement(m_SendPacketsDescriptor, 0);
9637             
9638             // Fill in native descriptor.
9639             int descriptorIndex = 0;
9640             int fileIndex = 0;
9641             foreach(SendPacketsElement spe in m_SendPacketsElementsInternal) {
9642                 if (spe != null) {
9643                     if(spe.m_Buffer != null && spe.m_Count > 0) {
9644                         // a buffer
9645                         m_SendPacketsDescriptor[descriptorIndex].buffer = Marshal.UnsafeAddrOfPinnedArrayElement(spe.m_Buffer, spe.m_Offset);
9646                         m_SendPacketsDescriptor[descriptorIndex].length = (uint)spe.m_Count;
9647                         m_SendPacketsDescriptor[descriptorIndex].flags = spe.m_Flags;
9648                         descriptorIndex++;
9649                     } else if (spe.m_FilePath != null) {
9650                         // a file
9651                         m_SendPacketsDescriptor[descriptorIndex].fileHandle = m_SendPacketsFileHandles[fileIndex].DangerousGetHandle();
9652                         m_SendPacketsDescriptor[descriptorIndex].fileOffset = spe.m_Offset;
9653                         m_SendPacketsDescriptor[descriptorIndex].length = (uint)spe.m_Count;
9654                         m_SendPacketsDescriptor[descriptorIndex].flags = spe.m_Flags;
9655                         fileIndex++;
9656                         descriptorIndex++;
9657                     }
9658                 }
9659             }
9660
9661             m_PinState = PinState.SendPackets;
9662         }
9663         
9664         internal void LogBuffer(int size) {
9665             switch(m_PinState) {
9666                 case PinState.SingleAcceptBuffer:
9667                     Logging.Dump(Logging.Sockets, m_CurrentSocket, "FinishOperation(" + m_CompletedOperation + "Async)", m_AcceptBuffer, 0, size);
9668                     break;                    
9669                 case PinState.SingleBuffer:
9670                     Logging.Dump(Logging.Sockets, m_CurrentSocket, "FinishOperation(" + m_CompletedOperation + "Async)", m_Buffer, m_Offset, size);
9671                     break;
9672                 case PinState.MultipleBuffer:
9673                     foreach(WSABuffer wsaBuffer in m_WSABufferArray) {
9674                         Logging.Dump(Logging.Sockets, m_CurrentSocket, "FinishOperation(" + m_CompletedOperation + "Async)", wsaBuffer.Pointer, Math.Min(wsaBuffer.Length, size));
9675                         if((size -= wsaBuffer.Length) <= 0)
9676                             break;
9677                     }
9678                     break;
9679                 default:
9680                     break;
9681             } 
9682         }
9683         
9684         internal void LogSendPacketsBuffers(int size) {
9685             foreach(SendPacketsElement spe in m_SendPacketsElementsInternal) {
9686                 if (spe != null) {
9687                     if(spe.m_Buffer != null && spe.m_Count > 0) {
9688                         // a buffer
9689                         Logging.Dump(Logging.Sockets, m_CurrentSocket, "FinishOperation(" + m_CompletedOperation + "Async)Buffer", spe.m_Buffer, spe.m_Offset, Math.Min(spe.m_Count, size));
9690                     } else if(spe.m_FilePath != null) {
9691                         // a file
9692                         Logging.PrintInfo(Logging.Sockets, m_CurrentSocket, "FinishOperation(" + m_CompletedOperation + "Async)", SR.GetString(SR.net_log_socket_not_logged_file, spe.m_FilePath));
9693                     }
9694                 }
9695             }
9696         }
9697
9698         internal void UpdatePerfCounters(int size, bool sendOp) {
9699 #if !FEATURE_PAL // perfcounter
9700             if(sendOp) {
9701                 NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketBytesSent, size);
9702                 if(m_CurrentSocket.Transport == TransportType.Udp) {
9703                     NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketDatagramsSent);
9704                 }
9705             } else {
9706                 NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketBytesReceived, size);
9707                 if(m_CurrentSocket.Transport == TransportType.Udp) {
9708                     NetworkingPerfCounters.Instance.Increment(NetworkingPerfCounterName.SocketDatagramsReceived);
9709                 }
9710             }
9711 #endif
9712         }
9713
9714         internal void FinishOperationSyncFailure(SocketError socketError, int bytesTransferred, SocketFlags flags) {
9715             SetResults(socketError, bytesTransferred, flags);
9716
9717             // this will be null if we're doing a static ConnectAsync to a DnsEndPoint with AddressFamily.Unspecified;
9718             // the attempt socket will be closed anyways, so not updating the state is OK
9719             if (m_CurrentSocket != null) {
9720                 m_CurrentSocket.UpdateStatusAfterSocketError(socketError);
9721             }
9722
9723             Complete();
9724         }
9725
9726         internal void FinishConnectByNameSyncFailure(Exception exception, int bytesTransferred, SocketFlags flags) {
9727             SetResults(exception, bytesTransferred, flags);
9728
9729             if (m_CurrentSocket != null) {
9730                 m_CurrentSocket.UpdateStatusAfterSocketError(m_SocketError);
9731             }
9732
9733             Complete();
9734         }
9735
9736         internal void FinishOperationAsyncFailure(SocketError socketError, int bytesTransferred, SocketFlags flags) {
9737             SetResults(socketError, bytesTransferred, flags);
9738
9739             // this will be null if we're doing a static ConnectAsync to a DnsEndPoint with AddressFamily.Unspecified;
9740             // the attempt socket will be closed anyways, so not updating the state is OK
9741             if (m_CurrentSocket != null) {
9742                 m_CurrentSocket.UpdateStatusAfterSocketError(socketError);
9743             }
9744
9745             Complete();
9746             if(m_Context == null) {
9747                 OnCompleted(this);
9748             } else {
9749                 ExecutionContext.Run(m_ContextCopy, m_ExecutionCallback, null);
9750             }
9751         }
9752
9753         internal void FinishOperationAsyncFailure(Exception exception, int bytesTransferred, SocketFlags flags) {
9754             SetResults(exception, bytesTransferred, flags);
9755
9756             if (m_CurrentSocket != null) {
9757                 m_CurrentSocket.UpdateStatusAfterSocketError(m_SocketError);
9758             }
9759             Complete();
9760             if (m_Context == null) {
9761                 OnCompleted(this);
9762             } else {
9763               ExecutionContext.Run(m_ContextCopy, m_ExecutionCallback, null);
9764             }
9765         }
9766
9767         internal void FinishWrapperConnectSuccess(Socket connectSocket, int bytesTransferred, SocketFlags flags) {
9768
9769             SetResults(SocketError.Success, bytesTransferred, flags);
9770             m_CurrentSocket = connectSocket;
9771             m_ConnectSocket = connectSocket;
9772
9773             // Complete the operation and raise the event
9774             Complete();
9775             if (m_ContextCopy == null) {
9776                 OnCompleted(this);
9777             } else {
9778                 ExecutionContext.Run(m_ContextCopy, m_ExecutionCallback, null);
9779             }
9780         }
9781
9782         internal void FinishOperationSuccess(SocketError socketError, int bytesTransferred, SocketFlags flags) {
9783
9784             SetResults(socketError, bytesTransferred, flags);
9785
9786             switch(m_CompletedOperation) {
9787                 
9788                 case SocketAsyncOperation.Accept:
9789
9790
9791                     if (bytesTransferred > 0) {
9792                         // Log and Perf counters.
9793                         if (s_LoggingEnabled) LogBuffer(bytesTransferred);
9794                         if (Socket.s_PerfCountersEnabled) UpdatePerfCounters(bytesTransferred, false);
9795                     }
9796
9797                     // Get the endpoint.
9798                     SocketAddress remoteSocketAddress = m_CurrentSocket.m_RightEndPoint.Serialize();
9799
9800                     IntPtr localAddr;
9801                     int localAddrLength;
9802                     IntPtr remoteAddr;
9803
9804                     try {
9805                         m_CurrentSocket.GetAcceptExSockaddrs(
9806                             m_PtrSingleBuffer != IntPtr.Zero ? m_PtrSingleBuffer : m_PtrAcceptBuffer,
9807                             m_Count != 0 ? m_Count - m_AcceptAddressBufferCount : 0,
9808                             m_AcceptAddressBufferCount / 2,
9809                             m_AcceptAddressBufferCount / 2,
9810                             out localAddr,
9811                             out localAddrLength,
9812                             out remoteAddr,
9813                             out remoteSocketAddress.m_Size
9814                             );
9815                         Marshal.Copy(remoteAddr, remoteSocketAddress.m_Buffer, 0, remoteSocketAddress.m_Size);
9816
9817                         // Set the socket context.
9818                         IntPtr handle = m_CurrentSocket.SafeHandle.DangerousGetHandle();
9819
9820                         socketError = UnsafeNclNativeMethods.OSSOCK.setsockopt(
9821                             m_AcceptSocket.SafeHandle,
9822                             SocketOptionLevel.Socket,
9823                             SocketOptionName.UpdateAcceptContext,
9824                             ref handle,
9825                             Marshal.SizeOf(handle));
9826
9827                         if(socketError == SocketError.SocketError) {
9828                             socketError = (SocketError)Marshal.GetLastWin32Error();
9829                         }
9830                     }
9831                     catch(ObjectDisposedException) {
9832                         socketError = SocketError.OperationAborted;
9833                     }
9834
9835                     if(socketError == SocketError.Success) {
9836                         m_AcceptSocket = m_CurrentSocket.UpdateAcceptSocket(m_AcceptSocket, m_CurrentSocket.m_RightEndPoint.Create(remoteSocketAddress), false);
9837
9838                         if (s_LoggingEnabled) Logging.PrintInfo(Logging.Sockets, m_AcceptSocket, 
9839                             SR.GetString(SR.net_log_socket_accepted, m_AcceptSocket.RemoteEndPoint, m_AcceptSocket.LocalEndPoint));
9840                     } else {
9841                         SetResults(socketError, bytesTransferred, SocketFlags.None);
9842                         m_AcceptSocket = null;
9843                     }
9844                     break;
9845
9846                 case SocketAsyncOperation.Connect:
9847
9848                     if (bytesTransferred > 0) {
9849                         // Log and Perf counters.
9850                         if (s_LoggingEnabled) LogBuffer(bytesTransferred);
9851                         if (Socket.s_PerfCountersEnabled) UpdatePerfCounters(bytesTransferred, true);
9852                     }
9853
9854                     // Update the socket context.
9855                     try {
9856                         socketError = UnsafeNclNativeMethods.OSSOCK.setsockopt(
9857                             m_CurrentSocket.SafeHandle,
9858                             SocketOptionLevel.Socket,
9859                             SocketOptionName.UpdateConnectContext,
9860                             null,
9861                             0);
9862                         if(socketError == SocketError.SocketError) {
9863                             socketError = (SocketError)Marshal.GetLastWin32Error();
9864                         }
9865                     }
9866                     catch(ObjectDisposedException) {
9867                         socketError = SocketError.OperationAborted;
9868                     }
9869
9870                     // Mark socket connected.
9871                     if(socketError == SocketError.Success) {
9872                         if (s_LoggingEnabled) Logging.PrintInfo(Logging.Sockets, m_CurrentSocket, 
9873                             SR.GetString(SR.net_log_socket_connected, m_CurrentSocket.LocalEndPoint, m_CurrentSocket.RemoteEndPoint));
9874
9875                         m_CurrentSocket.SetToConnected();
9876                         m_ConnectSocket = m_CurrentSocket;
9877                     }
9878                     break;
9879
9880                 case SocketAsyncOperation.Disconnect:
9881
9882                     m_CurrentSocket.SetToDisconnected();
9883                     m_CurrentSocket.m_RemoteEndPoint = null;
9884
9885                     break;
9886
9887                 case SocketAsyncOperation.Receive:
9888
9889                     if (bytesTransferred > 0) {
9890                         // Log and Perf counters.
9891                         if (s_LoggingEnabled) LogBuffer(bytesTransferred);
9892                         if (Socket.s_PerfCountersEnabled) UpdatePerfCounters(bytesTransferred, false);
9893                     }
9894                     break;
9895
9896                 case SocketAsyncOperation.ReceiveFrom:
9897
9898                     if (bytesTransferred > 0) {
9899                         // Log and Perf counters.
9900                         if (s_LoggingEnabled) LogBuffer(bytesTransferred);
9901                         if (Socket.s_PerfCountersEnabled) UpdatePerfCounters(bytesTransferred, false);
9902                     }
9903
9904                     // Deal with incoming address.
9905                     m_SocketAddress.SetSize(m_PtrSocketAddressBufferSize);
9906                     SocketAddress socketAddressOriginal = m_RemoteEndPoint.Serialize();
9907                     if(!socketAddressOriginal.Equals(m_SocketAddress)) {
9908                         try {
9909                             m_RemoteEndPoint = m_RemoteEndPoint.Create(m_SocketAddress);
9910                         }
9911                         catch {
9912                         }
9913                     }
9914                     break;
9915
9916                 case SocketAsyncOperation.ReceiveMessageFrom:
9917
9918                     if (bytesTransferred > 0) {
9919                         // Log and Perf counters.
9920                         if (s_LoggingEnabled) LogBuffer(bytesTransferred);
9921                         if (Socket.s_PerfCountersEnabled) UpdatePerfCounters(bytesTransferred, false);
9922                     }
9923
9924                     // Deal with incoming address.
9925                     m_SocketAddress.SetSize(m_PtrSocketAddressBufferSize);
9926                     socketAddressOriginal = m_RemoteEndPoint.Serialize();
9927                     if(!socketAddressOriginal.Equals(m_SocketAddress)) {
9928                         try {
9929                             m_RemoteEndPoint = m_RemoteEndPoint.Create(m_SocketAddress);
9930                         }
9931                         catch {
9932                         }
9933                     }
9934
9935                     // Extract the packet information.
9936                     unsafe {
9937                         IPAddress address = null;
9938                         UnsafeNclNativeMethods.OSSOCK.WSAMsg* PtrMessage = (UnsafeNclNativeMethods.OSSOCK.WSAMsg*)Marshal.UnsafeAddrOfPinnedArrayElement(m_WSAMessageBuffer, 0);
9939
9940                         //ipv4
9941                         if(m_ControlBuffer.Length == s_ControlDataSize) {
9942                             UnsafeNclNativeMethods.OSSOCK.ControlData controlData = (UnsafeNclNativeMethods.OSSOCK.ControlData)Marshal.PtrToStructure(PtrMessage->controlBuffer.Pointer, typeof(UnsafeNclNativeMethods.OSSOCK.ControlData));
9943                             if(controlData.length != UIntPtr.Zero) {
9944                                 address = new IPAddress((long)controlData.address);
9945                             }
9946                             m_ReceiveMessageFromPacketInfo = new IPPacketInformation(((address != null) ? address : IPAddress.None), (int)controlData.index);
9947                         }
9948                             //ipv6
9949                         else if(m_ControlBuffer.Length == s_ControlDataIPv6Size) {
9950                             UnsafeNclNativeMethods.OSSOCK.ControlDataIPv6 controlData = (UnsafeNclNativeMethods.OSSOCK.ControlDataIPv6)Marshal.PtrToStructure(PtrMessage->controlBuffer.Pointer, typeof(UnsafeNclNativeMethods.OSSOCK.ControlDataIPv6));
9951                             if(controlData.length != UIntPtr.Zero) {
9952                                 address = new IPAddress(controlData.address);
9953                             }
9954                             m_ReceiveMessageFromPacketInfo = new IPPacketInformation(((address != null) ? address : IPAddress.IPv6None), (int)controlData.index);
9955                         }
9956                             //other
9957                         else {
9958                             m_ReceiveMessageFromPacketInfo = new IPPacketInformation();
9959                         }
9960                     }
9961                     break;
9962
9963                 case SocketAsyncOperation.Send:
9964
9965                     if (bytesTransferred > 0) {
9966                         // Log and Perf counters.
9967                         if (s_LoggingEnabled) LogBuffer(bytesTransferred);
9968                         if (Socket.s_PerfCountersEnabled) UpdatePerfCounters(bytesTransferred, true);
9969                     }
9970                     break;
9971
9972                 case SocketAsyncOperation.SendPackets:
9973
9974                     if(bytesTransferred > 0) {
9975                         // Log and Perf counters.
9976                         if(s_LoggingEnabled) LogSendPacketsBuffers(bytesTransferred);
9977                         if(Socket.s_PerfCountersEnabled) UpdatePerfCounters(bytesTransferred, true);
9978                     }
9979
9980                     // Close the files if open
9981                     if (m_SendPacketsFileStreams != null) {
9982                         for(int i = 0; i < m_SendPacketsElementsFileCount; i++) {
9983                             // Dereference handles
9984                             m_SendPacketsFileHandles[i] = null;
9985                             // Close any open streams
9986                             if(m_SendPacketsFileStreams[i] != null) {
9987                                 m_SendPacketsFileStreams[i].Close();
9988                                 m_SendPacketsFileStreams[i] = null;
9989                             }
9990                         }
9991                     }
9992                     m_SendPacketsFileStreams = null;
9993                     m_SendPacketsFileHandles = null;
9994
9995                     break;
9996
9997                 case SocketAsyncOperation.SendTo:
9998
9999                     if (bytesTransferred > 0) {
10000                         // Log and Perf counters.
10001                         if (s_LoggingEnabled) LogBuffer(bytesTransferred);
10002                         if (Socket.s_PerfCountersEnabled) UpdatePerfCounters(bytesTransferred, true);
10003                     }
10004                     break;
10005
10006             }
10007
10008             if(socketError != SocketError.Success) {
10009                 // Asynchronous failure or something went wrong after async success.
10010                 SetResults(socketError, bytesTransferred, flags);
10011                 m_CurrentSocket.UpdateStatusAfterSocketError(socketError);
10012             }
10013
10014             // Complete the operation and raise completion event.
10015             Complete();
10016             if(m_ContextCopy == null) {
10017                 OnCompleted(this);
10018             } else {
10019                 ExecutionContext.Run(m_ContextCopy, m_ExecutionCallback, null);
10020             }
10021         }
10022
10023         private unsafe void CompletionPortCallback(uint errorCode, uint numBytes, NativeOverlapped* nativeOverlapped) {
10024 #if DEBUG
10025             GlobalLog.SetThreadSource(ThreadKinds.CompletionPort);
10026             using(GlobalLog.SetThreadKind(ThreadKinds.System)) {
10027 #endif
10028             SocketFlags socketFlags = SocketFlags.None;
10029             SocketError socketError = (SocketError)errorCode;
10030
10031             if(socketError == SocketError.Success) {
10032                 FinishOperationSuccess(socketError, (int)numBytes, socketFlags);
10033             } else {
10034                 if(socketError != SocketError.OperationAborted) {
10035                     if(m_CurrentSocket.CleanedUp) {
10036                         socketError = SocketError.OperationAborted;
10037                     } else {
10038                         try {
10039                             // This is the same NativeOverlapped* as we already have a SafeHandle for, re-use the orriginal.
10040                             Debug.Assert((IntPtr)nativeOverlapped == m_PtrNativeOverlapped.DangerousGetHandle(), "Handle mismatch");
10041
10042                             // The Async IO completed with a failure.
10043                             // here we need to call WSAGetOverlappedResult() just so Marshal.GetLastWin32Error() will return the correct error.
10044                             bool success = UnsafeNclNativeMethods.OSSOCK.WSAGetOverlappedResult(
10045                                 m_CurrentSocket.SafeHandle,
10046                                 m_PtrNativeOverlapped,
10047                                 out numBytes,
10048                                 false,
10049                                 out socketFlags);
10050                             socketError = (SocketError)Marshal.GetLastWin32Error();
10051                         }
10052                         catch {
10053                             // m_CurrentSocket.CleanedUp check above does not always work since this code is subject to race conditions
10054                             socketError = SocketError.OperationAborted;
10055                         }
10056                     }
10057                 }
10058                 FinishOperationAsyncFailure(socketError, (int)numBytes, socketFlags);
10059             }
10060 #if DEBUG
10061             }
10062 #endif
10063         }
10064     } // class SocketAsyncContext
10065
10066 #if SOCKETTHREADPOOL
10067     internal static class SocketThreadPool
10068     {
10069         private static readonly int c_threadIOCPTimeout = 15000; // milliseconds
10070         private static readonly IntPtr c_InvalidHandleValue = new IntPtr(-1);
10071         private static readonly int m_maxThreadsAllowed = System.Int32.MaxValue; //Maybe (Environment.ProcessorCount * some_factor) ?
10072         private static int m_numThreadsInPool = 0;
10073         private static int m_maxThreadsEverInPool = 0;
10074         private static int m_numBusyThreads = 0;
10075         private static int m_numCallbacks = 0;
10076         private static int m_numBoundHandles = 0;
10077         private static object s_InternalSyncObject;
10078         private static bool initialized = false;
10079         private static IntPtr m_hIOCP = c_InvalidHandleValue;
10080         
10081         public static bool BindHandle(SafeHandle osHandle)
10082         {
10083             // ensure initialized
10084
10085             Init();
10086
10087             // bind to completion port
10088
10089             IntPtr handle = UnsafeNclNativeMethods.OSSOCK.CreateIoCompletionPort(osHandle, m_hIOCP, 1111, 0);
10090             if (handle == IntPtr.Zero)
10091             {
10092                 throw new Exception(string.Format("CreateIoCompletionPort failed with Win32 error {0}.", Marshal.GetLastWin32Error()));
10093             }
10094
10095             // count handle
10096
10097             Interlocked.Increment(ref m_numBoundHandles);
10098
10099             if (m_numThreadsInPool == 0)
10100             {
10101                 // add thread to pool if none
10102
10103                 AddThreadToPool();
10104             }
10105             return true;
10106         }
10107
10108         public static void UnBindHandle(SafeHandle osHandle)
10109         {
10110             // take count to zero
10111
10112             Interlocked.Decrement(ref m_numBoundHandles);
10113         }
10114
10115         private static void Init()
10116         {
10117         if (!initialized)
10118         {
10119             lock (InternalSyncObject)
10120             {
10121                 if (!initialized)
10122                 {
10123                     // Create completion port
10124
10125                     m_hIOCP = UnsafeNclNativeMethods.OSSOCK.CreateIoCompletionPort(c_InvalidHandleValue, IntPtr.Zero, 1111, 0);
10126                     if (m_hIOCP == c_InvalidHandleValue)
10127                     {
10128                         throw new Exception(string.Format("CreateIoCompletionPort failed with Win32 error {0}.", Marshal.GetLastWin32Error()));
10129                     }
10130                     initialized = true;
10131                     }
10132                 }
10133             }
10134         }
10135
10136         private static object InternalSyncObject
10137         {
10138         get
10139         {
10140             if (s_InternalSyncObject == null)
10141             {
10142                 object o = new object();
10143                 Interlocked.CompareExchange(ref s_InternalSyncObject, o, null);
10144             }
10145             return s_InternalSyncObject;
10146         }
10147         }
10148
10149         private unsafe static void ThreadPoolFunc()
10150         {
10151             try
10152             {
10153                 for (Boolean fStayInPool = true; fStayInPool; /*empty*/ )
10154                 {
10155                     bool result;
10156                     uint status;
10157                     uint bytesTransferred;
10158                     int completionKey;
10159                     NativeOverlapped* nativeOverlappedPtr;
10160
10161                     // Thread no longer busy.
10162
10163                     Interlocked.Decrement(ref m_numBusyThreads);
10164
10165                     // Read the completion port queue.
10166
10167                     result = UnsafeNclNativeMethods.OSSOCK.GetQueuedCompletionStatus(
10168                                                                 m_hIOCP,
10169                                                                 out bytesTransferred,
10170                                                                 out completionKey,
10171                                                                 out nativeOverlappedPtr,
10172                                                                 c_threadIOCPTimeout);
10173
10174                     // Thread woke up and might have something to do.
10175
10176                     Int32 busyThreads = Interlocked.Increment(ref m_numBusyThreads);
10177
10178                     // Get win32 status only if GQCS returned false.
10179                     
10180                     status = 0;
10181                     if (!result)
10182                     {
10183                         status = (uint)Marshal.GetLastWin32Error();
10184                     }
10185
10186                     // Handle the case where GQCS itself fails without dequeueing a completion packet.
10187
10188                     if (nativeOverlappedPtr == null)
10189                     {
10190                         // Could be a timeout.
10191
10192                         if (status == (uint)258) // WAIT_TIMEOUT
10193                         {
10194                             // On timeout let thread go away
10195
10196                             fStayInPool = false;
10197                             break;  // Leave the loop
10198                         }
10199
10200                         // Some other win32 failure - try GQCS again.
10201
10202                         continue;
10203                     }
10204
10205                     // Heuristic to add another thread to pool.
10206
10207                     if ((busyThreads == m_numThreadsInPool) && (busyThreads < m_maxThreadsAllowed))
10208                     {
10209                         AddThreadToPool();
10210                     }
10211
10212                     // Unpack the native overlapped structure into managed Overlapped object
10213
10214                     Overlapped overlapped = Overlapped.Unpack(nativeOverlappedPtr);
10215
10216                     // See if we have a SocketOperationAsyncResult.
10217                     // Otherwise we have something derived from BaseOverlappedAsyncResult.
10218
10219                     DummyAsyncResult ar = overlapped.AsyncResult as DummyAsyncResult;
10220                     if (ar == null)
10221                     {
10222                         // Is child of BaseOverlappedAsyncResult. Callback is static function in BaseOverlappedAsyncResult.
10223
10224                         // call the callback
10225                         BaseOverlappedAsyncResult.s_IOCallback(status, bytesTransferred, nativeOverlappedPtr);
10226                     }
10227                     else
10228                     {
10229                         // Must be SocAsyncResult. Callback is in the AsyncResult.
10230
10231                         // call the callback
10232                         ar.IOCompletionCallBack(status, bytesTransferred, nativeOverlappedPtr);
10233                     }
10234
10235                     // count the completion
10236
10237                     Interlocked.Increment(ref m_numCallbacks);
10238
10239                 }   // for loop
10240
10241             }  // try
10242
10243             finally
10244             {
10245                 // Thread is leaving pool.
10246
10247                 Interlocked.Decrement(ref m_numBusyThreads);
10248                 if (Interlocked.Decrement(ref m_numThreadsInPool) == 0)
10249                 {
10250                     // No more threads in the pool.
10251                 }
10252             }
10253         }
10254
10255         private static void AddThreadToPool()
10256         {
10257             // suppress flow if not already
10258
10259             if (!ExecutionContext.IsFlowSuppressed()) ExecutionContext.SuppressFlow();
10260
10261             // Adding a thread to the thread pool
10262
10263             Interlocked.Increment(ref m_numThreadsInPool);
10264
10265             // Track max threads in pool
10266
10267             InterlockedMax(ref m_maxThreadsEverInPool, m_numThreadsInPool);
10268
10269             // Thread is busy until it blocks on GQCS
10270
10271             Interlocked.Increment(ref m_numBusyThreads);
10272
10273             // Start it up. 
10274
10275             Thread t = new Thread(new ThreadStart(ThreadPoolFunc));
10276             t.IsBackground = true;
10277             t.Start();
10278         }
10279
10280         private static Int32 InterlockedMax(ref Int32 target, Int32 val)
10281         {
10282          Int32 i, j = target;
10283          do
10284          {
10285              i = j;
10286              j = Interlocked.CompareExchange(ref target, Math.Max(i, val), i);
10287          } while (i != j);
10288          return j;
10289         }
10290     }
10291
10292     // internal minimal IAsyncResult class to pass completion routine across native overlapped calls via Overlapped magic internals
10293     internal class DummyAsyncResult : IAsyncResult {
10294         IOCompletionCallback m_iocb;
10295
10296         public DummyAsyncResult() : this(null) {
10297         }
10298         public DummyAsyncResult(IOCompletionCallback iocb) {
10299             m_iocb = iocb;
10300         }
10301         public IOCompletionCallback IOCompletionCallBack {
10302             get { return m_iocb; }
10303         }
10304         public object AsyncObject {
10305             get { return null; }
10306         }
10307         public object AsyncState {
10308             get { return null; }
10309         }
10310         public bool IsCompleted {
10311             get { return false; }
10312         }
10313         public WaitHandle AsyncWaitHandle {
10314             get { return null; }
10315         }
10316         public bool CompletedSynchronously {
10317             get { return false; }
10318         }
10319     }
10320 #endif // SOCKETTHREADPOOL
10321 #endif // !MONO
10322
10323 }