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