The Labs \ Source Viewer \ SSCLI \ System.Net.Sockets \ Socket

  1. //------------------------------------------------------------------------------
  2. // <copyright file="Socket.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. namespace System.Net.Sockets
  16. {
  17.     using System.Collections;
  18.     using System.Collections.Generic;
  19.     using System.ComponentModel;
  20.     using System.Configuration;
  21.     using System.Diagnostics;
  22.     using System.Globalization;
  23.     using System.IO;
  24.     using System.Net;
  25.     using System.Net.Configuration;
  26.     using System.Runtime.InteropServices;
  27.     using System.Security.Permissions;
  28.     using System.Threading;
  29.     using Microsoft.Win32;
  30.     using System.Security;
  31.     using System.Runtime.Versioning;
  32.    
  33.     /// <devdoc>
  34.     /// <para>The <see cref='Sockets.Socket'/> class implements the Berkeley sockets
  35.     /// interface.</para>
  36.     /// </devdoc>
  37.    
  38.    
  39.     public class Socket : IDisposable
  40.     {
  41.         internal const int DefaultCloseTimeout = -1;
  42.        
  43.         private object m_AcceptQueueOrConnectResult;
  44.        
  45.         // the following 8 members represent the state of the socket
  46.         private SafeCloseSocket m_Handle;
  47.         internal EndPoint m_RightEndPoint;
  48.         internal EndPoint m_RemoteEndPoint;
  49.         // this flags monitor if the socket was ever connected at any time and if it still is.
  50.         private bool m_IsConnected;
  51.         // = false;
  52.         private bool m_IsDisconnected;
  53.         // = false;
  54.         // when the socket is created it will be in blocking mode
  55.         // we'll only be able to Accept or Connect, so we only need
  56.         // to handle one of these cases at a time
  57.         private bool willBlock = true;
  58.         // desired state of the socket for the user
  59.         private bool willBlockInternal = true;
  60.         // actual win32 state of the socket
  61.         private bool isListening = false;
  62.        
  63.        
  64.         // These are constants initialized by constructor
  65.         private AddressFamily addressFamily;
  66.         private SocketType socketType;
  67.         private ProtocolType protocolType;
  68.        
  69.         // These caches are one degree off of Socket since they're not used in the sync case/when disabled in config.
  70.         private CacheSet m_Caches;
  71.        
  72.         private class CacheSet
  73.         {
  74.             internal CallbackClosure ConnectClosureCache;
  75.             internal CallbackClosure AcceptClosureCache;
  76.             internal CallbackClosure SendClosureCache;
  77.             internal CallbackClosure ReceiveClosureCache;
  78.            
  79.             internal OverlappedCache SendOverlappedCache;
  80.             internal OverlappedCache ReceiveOverlappedCache;
  81.         }
  82.        
  83.         //
  84.         // Overlapped constants.
  85.         //
  86.         // Disable the I/O completion port for Rotor
  87.         static internal bool UseOverlappedIO = true;
  88.         private bool useOverlappedIO;
  89.        
  90.         // Bool marked true if the native socket m_Handle was bound to the ThreadPool
  91.         private bool m_BoundToThreadPool;
  92.         // = false;
  93.         // Event used for async Connect/Accept calls
  94.         private ManualResetEvent m_AsyncEvent;
  95.         private RegisteredWaitHandle m_RegisteredWait;
  96.         private AsyncEventBits m_BlockEventBits = AsyncEventBits.FdNone;
  97.        
  98.         //These members are to cache permission checks
  99.         private SocketAddress m_PermittedRemoteAddress;
  100.        
  101.         private static ConnectExDelegate s_ConnectEx;
  102.         private static DisconnectExDelegate s_DisconnectEx;
  103.         private static DisconnectExDelegate_Blocking s_DisconnectEx_Blocking;
  104.         private static WSARecvMsgDelegate s_WSARecvMsg;
  105.         private static WSARecvMsgDelegate_Blocking s_WSARecvMsg_Blocking;
  106.        
  107.         private static object s_InternalSyncObject;
  108.         private int m_CloseTimeout = Socket.DefaultCloseTimeout;
  109.         private int m_IntCleanedUp;
  110.         // 0 if not completed >0 otherwise.
  111.         private const int microcnv = 1000000;
  112.         private static readonly int protocolInformationSize = Marshal.SizeOf(typeof(UnsafeNclNativeMethods.OSSOCK.WSAPROTOCOL_INFO));
  113.        
  114.         static internal bool s_SupportsIPv4;
  115.         static internal bool s_SupportsIPv6;
  116.         static internal bool s_OSSupportsIPv6;
  117.         static internal bool s_Initialized;
  118.         private static WaitOrTimerCallback s_RegisteredWaitCallback;
  119.        
  120.         //************* constructors *************************
  121.        
  122.         //------------------------------------
  123.        
  124.         /// <devdoc>
  125.         /// <para>
  126.         /// Initializes a new instance of the <see cref='Sockets.Socket'/> class.
  127.         /// </para>
  128.         /// </devdoc>
  129.         public Socket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)
  130.         {
  131.             if (Logging.On)
  132.                 Logging.Enter(Logging.Sockets, this, "Socket", addressFamily);
  133.             InitializeSockets();
  134.             m_Handle = SafeCloseSocket.CreateWSASocket(addressFamily, socketType, protocolType);
  135.            
  136.             if (m_Handle.IsInvalid) {
  137.                 //
  138.                 // failed to create the win32 socket, throw
  139.                 //
  140.                 throw new SocketException();
  141.             }
  142.            
  143.             this.addressFamily = addressFamily;
  144.             this.socketType = socketType;
  145.             this.protocolType = protocolType;
  146.            
  147.             if (Logging.On)
  148.                 Logging.Exit(Logging.Sockets, this, "Socket", null);
  149.         }
  150.        
  151.        
  152.         public Socket(SocketInformation socketInformation)
  153.         {
  154.             if (Logging.On)
  155.                 Logging.Enter(Logging.Sockets, this, "Socket", addressFamily);
  156.            
  157.             ExceptionHelper.UnrestrictedSocketPermission.Demand();
  158.            
  159.             InitializeSockets();
  160.             if (socketInformation.ProtocolInformation == null || socketInformation.ProtocolInformation.Length < protocolInformationSize) {
  161.                 throw new ArgumentException(SR.GetString(SR.net_sockets_invalid_socketinformation), "socketInformation.ProtocolInformation");
  162.             }
  163.            
  164.             unsafe {
  165.                 fixed (byte* pinnedBuffer = socketInformation.ProtocolInformation) {
  166.                     m_Handle = SafeCloseSocket.CreateWSASocket(pinnedBuffer);
  167.                    
  168.                     UnsafeNclNativeMethods.OSSOCK.WSAPROTOCOL_INFO protocolInfo = (UnsafeNclNativeMethods.OSSOCK.WSAPROTOCOL_INFO)Marshal.PtrToStructure((IntPtr)pinnedBuffer, typeof(UnsafeNclNativeMethods.OSSOCK.WSAPROTOCOL_INFO));
  169.                     addressFamily = protocolInfo.iAddressFamily;
  170.                     socketType = (SocketType)protocolInfo.iSocketType;
  171.                     protocolType = (ProtocolType)protocolInfo.iProtocol;
  172.                 }
  173.             }
  174.            
  175.             if (m_Handle.IsInvalid) {
  176.                 SocketException e = new SocketException();
  177.                 if (e.ErrorCode == (int)SocketError.InvalidArgument) {
  178.                     throw new ArgumentException(SR.GetString(SR.net_sockets_invalid_socketinformation), "socketInformation");
  179.                 }
  180.                 else {
  181.                     throw e;
  182.                 }
  183.             }
  184.            
  185.             if (addressFamily != AddressFamily.InterNetwork && addressFamily != AddressFamily.InterNetworkV6) {
  186.                 throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
  187.             }
  188.            
  189.             m_IsConnected = socketInformation.IsConnected;
  190.             willBlock = !socketInformation.IsNonBlocking;
  191.             InternalSetBlocking(willBlock);
  192.             isListening = socketInformation.IsListening;
  193.             UseOnlyOverlappedIO = socketInformation.UseOnlyOverlappedIO;
  194.            
  195.            
  196.             //are we bound? if so, what's the local endpoint?
  197.            
  198.             EndPoint ep = null;
  199.             if (addressFamily == AddressFamily.InterNetwork) {
  200.                 ep = IPEndPoint.Any;
  201.             }
  202.             else if (addressFamily == AddressFamily.InterNetworkV6) {
  203.                 ep = IPEndPoint.IPv6Any;
  204.             }
  205.            
  206.             SocketAddress socketAddress = ep.Serialize();
  207.             SocketError errorCode;
  208.             try {
  209.                 errorCode = UnsafeNclNativeMethods.OSSOCK.getsockname(m_Handle, socketAddress.m_Buffer, ref socketAddress.m_Size);
  210.             }
  211.             catch (ObjectDisposedException) {
  212.                 errorCode = SocketError.NotSocket;
  213.             }
  214.            
  215.             if (errorCode == SocketError.Success) {
  216.                 try {
  217.                     //we're bound
  218.                     m_RightEndPoint = ep.Create(socketAddress);
  219.                 }
  220.                 catch {
  221.                 }
  222.             }
  223.            
  224.             if (Logging.On)
  225.                 Logging.Exit(Logging.Sockets, this, "Socket", null);
  226.         }
  227.        
  228.        
  229.         /// <devdoc>
  230.         /// <para>
  231.         /// Called by the class to create a socket to accept an
  232.         /// incoming request.
  233.         /// </para>
  234.         /// </devdoc>
  235.         private Socket(SafeCloseSocket fd)
  236.         {
  237.             if (Logging.On)
  238.                 Logging.Enter(Logging.Sockets, this, "Socket", null);
  239.             InitializeSockets();
  240.            
  241.             //
  242.             if (fd == null || fd.IsInvalid) {
  243.                 throw new ArgumentException(SR.GetString(SR.net_InvalidSocketHandle));
  244.             }
  245.            
  246.             m_Handle = fd;
  247.            
  248.             addressFamily = Sockets.AddressFamily.Unknown;
  249.             socketType = Sockets.SocketType.Unknown;
  250.             protocolType = Sockets.ProtocolType.Unknown;
  251.             if (Logging.On)
  252.                 Logging.Exit(Logging.Sockets, this, "Socket", null);
  253.         }
  254.        
  255.        
  256.        
  257.         //************* properties *************************
  258.        
  259.        
  260.         /// <devdoc>
  261.         /// <para>Indicates whether IPv4 support is available and enabled on this machine.</para>
  262.         /// </devdoc>
  263.         public static bool SupportsIPv4 {
  264.             get {
  265.                 InitializeSockets();
  266.                 return s_SupportsIPv4;
  267.             }
  268.         }
  269.        
  270.         /// <devdoc>
  271.         /// <para>Indicates whether IPv6 support is available and enabled on this machine.</para>
  272.         /// </devdoc>
  273.        
  274.         [Obsolete("SupportsIPv6 is obsoleted for this type, please use OSSupportsIPv6 instead. http://go.microsoft.com/fwlink/?linkid=14202")]
  275.         public static bool SupportsIPv6 {
  276.             get {
  277.                 InitializeSockets();
  278.                 return s_SupportsIPv6;
  279.             }
  280.         }
  281.        
  282.         static internal bool LegacySupportsIPv6 {
  283.             get {
  284.                 InitializeSockets();
  285.                 return s_SupportsIPv6;
  286.             }
  287.         }
  288.        
  289.         public static bool OSSupportsIPv6 {
  290.             get {
  291.                 InitializeSockets();
  292.                 return s_OSSupportsIPv6;
  293.             }
  294.         }
  295.        
  296.        
  297.         /// <devdoc>
  298.         /// <para>
  299.         /// Gets the amount of data pending in the network's input buffer that can be
  300.         /// read from the socket.
  301.         /// </para>
  302.         /// </devdoc>
  303.         public int Available {
  304.             get {
  305.                 if (CleanedUp) {
  306.                     throw new ObjectDisposedException(this.GetType().FullName);
  307.                 }
  308.                
  309.                 int argp = 0;
  310.                
  311.                 // This may throw ObjectDisposedException.
  312.                 SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.ioctlsocket(m_Handle, IoctlSocketConstants.FIONREAD, ref argp);
  313.                
  314.                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Available_get() UnsafeNclNativeMethods.OSSOCK.ioctlsocket returns errorCode:" + errorCode);
  315.                
  316.                 //
  317.                 // if the native call fails we'll throw a SocketException
  318.                 //
  319.                 if (errorCode == SocketError.SocketError) {
  320.                     //
  321.                     // update our internal state after this socket error and throw
  322.                     //
  323.                     SocketException socketException = new SocketException();
  324.                     UpdateStatusAfterSocketError(socketException);
  325.                     if (Logging.On)
  326.                         Logging.Exception(Logging.Sockets, this, "Available", socketException);
  327.                     throw socketException;
  328.                 }
  329.                
  330.                 return argp;
  331.             }
  332.         }
  333.        
  334.        
  335.        
  336.        
  337.        
  338.         /// <devdoc>
  339.         /// <para>
  340.         /// Gets the local end point.
  341.         /// </para>
  342.         /// </devdoc>
  343.         public EndPoint LocalEndPoint {
  344.             get {
  345.                 if (CleanedUp) {
  346.                     throw new ObjectDisposedException(this.GetType().FullName);
  347.                 }
  348.                
  349.                 if (m_RightEndPoint == null) {
  350.                     return null;
  351.                 }
  352.                
  353.                 SocketAddress socketAddress = m_RightEndPoint.Serialize();
  354.                
  355.                 // This may throw ObjectDisposedException.
  356.                 SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.getsockname(m_Handle, socketAddress.m_Buffer, ref socketAddress.m_Size);
  357.                
  358.                 if (errorCode != SocketError.Success) {
  359.                     //
  360.                     // update our internal state after this socket error and throw
  361.                     //
  362.                     SocketException socketException = new SocketException();
  363.                     UpdateStatusAfterSocketError(socketException);
  364.                     if (Logging.On)
  365.                         Logging.Exception(Logging.Sockets, this, "LocalEndPoint", socketException);
  366.                     throw socketException;
  367.                 }
  368.                
  369.                 return m_RightEndPoint.Create(socketAddress);
  370.             }
  371.         }
  372.        
  373.         /// <devdoc>
  374.         /// <para>
  375.         /// Gets the remote end point
  376.         /// </para>
  377.         /// </devdoc>
  378.         public EndPoint RemoteEndPoint {
  379.             get {
  380.                 if (CleanedUp) {
  381.                     throw new ObjectDisposedException(this.GetType().FullName);
  382.                 }
  383.                
  384.                 if (m_RemoteEndPoint == null) {
  385.                     if (m_RightEndPoint == null) {
  386.                         return null;
  387.                     }
  388.                    
  389.                     SocketAddress socketAddress = m_RightEndPoint.Serialize();
  390.                    
  391.                     // This may throw ObjectDisposedException.
  392.                     SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.getpeername(m_Handle, socketAddress.m_Buffer, ref socketAddress.m_Size);
  393.                    
  394.                     if (errorCode != SocketError.Success) {
  395.                         //
  396.                         // update our internal state after this socket error and throw
  397.                         //
  398.                         SocketException socketException = new SocketException();
  399.                         UpdateStatusAfterSocketError(socketException);
  400.                         if (Logging.On)
  401.                             Logging.Exception(Logging.Sockets, this, "RemoteEndPoint", socketException);
  402.                         throw socketException;
  403.                     }
  404.                    
  405.                     try {
  406.                         m_RemoteEndPoint = m_RightEndPoint.Create(socketAddress);
  407.                     }
  408.                     catch {
  409.                     }
  410.                 }
  411.                
  412.                 return m_RemoteEndPoint;
  413.             }
  414.         }
  415.        
  416.         public IntPtr Handle {
  417.             get {
  418.                 ExceptionHelper.UnmanagedPermission.Demand();
  419.                 return m_Handle.DangerousGetHandle();
  420.             }
  421.         }
  422.         internal SafeCloseSocket SafeHandle {
  423.             get { return m_Handle; }
  424.         }
  425.        
  426.        
  427.         // Non-blocking I/O control
  428.         /// <devdoc>
  429.         /// <para>
  430.         /// Gets and sets the blocking mode of a socket.
  431.         /// </para>
  432.         /// </devdoc>
  433.         public bool Blocking {
  434. //
  435. // return the user's desired blocking behaviour (not the actual win32 state)
  436. //
  437.             get { return willBlock; }
  438.             set {
  439.                 if (CleanedUp) {
  440.                     throw new ObjectDisposedException(this.GetType().FullName);
  441.                 }
  442.                
  443.                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::set_Blocking() value:" + value.ToString() + " willBlock:" + willBlock.ToString() + " willBlockInternal:" + willBlockInternal.ToString());
  444.                
  445.                 bool current;
  446.                
  447.                 SocketError errorCode = InternalSetBlocking(value, out current);
  448.                
  449.                 if (errorCode != SocketError.Success) {
  450.                     //
  451.                     // update our internal state after this socket error and throw
  452.                     SocketException socketException = new SocketException(errorCode);
  453.                     UpdateStatusAfterSocketError(socketException);
  454.                     if (Logging.On)
  455.                         Logging.Exception(Logging.Sockets, this, "Blocking", socketException);
  456.                     throw socketException;
  457.                 }
  458.                
  459.                 //
  460.                 // win32 call succeeded, update desired state
  461.                 //
  462.                 willBlock = current;
  463.             }
  464.         }
  465.        
  466.         public bool UseOnlyOverlappedIO {
  467. //
  468. // return the user's desired blocking behaviour (not the actual win32 state)
  469. //
  470.                
  471.             get { return useOverlappedIO; }
  472.             set {
  473.                
  474.                 if (m_BoundToThreadPool) {
  475.                     throw new InvalidOperationException(SR.GetString(SR.net_io_completionportwasbound));
  476.                 }
  477.                
  478.                 useOverlappedIO = value;
  479.             }
  480.         }
  481.        
  482.        
  483.         /// <devdoc>
  484.         /// <para>
  485.         /// Gets the connection state of the Socket. This property will return the latest
  486.         /// known state of the Socket. When it returns false, the Socket was either never connected
  487.         /// or it is not connected anymore. When it returns true, though, there's no guarantee that the Socket
  488.         /// is still connected, but only that it was connected at the time of the last IO operation.
  489.         /// </para>
  490.         /// </devdoc>
  491.         public bool Connected {
  492.             get {
  493.                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Connected() m_IsConnected:" + m_IsConnected);
  494.                 return m_IsConnected;
  495.             }
  496.         }
  497.        
  498.         /// <devdoc>
  499.         /// <para>
  500.         /// Gets the socket's address family.
  501.         /// </para>
  502.         /// </devdoc>
  503.         public AddressFamily AddressFamily {
  504.             get { return addressFamily; }
  505.         }
  506.        
  507.         /// <devdoc>
  508.         /// <para>
  509.         /// Gets the socket's socketType.
  510.         /// </para>
  511.         /// </devdoc>
  512.         public SocketType SocketType {
  513.             get { return socketType; }
  514.         }
  515.        
  516.         /// <devdoc>
  517.         /// <para>
  518.         /// Gets the socket's protocol socketType.
  519.         /// </para>
  520.         /// </devdoc>
  521.         public ProtocolType ProtocolType {
  522.             get { return protocolType; }
  523.         }
  524.        
  525.        
  526.         public bool IsBound {
  527.             get { return (m_RightEndPoint != null); }
  528.         }
  529.        
  530.        
  531.         public bool ExclusiveAddressUse {
  532.             get { return (int)GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse) != 0 ? true : false; }
  533.             set {
  534.                 if (IsBound) {
  535.                     throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustnotbebound));
  536.                 }
  537.                 SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse, value ? 1 : 0);
  538.             }
  539.         }
  540.        
  541.        
  542.         public int ReceiveBufferSize {
  543.             get { return (int)GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer); }
  544.             set {
  545.                 if (value < 0) {
  546.                     throw new ArgumentOutOfRangeException("value");
  547.                 }
  548.                
  549.                 SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, value);
  550.             }
  551.         }
  552.        
  553.         public int SendBufferSize {
  554.             get { return (int)GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendBuffer); }
  555.            
  556.             set {
  557.                 if (value < 0) {
  558.                     throw new ArgumentOutOfRangeException("value");
  559.                 }
  560.                
  561.                 SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendBuffer, value);
  562.             }
  563.         }
  564.        
  565.         public int ReceiveTimeout {
  566.             get { return (int)GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout); }
  567.             set {
  568.                 if (value < -1) {
  569.                     throw new ArgumentOutOfRangeException("value");
  570.                 }
  571.                 if (value == -1) {
  572.                     value = 0;
  573.                 }
  574.                
  575.                 SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, value);
  576.             }
  577.         }
  578.        
  579.         public int SendTimeout {
  580.             get { return (int)GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout); }
  581.            
  582.             set {
  583.                 if (value < -1) {
  584.                     throw new ArgumentOutOfRangeException("value");
  585.                 }
  586.                 if (value == -1) {
  587.                     value = 0;
  588.                 }
  589.                
  590.                 SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, value);
  591.             }
  592.         }
  593.        
  594.         public LingerOption LingerState {
  595.             get { return (LingerOption)GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger); }
  596.             set { SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, value); }
  597.         }
  598.        
  599.         public bool NoDelay {
  600.             get { return (int)GetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay) != 0 ? true : false; }
  601.             set { SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, value ? 1 : 0); }
  602.         }
  603.        
  604.         public short Ttl {
  605.             get {
  606.                 if (addressFamily == AddressFamily.InterNetwork) {
  607.                     return (short)(int)GetSocketOption(SocketOptionLevel.IP, SocketOptionName.IpTimeToLive);
  608.                 }
  609.                 else if (addressFamily == AddressFamily.InterNetworkV6) {
  610.                     return (short)(int)GetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IpTimeToLive);
  611.                 }
  612.                 else {
  613.                     throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
  614.                 }
  615.             }
  616.            
  617.             set {
  618.                
  619.                 // -1 is valid only for IPv6 sockets
  620.                 // All numbers < -1 are invalid for all sockets
  621.                 //
  622.                 if (value < -1 || (value == -1 && addressFamily != AddressFamily.InterNetworkV6)) {
  623.                     throw new ArgumentOutOfRangeException("value");
  624.                 }
  625.                
  626.                 if (addressFamily == AddressFamily.InterNetwork) {
  627.                     SetSocketOption(SocketOptionLevel.IP, SocketOptionName.IpTimeToLive, value);
  628.                 }
  629.                
  630.                 else if (addressFamily == AddressFamily.InterNetworkV6) {
  631.                     SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IpTimeToLive, value);
  632.                 }
  633.                 else {
  634.                     throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
  635.                 }
  636.             }
  637.         }
  638.        
  639.         public bool DontFragment {
  640.             get {
  641.                 if (addressFamily == AddressFamily.InterNetwork) {
  642.                     return (int)GetSocketOption(SocketOptionLevel.IP, SocketOptionName.DontFragment) != 0 ? true : false;
  643.                 }
  644.                 else {
  645.                     throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
  646.                 }
  647.             }
  648.            
  649.             set {
  650.                 if (addressFamily == AddressFamily.InterNetwork) {
  651.                     SetSocketOption(SocketOptionLevel.IP, SocketOptionName.DontFragment, value ? 1 : 0);
  652.                 }
  653.                 else {
  654.                     throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
  655.                 }
  656.             }
  657.         }
  658.        
  659.         public bool MulticastLoopback {
  660.             get {
  661.                 if (addressFamily == AddressFamily.InterNetwork) {
  662.                     return (int)GetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastLoopback) != 0 ? true : false;
  663.                 }
  664.                 else if (addressFamily == AddressFamily.InterNetworkV6) {
  665.                     return (int)GetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback) != 0 ? true : false;
  666.                 }
  667.                 else {
  668.                     throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
  669.                 }
  670.             }
  671.            
  672.             set {
  673.                 if (addressFamily == AddressFamily.InterNetwork) {
  674.                     SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastLoopback, value ? 1 : 0);
  675.                 }
  676.                
  677.                 else if (addressFamily == AddressFamily.InterNetworkV6) {
  678.                     SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback, value ? 1 : 0);
  679.                 }
  680.                 else {
  681.                     throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
  682.                 }
  683.             }
  684.         }
  685.        
  686.        
  687.         public bool EnableBroadcast {
  688.             get { return (int)GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast) != 0 ? true : false; }
  689.             set { SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, value ? 1 : 0); }
  690.         }
  691.        
  692.        
  693.        
  694.         //************* public methods *************************
  695.        
  696.        
  697.        
  698.        
  699.        
  700.         /// <devdoc>
  701.         /// <para>Associates a socket with an end point.</para>
  702.         /// </devdoc>
  703.         public void Bind(EndPoint localEP)
  704.         {
  705.            
  706.             if (Logging.On)
  707.                 Logging.Enter(Logging.Sockets, this, "Bind", localEP);
  708.            
  709.             if (CleanedUp) {
  710.                 throw new ObjectDisposedException(this.GetType().FullName);
  711.             }
  712.             //
  713.             // parameter validation
  714.             //
  715.             if (localEP == null) {
  716.                 throw new ArgumentNullException("localEP");
  717.             }
  718.            
  719.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Bind() localEP:" + localEP.ToString());
  720.            
  721.             EndPoint endPointSnapshot = localEP;
  722.             IPEndPoint ipSnapshot = localEP as IPEndPoint;
  723.            
  724.             //
  725.             // for now security is implemented only on IPEndPoint
  726.             // If EndPoint is of other type - unmanaged code permisison is demanded
  727.             //
  728.             if (ipSnapshot != null) {
  729.                 // Take a snapshot that will make it immutable and not derived.
  730.                 ipSnapshot = ipSnapshot.Snapshot();
  731.                 endPointSnapshot = ipSnapshot;
  732.                
  733.                 //
  734.                 // create the permissions the user would need for the call
  735.                 //
  736.                 SocketPermission socketPermission = new SocketPermission(NetworkAccess.Accept, Transport, ipSnapshot.Address.ToString(), ipSnapshot.Port);
  737.                 //
  738.                 // demand for them
  739.                 //
  740.                 socketPermission.Demand();
  741.                
  742.                 // Here the permission check has succeded.
  743.                 // NB: if local port is 0, then winsock will assign some>1024,
  744.                 // so assuming that this is safe. We will not check the
  745.                 // NetworkAccess.Accept permissions in Receive.
  746.             }
  747.             else {
  748.                
  749.                 ExceptionHelper.UnmanagedPermission.Demand();
  750.             }
  751.            
  752.             //
  753.             // ask the EndPoint to generate a SocketAddress that we
  754.             // can pass down to winsock
  755.             //
  756.             SocketAddress socketAddress = endPointSnapshot.Serialize();
  757.             DoBind(endPointSnapshot, socketAddress);
  758.             if (Logging.On)
  759.                 Logging.Exit(Logging.Sockets, this, "Bind", "");
  760.         }
  761.        
  762.         internal void InternalBind(EndPoint localEP)
  763.         {
  764.             if (Logging.On)
  765.                 Logging.Enter(Logging.Sockets, this, "InternalBind", localEP);
  766.            
  767.             if (CleanedUp) {
  768.                 throw new ObjectDisposedException(GetType().FullName);
  769.             }
  770.            
  771.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::InternalBind() localEP:" + localEP.ToString());
  772.            
  773.             //
  774.             // ask the EndPoint to generate a SocketAddress that we
  775.             // can pass down to winsock
  776.             //
  777.             EndPoint endPointSnapshot = localEP;
  778.             SocketAddress socketAddress = SnapshotAndSerialize(ref endPointSnapshot);
  779.             DoBind(endPointSnapshot, socketAddress);
  780.            
  781.             if (Logging.On)
  782.                 Logging.Exit(Logging.Sockets, this, "InternalBind", "");
  783.         }
  784.        
  785.         private void DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
  786.         {
  787.             // This may throw ObjectDisposedException.
  788.             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.bind(m_Handle, socketAddress.m_Buffer, socketAddress.m_Size);
  789.            
  790.            
  791.             //
  792.             // if the native call fails we'll throw a SocketException
  793.             //
  794.             if (errorCode != SocketError.Success) {
  795.                 //
  796.                 // update our internal state after this socket error and throw
  797.                 //
  798.                 SocketException socketException = new SocketException();
  799.                 UpdateStatusAfterSocketError(socketException);
  800.                 if (Logging.On)
  801.                     Logging.Exception(Logging.Sockets, this, "DoBind", socketException);
  802.                 throw socketException;
  803.             }
  804.            
  805.             if (m_RightEndPoint == null) {
  806.                 //
  807.                 // save a copy of the EndPoint so we can use it for Create()
  808.                 //
  809.                 m_RightEndPoint = endPointSnapshot;
  810.             }
  811.         }
  812.        
  813.        
  814.         /// <devdoc>
  815.         /// <para>Establishes a connection to a remote system.</para>
  816.         /// </devdoc>
  817.         public void Connect(EndPoint remoteEP)
  818.         {
  819.             if (CleanedUp) {
  820.                 throw new ObjectDisposedException(this.GetType().FullName);
  821.             }
  822.             //
  823.             // parameter validation
  824.             //
  825.             if (remoteEP == null) {
  826.                 throw new ArgumentNullException("remoteEP");
  827.             }
  828.            
  829.             if (m_IsDisconnected) {
  830.                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_disconnectedConnect));
  831.             }
  832.            
  833.             if (isListening) {
  834.                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustnotlisten));
  835.             }
  836.            
  837.             ValidateBlockingMode();
  838.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Connect() DST:" + ValidationHelper.ToString(remoteEP));
  839.            
  840.             //This will check the permissions for connect
  841.             EndPoint endPointSnapshot = remoteEP;
  842.             SocketAddress socketAddress = CheckCacheRemote(ref endPointSnapshot, true);
  843.            
  844.             DoConnect(endPointSnapshot, socketAddress);
  845.         }
  846.        
  847.        
  848.         public void Connect(IPAddress address, int port)
  849.         {
  850.            
  851.             if (Logging.On)
  852.                 Logging.Enter(Logging.Sockets, this, "Connect", address);
  853.            
  854.             if (CleanedUp) {
  855.                 throw new ObjectDisposedException(this.GetType().FullName);
  856.             }
  857.             //if address family isn't the socket address family throw
  858.             if (address == null) {
  859.                 throw new ArgumentNullException("address");
  860.             }
  861.            
  862.             if (!ValidationHelper.ValidateTcpPort(port)) {
  863.                 throw new ArgumentOutOfRangeException("port");
  864.             }
  865.             if (addressFamily != address.AddressFamily) {
  866.                 throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
  867.             }
  868.            
  869.             IPEndPoint remoteEP = new IPEndPoint(address, port);
  870.             Connect(remoteEP);
  871.             if (Logging.On)
  872.                 Logging.Exit(Logging.Sockets, this, "Connect", null);
  873.         }
  874.        
  875.        
  876.         public void Connect(string host, int port)
  877.         {
  878.             if (Logging.On)
  879.                 Logging.Enter(Logging.Sockets, this, "Connect", host);
  880.            
  881.             if (CleanedUp) {
  882.                 throw new ObjectDisposedException(this.GetType().FullName);
  883.             }
  884.             if (host == null) {
  885.                 throw new ArgumentNullException("host");
  886.             }
  887.             if (!ValidationHelper.ValidateTcpPort(port)) {
  888.                 throw new ArgumentOutOfRangeException("port");
  889.             }
  890.             if (addressFamily != AddressFamily.InterNetwork && addressFamily != AddressFamily.InterNetworkV6) {
  891.                 throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
  892.             }
  893.            
  894.             IPAddress[] addresses = Dns.GetHostAddresses(host);
  895.             Connect(addresses, port);
  896.             if (Logging.On)
  897.                 Logging.Exit(Logging.Sockets, this, "Connect", null);
  898.         }
  899.        
  900.         public void Connect(IPAddress[] addresses, int port)
  901.         {
  902.             if (Logging.On)
  903.                 Logging.Enter(Logging.Sockets, this, "Connect", addresses);
  904.            
  905.             if (CleanedUp) {
  906.                 throw new ObjectDisposedException(this.GetType().FullName);
  907.             }
  908.             if (addresses == null) {
  909.                 throw new ArgumentNullException("addresses");
  910.             }
  911.             if (addresses.Length == 0) {
  912.                 throw new ArgumentException(SR.GetString(SR.net_sockets_invalid_ipaddress_length), "addresses");
  913.             }
  914.             if (!ValidationHelper.ValidateTcpPort(port)) {
  915.                 throw new ArgumentOutOfRangeException("port");
  916.             }
  917.             if (addressFamily != AddressFamily.InterNetwork && addressFamily != AddressFamily.InterNetworkV6) {
  918.                 throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
  919.             }
  920.            
  921.             Exception lastex = null;
  922.             foreach (IPAddress address in addresses) {
  923.                 if (address.AddressFamily == addressFamily) {
  924.                     try {
  925.                         Connect(new IPEndPoint(address, port));
  926.                         lastex = null;
  927.                         break;
  928.                     }
  929.                     catch (Exception ex) {
  930.                         if (NclUtilities.IsFatal(ex))
  931.                             throw;
  932.                         lastex = ex;
  933.                     }
  934.                     catch {
  935.                         lastex = new Exception(SR.GetString(SR.net_nonClsCompliantException));
  936.                     }
  937.                 }
  938.             }
  939.            
  940.             if (lastex != null)
  941.                 throw lastex;
  942.            
  943.             //if we're not connected, then we didn't get a valid ipaddress in the list
  944.             if (!Connected) {
  945.                 throw new ArgumentException(SR.GetString(SR.net_invalidAddressList), "addresses");
  946.             }
  947.            
  948.             if (Logging.On)
  949.                 Logging.Exit(Logging.Sockets, this, "Connect", null);
  950.         }
  951.        
  952.        
  953.         /// <devdoc>
  954.         /// <para>
  955.         /// Forces a socket connection to close.
  956.         /// </para>
  957.         /// </devdoc>
  958.         public void Close()
  959.         {
  960.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Close() timeout = " + m_CloseTimeout);
  961.             if (Logging.On)
  962.                 Logging.Enter(Logging.Sockets, this, "Close", null);
  963.             ((IDisposable)this).Dispose();
  964.             if (Logging.On)
  965.                 Logging.Exit(Logging.Sockets, this, "Close", null);
  966.         }
  967.        
  968.         public void Close(int timeout)
  969.         {
  970.             if (timeout < -1) {
  971.                 throw new ArgumentOutOfRangeException("timeout");
  972.             }
  973.             m_CloseTimeout = timeout;
  974.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Close() timeout = " + m_CloseTimeout);
  975.             ((IDisposable)this).Dispose();
  976.         }
  977.        
  978.        
  979.         /// <devdoc>
  980.         /// <para>
  981.         /// Places a socket in a listening state.
  982.         /// </para>
  983.         /// </devdoc>
  984.         public void Listen(int backlog)
  985.         {
  986.             if (Logging.On)
  987.                 Logging.Enter(Logging.Sockets, this, "Listen", backlog);
  988.             if (CleanedUp) {
  989.                 throw new ObjectDisposedException(this.GetType().FullName);
  990.             }
  991.            
  992.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Listen() backlog:" + backlog.ToString());
  993.            
  994.             // No access permissions are necessary here because
  995.             // the verification is done for Bind
  996.            
  997.             // This may throw ObjectDisposedException.
  998.             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.listen(m_Handle, backlog);
  999.            
  1000.            
  1001.             //
  1002.             // if the native call fails we'll throw a SocketException
  1003.             //
  1004.             if (errorCode != SocketError.Success) {
  1005.                 //
  1006.                 // update our internal state after this socket error and throw
  1007.                 //
  1008.                 SocketException socketException = new SocketException();
  1009.                 UpdateStatusAfterSocketError(socketException);
  1010.                 if (Logging.On)
  1011.                     Logging.Exception(Logging.Sockets, this, "Listen", socketException);
  1012.                 throw socketException;
  1013.             }
  1014.             isListening = true;
  1015.             if (Logging.On)
  1016.                 Logging.Exit(Logging.Sockets, this, "Listen", "");
  1017.         }
  1018.        
  1019.         /// <devdoc>
  1020.         /// <para>
  1021.         /// Creates a new <see cref='Sockets.Socket'/> instance to handle an incoming
  1022.         /// connection.
  1023.         /// </para>
  1024.         /// </devdoc>
  1025.         public Socket Accept()
  1026.         {
  1027.             if (Logging.On)
  1028.                 Logging.Enter(Logging.Sockets, this, "Accept", "");
  1029.            
  1030.             //
  1031.             // parameter validation
  1032.             //
  1033.            
  1034.             if (CleanedUp) {
  1035.                 throw new ObjectDisposedException(this.GetType().FullName);
  1036.             }
  1037.            
  1038.             if (m_RightEndPoint == null) {
  1039.                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustbind));
  1040.             }
  1041.            
  1042.             if (!isListening) {
  1043.                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustlisten));
  1044.             }
  1045.            
  1046.             if (m_IsDisconnected) {
  1047.                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_disconnectedAccept));
  1048.             }
  1049.            
  1050.             ValidateBlockingMode();
  1051.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Accept() SRC:" + ValidationHelper.ToString(LocalEndPoint));
  1052.            
  1053.             SocketAddress socketAddress = m_RightEndPoint.Serialize();
  1054.            
  1055.             // This may throw ObjectDisposedException.
  1056.             SafeCloseSocket acceptedSocketHandle = SafeCloseSocket.Accept(m_Handle, socketAddress.m_Buffer, ref socketAddress.m_Size);
  1057.            
  1058.             //
  1059.             // if the native call fails we'll throw a SocketException
  1060.             //
  1061.             if (acceptedSocketHandle.IsInvalid) {
  1062.                 //
  1063.                 // update our internal state after this socket error and throw
  1064.                 //
  1065.                 SocketException socketException = new SocketException();
  1066.                 UpdateStatusAfterSocketError(socketException);
  1067.                 if (Logging.On)
  1068.                     Logging.Exception(Logging.Sockets, this, "Accept", socketException);
  1069.                 throw socketException;
  1070.             }
  1071.            
  1072.             Socket socket = CreateAcceptSocket(acceptedSocketHandle, m_RightEndPoint.Create(socketAddress), false);
  1073.             if (Logging.On)
  1074.                 Logging.Exit(Logging.Sockets, this, "Accept", socket);
  1075.             return socket;
  1076.         }
  1077.        
  1078.        
  1079.         /// <devdoc>
  1080.         /// <para>Sends a data buffer to a connected socket.</para>
  1081.         /// </devdoc>
  1082.         public int Send(byte[] buffer, int size, SocketFlags socketFlags)
  1083.         {
  1084.             return Send(buffer, 0, size, socketFlags);
  1085.         }
  1086.         /// <devdoc>
  1087.         /// <para>[To be supplied.]</para>
  1088.         /// </devdoc>
  1089.         public int Send(byte[] buffer, SocketFlags socketFlags)
  1090.         {
  1091.             return Send(buffer, 0, buffer != null ? buffer.Length : 0, socketFlags);
  1092.         }
  1093.         /// <devdoc>
  1094.         /// <para>[To be supplied.]</para>
  1095.         /// </devdoc>
  1096.         public int Send(byte[] buffer)
  1097.         {
  1098.             return Send(buffer, 0, buffer != null ? buffer.Length : 0, SocketFlags.None);
  1099.         }
  1100.        
  1101.        
  1102.        
  1103.         /// <devdoc>
  1104.         /// <para>Sends data to
  1105.         /// a connected socket, starting at the indicated location in the
  1106.         /// data.</para>
  1107.         /// </devdoc>
  1108.        
  1109.        
  1110.         public int Send(byte[] buffer, int offset, int size, SocketFlags socketFlags)
  1111.         {
  1112.             SocketError errorCode;
  1113.             int bytesTransferred = Send(buffer, offset, size, socketFlags, out errorCode);
  1114.             if (errorCode != SocketError.Success) {
  1115.                 throw new SocketException(errorCode);
  1116.             }
  1117.             return bytesTransferred;
  1118.         }
  1119.        
  1120.        
  1121.        
  1122.         public int Send(byte[] buffer, int offset, int size, SocketFlags socketFlags, out SocketError errorCode)
  1123.         {
  1124.             if (Logging.On)
  1125.                 Logging.Enter(Logging.Sockets, this, "Send", "");
  1126.            
  1127.             if (CleanedUp) {
  1128.                 throw new ObjectDisposedException(this.GetType().FullName);
  1129.             }
  1130.             //
  1131.             // parameter validation
  1132.             //
  1133.             if (buffer == null) {
  1134.                 throw new ArgumentNullException("buffer");
  1135.             }
  1136.             if (offset < 0 || offset > buffer.Length) {
  1137.                 throw new ArgumentOutOfRangeException("offset");
  1138.             }
  1139.             if (size < 0 || size > buffer.Length - offset) {
  1140.                 throw new ArgumentOutOfRangeException("size");
  1141.             }
  1142.            
  1143.            
  1144.             errorCode = SocketError.Success;
  1145.             ValidateBlockingMode();
  1146.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Send() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " DST:" + ValidationHelper.ToString(RemoteEndPoint) + " size:" + size);
  1147.            
  1148.             // This can throw ObjectDisposedException.
  1149.             int bytesTransferred;
  1150.             unsafe {
  1151.                 if (buffer.Length == 0)
  1152.                     bytesTransferred = UnsafeNclNativeMethods.OSSOCK.send(m_Handle.DangerousGetHandle(), null, 0, socketFlags);
  1153.                 else {
  1154.                     fixed (byte* pinnedBuffer = buffer) {
  1155.                         bytesTransferred = UnsafeNclNativeMethods.OSSOCK.send(m_Handle.DangerousGetHandle(), pinnedBuffer + offset, size, socketFlags);
  1156.                     }
  1157.                 }
  1158.             }
  1159.            
  1160.             //
  1161.             // if the native call fails we'll throw a SocketException
  1162.             //
  1163.             if ((SocketError)bytesTransferred == SocketError.SocketError) {
  1164.                 //
  1165.                 // update our internal state after this socket error and throw
  1166.                 //
  1167.                 errorCode = (SocketError)Marshal.GetLastWin32Error();
  1168.                 UpdateStatusAfterSocketError(errorCode);
  1169.                 if (Logging.On) {
  1170.                     Logging.Exception(Logging.Sockets, this, "Send", new SocketException(errorCode));
  1171.                     Logging.Exit(Logging.Sockets, this, "Send", 0);
  1172.                 }
  1173.                 return 0;
  1174.             }
  1175.            
  1176.            
  1177.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Send() UnsafeNclNativeMethods.OSSOCK.send returns:" + bytesTransferred.ToString());
  1178.            
  1179.             if (Logging.On)
  1180.                 Logging.Dump(Logging.Sockets, this, "Send", buffer, offset, size);
  1181.             if (Logging.On)
  1182.                 Logging.Exit(Logging.Sockets, this, "Send", bytesTransferred);
  1183.             return bytesTransferred;
  1184.         }
  1185.        
  1186.        
  1187.         /// <devdoc>
  1188.         /// <para>Sends data to a specific end point, starting at the indicated location in the
  1189.         /// data.</para>
  1190.         /// </devdoc>
  1191.         public int SendTo(byte[] buffer, int offset, int size, SocketFlags socketFlags, EndPoint remoteEP)
  1192.         {
  1193.             if (Logging.On)
  1194.                 Logging.Enter(Logging.Sockets, this, "SendTo", "");
  1195.             if (CleanedUp) {
  1196.                 throw new ObjectDisposedException(this.GetType().FullName);
  1197.             }
  1198.             //
  1199.             // parameter validation
  1200.             //
  1201.             if (buffer == null) {
  1202.                 throw new ArgumentNullException("buffer");
  1203.             }
  1204.             if (remoteEP == null) {
  1205.                 throw new ArgumentNullException("remoteEP");
  1206.             }
  1207.             if (offset < 0 || offset > buffer.Length) {
  1208.                 throw new ArgumentOutOfRangeException("offset");
  1209.             }
  1210.             if (size < 0 || size > buffer.Length - offset) {
  1211.                 throw new ArgumentOutOfRangeException("size");
  1212.             }
  1213.            
  1214.             ValidateBlockingMode();
  1215.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SendTo() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " size:" + size + " remoteEP:" + ValidationHelper.ToString(remoteEP));
  1216.            
  1217.             //That will check ConnectPermission for remoteEP
  1218.             EndPoint endPointSnapshot = remoteEP;
  1219.             SocketAddress socketAddress = CheckCacheRemote(ref endPointSnapshot, false);
  1220.            
  1221.             // This can throw ObjectDisposedException.
  1222.             int bytesTransferred;
  1223.             unsafe {
  1224.                 if (buffer.Length == 0) {
  1225.                     bytesTransferred = UnsafeNclNativeMethods.OSSOCK.sendto(m_Handle.DangerousGetHandle(), null, 0, socketFlags, socketAddress.m_Buffer, socketAddress.m_Size);
  1226.                 }
  1227.                 else {
  1228.                     fixed (byte* pinnedBuffer = buffer) {
  1229.                         bytesTransferred = UnsafeNclNativeMethods.OSSOCK.sendto(m_Handle.DangerousGetHandle(), pinnedBuffer + offset, size, socketFlags, socketAddress.m_Buffer, socketAddress.m_Size);
  1230.                     }
  1231.                 }
  1232.             }
  1233.            
  1234.             //
  1235.             // if the native call fails we'll throw a SocketException
  1236.             //
  1237.             if ((SocketError)bytesTransferred == SocketError.SocketError) {
  1238.                 //
  1239.                 // update our internal state after this socket error and throw
  1240.                 //
  1241.                 SocketException socketException = new SocketException();
  1242.                 UpdateStatusAfterSocketError(socketException);
  1243.                 if (Logging.On)
  1244.                     Logging.Exception(Logging.Sockets, this, "SendTo", socketException);
  1245.                 throw socketException;
  1246.             }
  1247.            
  1248.             if (m_RightEndPoint == null) {
  1249.                 //
  1250.                 // save a copy of the EndPoint so we can use it for Create()
  1251.                 //
  1252.                 m_RightEndPoint = endPointSnapshot;
  1253.             }
  1254.            
  1255.            
  1256.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SendTo() returning bytesTransferred:" + bytesTransferred.ToString());
  1257.             if (Logging.On)
  1258.                 Logging.Dump(Logging.Sockets, this, "SendTo", buffer, offset, size);
  1259.             if (Logging.On)
  1260.                 Logging.Exit(Logging.Sockets, this, "SendTo", bytesTransferred);
  1261.             return bytesTransferred;
  1262.         }
  1263.        
  1264.         /// <devdoc>
  1265.         /// <para>Sends data to a specific end point, starting at the indicated location in the data.</para>
  1266.         /// </devdoc>
  1267.         public int SendTo(byte[] buffer, int size, SocketFlags socketFlags, EndPoint remoteEP)
  1268.         {
  1269.             return SendTo(buffer, 0, size, socketFlags, remoteEP);
  1270.         }
  1271.         /// <devdoc>
  1272.         /// <para>[To be supplied.]</para>
  1273.         /// </devdoc>
  1274.         public int SendTo(byte[] buffer, SocketFlags socketFlags, EndPoint remoteEP)
  1275.         {
  1276.             return SendTo(buffer, 0, buffer != null ? buffer.Length : 0, socketFlags, remoteEP);
  1277.         }
  1278.         /// <devdoc>
  1279.         /// <para>[To be supplied.]</para>
  1280.         /// </devdoc>
  1281.         public int SendTo(byte[] buffer, EndPoint remoteEP)
  1282.         {
  1283.             return SendTo(buffer, 0, buffer != null ? buffer.Length : 0, SocketFlags.None, remoteEP);
  1284.         }
  1285.        
  1286.        
  1287.         /// <devdoc>
  1288.         /// <para>Receives data from a connected socket.</para>
  1289.         /// </devdoc>
  1290.         public int Receive(byte[] buffer, int size, SocketFlags socketFlags)
  1291.         {
  1292.             return Receive(buffer, 0, size, socketFlags);
  1293.         }
  1294.         /// <devdoc>
  1295.         /// <para>[To be supplied.]</para>
  1296.         /// </devdoc>
  1297.         public int Receive(byte[] buffer, SocketFlags socketFlags)
  1298.         {
  1299.             return Receive(buffer, 0, buffer != null ? buffer.Length : 0, socketFlags);
  1300.         }
  1301.         /// <devdoc>
  1302.         /// <para>[To be supplied.]</para>
  1303.         /// </devdoc>
  1304.         public int Receive(byte[] buffer)
  1305.         {
  1306.             return Receive(buffer, 0, buffer != null ? buffer.Length : 0, SocketFlags.None);
  1307.         }
  1308.        
  1309.         /// <devdoc>
  1310.         /// <para>Receives data from a connected socket into a specific location of the receive
  1311.         /// buffer.</para>
  1312.         /// </devdoc>
  1313.        
  1314.         public int Receive(byte[] buffer, int offset, int size, SocketFlags socketFlags)
  1315.         {
  1316.             SocketError errorCode;
  1317.             int bytesTransferred = Receive(buffer, offset, size, socketFlags, out errorCode);
  1318.             if (errorCode != SocketError.Success) {
  1319.                 throw new SocketException(errorCode);
  1320.             }
  1321.             return bytesTransferred;
  1322.         }
  1323.        
  1324.        
  1325.         public int Receive(byte[] buffer, int offset, int size, SocketFlags socketFlags, out SocketError errorCode)
  1326.         {
  1327.             if (Logging.On)
  1328.                 Logging.Enter(Logging.Sockets, this, "Receive", "");
  1329.             if (CleanedUp) {
  1330.                 throw new ObjectDisposedException(this.GetType().FullName);
  1331.             }
  1332.             //
  1333.             // parameter validation
  1334.             //
  1335.            
  1336.             if (buffer == null) {
  1337.                 throw new ArgumentNullException("buffer");
  1338.             }
  1339.             if (offset < 0 || offset > buffer.Length) {
  1340.                 throw new ArgumentOutOfRangeException("offset");
  1341.             }
  1342.             if (size < 0 || size > buffer.Length - offset) {
  1343.                 throw new ArgumentOutOfRangeException("size");
  1344.             }
  1345.            
  1346.            
  1347.             ValidateBlockingMode();
  1348.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Receive() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " DST:" + ValidationHelper.ToString(RemoteEndPoint) + " size:" + size);
  1349.            
  1350.             // This can throw ObjectDisposedException.
  1351.             int bytesTransferred;
  1352.             errorCode = SocketError.Success;
  1353.             unsafe {
  1354.                 if (buffer.Length == 0) {
  1355.                     bytesTransferred = UnsafeNclNativeMethods.OSSOCK.recv(m_Handle.DangerousGetHandle(), null, 0, socketFlags);
  1356.                 }
  1357.                 else
  1358.                     fixed (byte* pinnedBuffer = buffer) {
  1359.                         bytesTransferred = UnsafeNclNativeMethods.OSSOCK.recv(m_Handle.DangerousGetHandle(), pinnedBuffer + offset, size, socketFlags);
  1360.                     }
  1361.             }
  1362.            
  1363.             if ((SocketError)bytesTransferred == SocketError.SocketError) {
  1364.                 //
  1365.                 // update our internal state after this socket error and throw
  1366.                 //
  1367.                 errorCode = (SocketError)Marshal.GetLastWin32Error();
  1368.                 UpdateStatusAfterSocketError(errorCode);
  1369.                 if (Logging.On) {
  1370.                     Logging.Exception(Logging.Sockets, this, "Receive", new SocketException(errorCode));
  1371.                     Logging.Exit(Logging.Sockets, this, "Receive", 0);
  1372.                 }
  1373.                 return 0;
  1374.             }
  1375.            
  1376.            
  1377.            
  1378.             if (Logging.On)
  1379.                 Logging.Dump(Logging.Sockets, this, "Receive", buffer, offset, bytesTransferred);
  1380.             if (Logging.On)
  1381.                 Logging.Exit(Logging.Sockets, this, "Receive", bytesTransferred);
  1382.            
  1383.             return bytesTransferred;
  1384.         }
  1385.        
  1386.        
  1387.         public int Receive(IList<ArraySegment<byte>> buffers)
  1388.         {
  1389.             return Receive(buffers, SocketFlags.None);
  1390.         }
  1391.        
  1392.        
  1393.         [CLSCompliant(false)]
  1394.         public int Receive(IList<ArraySegment<byte>> buffers, SocketFlags socketFlags)
  1395.         {
  1396.             SocketError errorCode;
  1397.             int bytesTransferred = Receive(buffers, socketFlags, out errorCode);
  1398.             if (errorCode != SocketError.Success) {
  1399.                 throw new SocketException(errorCode);
  1400.             }
  1401.             return bytesTransferred;
  1402.         }
  1403.        
  1404.         [CLSCompliant(false)]
  1405.         public int Receive(IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode)
  1406.         {
  1407.             if (Logging.On)
  1408.                 Logging.Enter(Logging.Sockets, this, "Receive", "");
  1409.             if (CleanedUp) {
  1410.                 throw new ObjectDisposedException(this.GetType().FullName);
  1411.             }
  1412.            
  1413.             if (buffers == null) {
  1414.                 throw new ArgumentNullException("buffers");
  1415.             }
  1416.            
  1417.             if (buffers.Count == 0) {
  1418.                 throw new ArgumentException(SR.GetString(SR.net_sockets_zerolist, "buffers"), "buffers");
  1419.             }
  1420.            
  1421.            
  1422.             ValidateBlockingMode();
  1423.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Receive() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " DST:" + ValidationHelper.ToString(RemoteEndPoint));
  1424.            
  1425.             //make sure we don't let the app mess up the buffer array enough to cause
  1426.             //corruption.
  1427.             int count = buffers.Count;
  1428.             WSABuffer[] WSABuffers = new WSABuffer[count];
  1429.             GCHandle[] objectsToPin = null;
  1430.             int bytesTransferred;
  1431.             errorCode = SocketError.Success;
  1432.            
  1433.             try {
  1434.                 objectsToPin = new GCHandle[count];
  1435.                 for (int i = 0; i < count; ++i) {
  1436.                     ArraySegment<byte> buffer = buffers[i];
  1437.                     objectsToPin[i] = GCHandle.Alloc(buffer.Array, GCHandleType.Pinned);
  1438.                     WSABuffers[i].Length = buffer.Count;
  1439.                     WSABuffers[i].Pointer = Marshal.UnsafeAddrOfPinnedArrayElement(buffer.Array, buffer.Offset);
  1440.                 }
  1441.                
  1442.                 // This can throw ObjectDisposedException.
  1443.                 errorCode = UnsafeNclNativeMethods.OSSOCK.WSARecv_Blocking(m_Handle.DangerousGetHandle(), WSABuffers, buffers.Count, out bytesTransferred, ref socketFlags, IntPtr.Zero, IntPtr.Zero);
  1444.                
  1445.                 if ((SocketError)errorCode == SocketError.SocketError) {
  1446.                     errorCode = (SocketError)Marshal.GetLastWin32Error();
  1447.                 }
  1448.             }
  1449.             finally {
  1450.                 if (objectsToPin != null)
  1451.                     for (int i = 0; i < objectsToPin.Length; ++i)
  1452.                         if (objectsToPin[i].IsAllocated)
  1453.                             objectsToPin[i].Free();
  1454.             }
  1455.            
  1456.             if (errorCode != SocketError.Success) {
  1457.                 //
  1458.                 // update our internal state after this socket error and throw
  1459.                 //
  1460.                 UpdateStatusAfterSocketError(errorCode);
  1461.                 if (Logging.On) {
  1462.                     Logging.Exception(Logging.Sockets, this, "Receive", new SocketException(errorCode));
  1463.                     Logging.Exit(Logging.Sockets, this, "Receive", 0);
  1464.                 }
  1465.                 return 0;
  1466.             }
  1467.            
  1468.            
  1469.            
  1470.            
  1471.            
  1472.             if (Logging.On)
  1473.                 Logging.Exit(Logging.Sockets, this, "Receive", bytesTransferred);
  1474.            
  1475.             return bytesTransferred;
  1476.         }
  1477.        
  1478.        
  1479.        
  1480.        
  1481.         /// <devdoc>
  1482.         /// <para>Receives a datagram into a specific location in the data buffer and stores
  1483.         /// the end point.</para>
  1484.         /// </devdoc>
  1485.         public int ReceiveMessageFrom(byte[] buffer, int offset, int size, ref SocketFlags socketFlags, ref EndPoint remoteEP, out IPPacketInformation ipPacketInformation)
  1486.         {
  1487.             if (Logging.On)
  1488.                 Logging.Enter(Logging.Sockets, this, "ReceiveMessageFrom", "");
  1489.            
  1490.             if (CleanedUp) {
  1491.                 throw new ObjectDisposedException(this.GetType().FullName);
  1492.             }
  1493.             if (buffer == null) {
  1494.                 throw new ArgumentNullException("buffer");
  1495.             }
  1496.             if (remoteEP == null) {
  1497.                 throw new ArgumentNullException("remoteEP");
  1498.             }
  1499.             if (offset < 0 || offset > buffer.Length) {
  1500.                 throw new ArgumentOutOfRangeException("offset");
  1501.             }
  1502.             if (size < 0 || size > buffer.Length - offset) {
  1503.                 throw new ArgumentOutOfRangeException("size");
  1504.             }
  1505.             if (m_RightEndPoint == null) {
  1506.                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustbind));
  1507.             }
  1508.            
  1509.            
  1510.             ValidateBlockingMode();
  1511.            
  1512.             // This will check the permissions for connect.
  1513.             EndPoint endPointSnapshot = remoteEP;
  1514.             SocketAddress socketAddress = CheckCacheRemote(ref endPointSnapshot, false);
  1515.            
  1516.             ReceiveMessageOverlappedAsyncResult asyncResult = new ReceiveMessageOverlappedAsyncResult(this, null, null);
  1517.             asyncResult.SetUnmanagedStructures(buffer, offset, size, socketAddress, socketFlags);
  1518.            
  1519.             // save a copy of the original EndPoint
  1520.             SocketAddress socketAddressOriginal = endPointSnapshot.Serialize();
  1521.            
  1522.             //setup structure
  1523.             int bytesTransfered = 0;
  1524.             SocketError errorCode = SocketError.Success;
  1525.            
  1526.             if (addressFamily == AddressFamily.InterNetwork) {
  1527.                 SetSocketOption(SocketOptionLevel.IP, SocketOptionName.PacketInformation, true);
  1528.             }
  1529.             else if (addressFamily == AddressFamily.InterNetworkV6) {
  1530.                 SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.PacketInformation, true);
  1531.             }
  1532.            
  1533.             try {
  1534.                 // This can throw ObjectDisposedException (retrieving the delegate AND resolving the handle).
  1535.                 if (WSARecvMsg_Blocking(m_Handle.DangerousGetHandle(), Marshal.UnsafeAddrOfPinnedArrayElement(asyncResult.m_MessageBuffer, 0), out bytesTransfered, IntPtr.Zero, IntPtr.Zero) == SocketError.SocketError) {
  1536.                     errorCode = (SocketError)Marshal.GetLastWin32Error();
  1537.                 }
  1538.             }
  1539.             finally {
  1540.                 asyncResult.SyncReleaseUnmanagedStructures();
  1541.             }
  1542.            
  1543.            
  1544.             //
  1545.             // if the native call fails we'll throw a SocketException
  1546.             //
  1547.             if (errorCode != SocketError.Success && errorCode != SocketError.MessageSize) {
  1548.                 //
  1549.                 // update our internal state after this socket error and throw
  1550.                 //
  1551.                 SocketException socketException = new SocketException(errorCode);
  1552.                 UpdateStatusAfterSocketError(socketException);
  1553.                 if (Logging.On)
  1554.                     Logging.Exception(Logging.Sockets, this, "ReceiveMessageFrom", socketException);
  1555.                 throw socketException;
  1556.             }
  1557.            
  1558.            
  1559.             if (!socketAddressOriginal.Equals(asyncResult.m_SocketAddress)) {
  1560.                 try {
  1561.                     remoteEP = endPointSnapshot.Create(asyncResult.m_SocketAddress);
  1562.                 }
  1563.                 catch {
  1564.                 }
  1565.                 if (m_RightEndPoint == null) {
  1566.                     //
  1567.                     // save a copy of the EndPoint so we can use it for Create()
  1568.                     //
  1569.                     m_RightEndPoint = endPointSnapshot;
  1570.                 }
  1571.             }
  1572.            
  1573.             socketFlags = asyncResult.m_flags;
  1574.             ipPacketInformation = asyncResult.m_IPPacketInformation;
  1575.            
  1576.             if (Logging.On)
  1577.                 Logging.Exit(Logging.Sockets, this, "ReceiveMessageFrom", errorCode);
  1578.             return bytesTransfered;
  1579.         }
  1580.        
  1581.         /// <devdoc>
  1582.         /// <para>Receives a datagram into a specific location in the data buffer and stores
  1583.         /// the end point.</para>
  1584.         /// </devdoc>
  1585.         public int ReceiveFrom(byte[] buffer, int offset, int size, SocketFlags socketFlags, ref EndPoint remoteEP)
  1586.         {
  1587.             if (Logging.On)
  1588.                 Logging.Enter(Logging.Sockets, this, "ReceiveFrom", "");
  1589.             if (CleanedUp) {
  1590.                 throw new ObjectDisposedException(this.GetType().FullName);
  1591.             }
  1592.             //
  1593.             // parameter validation
  1594.             //
  1595.             if (buffer == null) {
  1596.                 throw new ArgumentNullException("buffer");
  1597.             }
  1598.             if (remoteEP == null) {
  1599.                 throw new ArgumentNullException("remoteEP");
  1600.             }
  1601.             if (offset < 0 || offset > buffer.Length) {
  1602.                 throw new ArgumentOutOfRangeException("offset");
  1603.             }
  1604.             if (size < 0 || size > buffer.Length - offset) {
  1605.                 throw new ArgumentOutOfRangeException("size");
  1606.             }
  1607.             if (m_RightEndPoint == null) {
  1608.                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustbind));
  1609.             }
  1610.            
  1611.            
  1612.             ValidateBlockingMode();
  1613.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::ReceiveFrom() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " size:" + size + " remoteEP:" + remoteEP.ToString());
  1614.            
  1615.             // This will check the permissions for connect.
  1616.             // We need this because remoteEP may differ from one used in Connect or
  1617.             // there was no Connect called.
  1618.             EndPoint endPointSnapshot = remoteEP;
  1619.             SocketAddress socketAddress = CheckCacheRemote(ref endPointSnapshot, false);
  1620.             SocketAddress socketAddressOriginal = endPointSnapshot.Serialize();
  1621.            
  1622.             // This can throw ObjectDisposedException.
  1623.             int bytesTransferred;
  1624.             unsafe {
  1625.                 if (buffer.Length == 0)
  1626.                     bytesTransferred = UnsafeNclNativeMethods.OSSOCK.recvfrom(m_Handle.DangerousGetHandle(), null, 0, socketFlags, socketAddress.m_Buffer, ref socketAddress.m_Size);
  1627.                 else
  1628.                     fixed (byte* pinnedBuffer = buffer) {
  1629.                         bytesTransferred = UnsafeNclNativeMethods.OSSOCK.recvfrom(m_Handle.DangerousGetHandle(), pinnedBuffer + offset, size, socketFlags, socketAddress.m_Buffer, ref socketAddress.m_Size);
  1630.                     }
  1631.             }
  1632.            
  1633.             // If the native call fails we'll throw a SocketException.
  1634.             // Must do this immediately after the native call so that the SocketException() constructor can pick up the error code.
  1635.             SocketException socketException = null;
  1636.             if ((SocketError)bytesTransferred == SocketError.SocketError) {
  1637.                 socketException = new SocketException();
  1638.                 UpdateStatusAfterSocketError(socketException);
  1639.                 if (Logging.On)
  1640.                     Logging.Exception(Logging.Sockets, this, "ReceiveFrom", socketException);
  1641.                
  1642.                 if (socketException.ErrorCode != (int)SocketError.MessageSize) {
  1643.                     throw socketException;
  1644.                 }
  1645.             }
  1646.            
  1647.             if (!socketAddressOriginal.Equals(socketAddress)) {
  1648.                 try {
  1649.                     remoteEP = endPointSnapshot.Create(socketAddress);
  1650.                 }
  1651.                 catch {
  1652.                 }
  1653.                 if (m_RightEndPoint == null) {
  1654.                     //
  1655.                     // save a copy of the EndPoint so we can use it for Create()
  1656.                     //
  1657.                     m_RightEndPoint = endPointSnapshot;
  1658.                 }
  1659.             }
  1660.            
  1661.             if (socketException != null) {
  1662.                 throw socketException;
  1663.             }
  1664.            
  1665.            
  1666.            
  1667.             if (Logging.On)
  1668.                 Logging.Dump(Logging.Sockets, this, "ReceiveFrom", buffer, offset, size);
  1669.             if (Logging.On)
  1670.                 Logging.Exit(Logging.Sockets, this, "ReceiveFrom", bytesTransferred);
  1671.             return bytesTransferred;
  1672.         }
  1673.        
  1674.        
  1675.        
  1676.         /// <devdoc>
  1677.         /// <para>Receives a datagram and stores the source end point.</para>
  1678.         /// </devdoc>
  1679.         public int ReceiveFrom(byte[] buffer, int size, SocketFlags socketFlags, ref EndPoint remoteEP)
  1680.         {
  1681.             return ReceiveFrom(buffer, 0, size, socketFlags, ref remoteEP);
  1682.         }
  1683.         /// <devdoc>
  1684.         /// <para>[To be supplied.]</para>
  1685.         /// </devdoc>
  1686.         public int ReceiveFrom(byte[] buffer, SocketFlags socketFlags, ref EndPoint remoteEP)
  1687.         {
  1688.             return ReceiveFrom(buffer, 0, buffer != null ? buffer.Length : 0, socketFlags, ref remoteEP);
  1689.         }
  1690.         /// <devdoc>
  1691.         /// <para>[To be supplied.]</para>
  1692.         /// </devdoc>
  1693.         public int ReceiveFrom(byte[] buffer, ref EndPoint remoteEP)
  1694.         {
  1695.             return ReceiveFrom(buffer, 0, buffer != null ? buffer.Length : 0, SocketFlags.None, ref remoteEP);
  1696.         }
  1697.        
  1698.         // UE
  1699.         /// <devdoc>
  1700.         /// <para>[To be supplied.]</para>
  1701.         /// </devdoc>
  1702.         public int IOControl(int ioControlCode, byte[] optionInValue, byte[] optionOutValue)
  1703.         {
  1704.             if (CleanedUp) {
  1705.                 throw new ObjectDisposedException(this.GetType().FullName);
  1706.             }
  1707.             if (ioControlCode == IoctlSocketConstants.FIONBIO) {
  1708.                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_useblocking));
  1709.             }
  1710.            
  1711.             ExceptionHelper.UnmanagedPermission.Demand();
  1712.            
  1713.             int realOptionLength = 0;
  1714.            
  1715.             // This can throw ObjectDisposedException.
  1716.             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.WSAIoctl_Blocking(m_Handle.DangerousGetHandle(), ioControlCode, optionInValue, optionInValue != null ? optionInValue.Length : 0, optionOutValue, optionOutValue != null ? optionOutValue.Length : 0, out realOptionLength, IntPtr.Zero, IntPtr.Zero);
  1717.            
  1718.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::IOControl() UnsafeNclNativeMethods.OSSOCK.WSAIoctl returns errorCode:" + errorCode);
  1719.            
  1720.             //
  1721.             // if the native call fails we'll throw a SocketException
  1722.             //
  1723.             if (errorCode == SocketError.SocketError) {
  1724.                 //
  1725.                 // update our internal state after this socket error and throw
  1726.                 //
  1727.                 SocketException socketException = new SocketException();
  1728.                 UpdateStatusAfterSocketError(socketException);
  1729.                 if (Logging.On)
  1730.                     Logging.Exception(Logging.Sockets, this, "IOControl", socketException);
  1731.                 throw socketException;
  1732.             }
  1733.            
  1734.             return realOptionLength;
  1735.         }
  1736.        
  1737.         // UE
  1738.         /// <devdoc>
  1739.         /// <para>[To be supplied.]</para>
  1740.         /// </devdoc>
  1741.         public int IOControl(IOControlCode ioControlCode, byte[] optionInValue, byte[] optionOutValue)
  1742.         {
  1743.             return IOControl(unchecked((int)ioControlCode), optionInValue, optionOutValue);
  1744.         }
  1745.        
  1746.        
  1747.        
  1748.        
  1749.         /// <devdoc>
  1750.         /// <para>
  1751.         /// Sets the specified option to the specified value.
  1752.         /// </para>
  1753.         /// </devdoc>
  1754.         public void SetSocketOption(SocketOptionLevel optionLevel, SocketOptionName optionName, int optionValue)
  1755.         {
  1756.             if (CleanedUp) {
  1757.                 throw new ObjectDisposedException(this.GetType().FullName);
  1758.             }
  1759.             CheckSetOptionPermissions(optionLevel, optionName);
  1760.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SetSocketOption(): optionLevel:" + optionLevel.ToString() + " optionName:" + optionName.ToString() + " optionValue:" + optionValue.ToString());
  1761.             SetSocketOption(optionLevel, optionName, optionValue, false);
  1762.         }
  1763.        
  1764.        
  1765.         /// <devdoc>
  1766.         /// <para>[To be supplied.]</para>
  1767.         /// </devdoc>
  1768.         public void SetSocketOption(SocketOptionLevel optionLevel, SocketOptionName optionName, byte[] optionValue)
  1769.         {
  1770.             if (CleanedUp) {
  1771.                 throw new ObjectDisposedException(this.GetType().FullName);
  1772.             }
  1773.            
  1774.             CheckSetOptionPermissions(optionLevel, optionName);
  1775.            
  1776.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SetSocketOption(): optionLevel:" + optionLevel.ToString() + " optionName:" + optionName.ToString() + " optionValue:" + optionValue.ToString());
  1777.            
  1778.             // This can throw ObjectDisposedException.
  1779.             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.setsockopt(m_Handle, optionLevel, optionName, optionValue, optionValue != null ? optionValue.Length : 0);
  1780.            
  1781.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SetSocketOption() UnsafeNclNativeMethods.OSSOCK.setsockopt returns errorCode:" + errorCode);
  1782.            
  1783.             //
  1784.             // if the native call fails we'll throw a SocketException
  1785.             //
  1786.             if (errorCode == SocketError.SocketError) {
  1787.                 //
  1788.                 // update our internal state after this socket error and throw
  1789.                 //
  1790.                 SocketException socketException = new SocketException();
  1791.                 UpdateStatusAfterSocketError(socketException);
  1792.                 if (Logging.On)
  1793.                     Logging.Exception(Logging.Sockets, this, "SetSocketOption", socketException);
  1794.                 throw socketException;
  1795.             }
  1796.         }
  1797.        
  1798.         /// <devdoc>
  1799.         /// <para>Sets the specified option to the specified value.</para>
  1800.         /// </devdoc>
  1801.        
  1802.         public void SetSocketOption(SocketOptionLevel optionLevel, SocketOptionName optionName, bool optionValue)
  1803.         {
  1804.             SetSocketOption(optionLevel, optionName, (optionValue ? 1 : 0));
  1805.         }
  1806.        
  1807.         /// <devdoc>
  1808.         /// <para>Sets the specified option to the specified value.</para>
  1809.         /// </devdoc>
  1810.         public void SetSocketOption(SocketOptionLevel optionLevel, SocketOptionName optionName, object optionValue)
  1811.         {
  1812.             if (CleanedUp) {
  1813.                 throw new ObjectDisposedException(this.GetType().FullName);
  1814.             }
  1815.             //
  1816.             // parameter validation
  1817.             //
  1818.             if (optionValue == null) {
  1819.                 throw new ArgumentNullException("optionValue");
  1820.             }
  1821.            
  1822.             CheckSetOptionPermissions(optionLevel, optionName);
  1823.            
  1824.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SetSocketOption(): optionLevel:" + optionLevel.ToString() + " optionName:" + optionName.ToString() + " optionValue:" + optionValue.ToString());
  1825.            
  1826.             if (optionLevel == SocketOptionLevel.Socket && optionName == SocketOptionName.Linger) {
  1827.                 LingerOption lingerOption = optionValue as LingerOption;
  1828.                 if (lingerOption == null) {
  1829.                     throw new ArgumentException(SR.GetString(SR.net_sockets_invalid_optionValue, "LingerOption"), "optionValue");
  1830.                 }
  1831.                 if (lingerOption.LingerTime < 0 || lingerOption.LingerTime > (int)UInt16.MaxValue) {
  1832.                     throw new ArgumentException(SR.GetString(SR.ArgumentOutOfRange_Bounds_Lower_Upper, 0, (int)UInt16.MaxValue), "optionValue.LingerTime");
  1833.                 }
  1834.                 setLingerOption(lingerOption);
  1835.             }
  1836.             else if (optionLevel == SocketOptionLevel.IP && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
  1837.                 MulticastOption multicastOption = optionValue as MulticastOption;
  1838.                 if (multicastOption == null) {
  1839.                     throw new ArgumentException(SR.GetString(SR.net_sockets_invalid_optionValue, "MulticastOption"), "optionValue");
  1840.                 }
  1841.                 setMulticastOption(optionName, multicastOption);
  1842.             }
  1843.             //
  1844.             // IPv6 Changes: Handle IPv6 Multicast Add / Drop
  1845.             //
  1846.             else if (optionLevel == SocketOptionLevel.IPv6 && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
  1847.                 IPv6MulticastOption multicastOption = optionValue as IPv6MulticastOption;
  1848.                 if (multicastOption == null) {
  1849.                     throw new ArgumentException(SR.GetString(SR.net_sockets_invalid_optionValue, "IPv6MulticastOption"), "optionValue");
  1850.                 }
  1851.                 setIPv6MulticastOption(optionName, multicastOption);
  1852.             }
  1853.             else {
  1854.                 throw new ArgumentException(SR.GetString(SR.net_sockets_invalid_optionValue_all), "optionValue");
  1855.             }
  1856.         }
  1857.        
  1858.        
  1859.         /// <devdoc>
  1860.         /// <para>
  1861.         /// Gets the value of a socket option.
  1862.         /// </para>
  1863.         /// </devdoc>
  1864.         // UE
  1865.         public object GetSocketOption(SocketOptionLevel optionLevel, SocketOptionName optionName)
  1866.         {
  1867.             if (CleanedUp) {
  1868.                 throw new ObjectDisposedException(this.GetType().FullName);
  1869.             }
  1870.             if (optionLevel == SocketOptionLevel.Socket && optionName == SocketOptionName.Linger) {
  1871.                 return getLingerOpt();
  1872.             }
  1873.             else if (optionLevel == SocketOptionLevel.IP && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
  1874.                 return getMulticastOpt(optionName);
  1875.             }
  1876.             //
  1877.             // Handle IPv6 case
  1878.             //
  1879.             else if (optionLevel == SocketOptionLevel.IPv6 && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
  1880.                 return getIPv6MulticastOpt(optionName);
  1881.             }
  1882.             else {
  1883.                 int optionValue = 0;
  1884.                 int optionLength = 4;
  1885.                
  1886.                 // This can throw ObjectDisposedException.
  1887.                 SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.getsockopt(m_Handle, optionLevel, optionName, out optionValue, ref optionLength);
  1888.                
  1889.                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::GetSocketOption() UnsafeNclNativeMethods.OSSOCK.getsockopt returns errorCode:" + errorCode);
  1890.                
  1891.                 //
  1892.                 // if the native call fails we'll throw a SocketException
  1893.                 //
  1894.                 if (errorCode == SocketError.SocketError) {
  1895.                     //
  1896.                     // update our internal state after this socket error and throw
  1897.                     //
  1898.                     SocketException socketException = new SocketException();
  1899.                     UpdateStatusAfterSocketError(socketException);
  1900.                     if (Logging.On)
  1901.                         Logging.Exception(Logging.Sockets, this, "GetSocketOption", socketException);
  1902.                     throw socketException;
  1903.                 }
  1904.                
  1905.                 return optionValue;
  1906.             }
  1907.         }
  1908.        
  1909.         // UE
  1910.         /// <devdoc>
  1911.         /// <para>[To be supplied.]</para>
  1912.         /// </devdoc>
  1913.         public void GetSocketOption(SocketOptionLevel optionLevel, SocketOptionName optionName, byte[] optionValue)
  1914.         {
  1915.             if (CleanedUp) {
  1916.                 throw new ObjectDisposedException(this.GetType().FullName);
  1917.             }
  1918.            
  1919.             int optionLength = optionValue != null ? optionValue.Length : 0;
  1920.            
  1921.             // This can throw ObjectDisposedException.
  1922.             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.getsockopt(m_Handle, optionLevel, optionName, optionValue, ref optionLength);
  1923.            
  1924.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::GetSocketOption() UnsafeNclNativeMethods.OSSOCK.getsockopt returns errorCode:" + errorCode);
  1925.            
  1926.             //
  1927.             // if the native call fails we'll throw a SocketException
  1928.             //
  1929.             if (errorCode == SocketError.SocketError) {
  1930.                 //
  1931.                 // update our internal state after this socket error and throw
  1932.                 //
  1933.                 SocketException socketException = new SocketException();
  1934.                 UpdateStatusAfterSocketError(socketException);
  1935.                 if (Logging.On)
  1936.                     Logging.Exception(Logging.Sockets, this, "GetSocketOption", socketException);
  1937.                 throw socketException;
  1938.             }
  1939.         }
  1940.        
  1941.         // UE
  1942.         /// <devdoc>
  1943.         /// <para>[To be supplied.]</para>
  1944.         /// </devdoc>
  1945.         public byte[] GetSocketOption(SocketOptionLevel optionLevel, SocketOptionName optionName, int optionLength)
  1946.         {
  1947.             if (CleanedUp) {
  1948.                 throw new ObjectDisposedException(this.GetType().FullName);
  1949.             }
  1950.            
  1951.             byte[] optionValue = new byte[optionLength];
  1952.             int realOptionLength = optionLength;
  1953.            
  1954.             // This can throw ObjectDisposedException.
  1955.             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.getsockopt(m_Handle, optionLevel, optionName, optionValue, ref realOptionLength);
  1956.            
  1957.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::GetSocketOption() UnsafeNclNativeMethods.OSSOCK.getsockopt returns errorCode:" + errorCode);
  1958.            
  1959.             //
  1960.             // if the native call fails we'll throw a SocketException
  1961.             //
  1962.             if (errorCode == SocketError.SocketError) {
  1963.                 //
  1964.                 // update our internal state after this socket error and throw
  1965.                 //
  1966.                 SocketException socketException = new SocketException();
  1967.                 UpdateStatusAfterSocketError(socketException);
  1968.                 if (Logging.On)
  1969.                     Logging.Exception(Logging.Sockets, this, "GetSocketOption", socketException);
  1970.                 throw socketException;
  1971.             }
  1972.            
  1973.             if (optionLength != realOptionLength) {
  1974.                 byte[] newOptionValue = new byte[realOptionLength];
  1975.                 Buffer.BlockCopy(optionValue, 0, newOptionValue, 0, realOptionLength);
  1976.                 optionValue = newOptionValue;
  1977.             }
  1978.            
  1979.             return optionValue;
  1980.         }
  1981.        
  1982.        
  1983.         /// <devdoc>
  1984.         /// <para>
  1985.         /// Determines the status of the socket.
  1986.         /// </para>
  1987.         /// </devdoc>
  1988.         public bool Poll(int microSeconds, SelectMode mode)
  1989.         {
  1990.             if (CleanedUp) {
  1991.                 throw new ObjectDisposedException(this.GetType().FullName);
  1992.             }
  1993.            
  1994.             IntPtr handle = m_Handle.DangerousGetHandle();
  1995.             IntPtr[] fileDescriptorSet = new IntPtr[2] {(IntPtr)1, handle};
  1996.             TimeValue IOwait = new TimeValue();
  1997.            
  1998.             //
  1999.             // negative timeout value implies indefinite wait
  2000.             //
  2001.             int socketCount;
  2002.             if (microSeconds != -1) {
  2003.                 MicrosecondsToTimeValue((long)(uint)microSeconds, ref IOwait);
  2004.                 socketCount = UnsafeNclNativeMethods.OSSOCK.select(0, mode == SelectMode.SelectRead ? fileDescriptorSet : null, mode == SelectMode.SelectWrite ? fileDescriptorSet : null, mode == SelectMode.SelectError ? fileDescriptorSet : null, ref IOwait);
  2005.             }
  2006.             else {
  2007.                 socketCount = UnsafeNclNativeMethods.OSSOCK.select(0, mode == SelectMode.SelectRead ? fileDescriptorSet : null, mode == SelectMode.SelectWrite ? fileDescriptorSet : null, mode == SelectMode.SelectError ? fileDescriptorSet : null, IntPtr.Zero);
  2008.             }
  2009.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Poll() UnsafeNclNativeMethods.OSSOCK.select returns socketCount:" + socketCount);
  2010.            
  2011.             //
  2012.             // if the native call fails we'll throw a SocketException
  2013.             //
  2014.             if ((SocketError)socketCount == SocketError.SocketError) {
  2015.                 //
  2016.                 // update our internal state after this socket error and throw
  2017.                 //
  2018.                 SocketException socketException = new SocketException();
  2019.                 UpdateStatusAfterSocketError(socketException);
  2020.                 if (Logging.On)
  2021.                     Logging.Exception(Logging.Sockets, this, "Poll", socketException);
  2022.                 throw socketException;
  2023.             }
  2024.             if ((int)fileDescriptorSet[0] == 0) {
  2025.                 return false;
  2026.             }
  2027.             return fileDescriptorSet[1] == handle;
  2028.         }
  2029.        
  2030.         /// <devdoc>
  2031.         /// <para>Determines the status of a socket.</para>
  2032.         /// </devdoc>
  2033.         public static void Select(IList checkRead, IList checkWrite, IList checkError, int microSeconds)
  2034.         {
  2035.             // parameter validation
  2036.             if ((checkRead == null || checkRead.Count == 0) && (checkWrite == null || checkWrite.Count == 0) && (checkError == null || checkError.Count == 0)) {
  2037.                 throw new ArgumentNullException(SR.GetString(SR.net_sockets_empty_select));
  2038.             }
  2039.             const int MaxSelect = 65536;
  2040.             if (checkRead != null && checkRead.Count > MaxSelect) {
  2041.                 throw new ArgumentOutOfRangeException(SR.GetString(SR.net_sockets_toolarge_select, "checkRead", MaxSelect.ToString(NumberFormatInfo.CurrentInfo)));
  2042.             }
  2043.             if (checkWrite != null && checkWrite.Count > MaxSelect) {
  2044.                 throw new ArgumentOutOfRangeException(SR.GetString(SR.net_sockets_toolarge_select, "checkWrite", MaxSelect.ToString(NumberFormatInfo.CurrentInfo)));
  2045.             }
  2046.             if (checkError != null && checkError.Count > MaxSelect) {
  2047.                 throw new ArgumentOutOfRangeException(SR.GetString(SR.net_sockets_toolarge_select, "checkError", MaxSelect.ToString(NumberFormatInfo.CurrentInfo)));
  2048.             }
  2049.             IntPtr[] readfileDescriptorSet = SocketListToFileDescriptorSet(checkRead);
  2050.             IntPtr[] writefileDescriptorSet = SocketListToFileDescriptorSet(checkWrite);
  2051.             IntPtr[] errfileDescriptorSet = SocketListToFileDescriptorSet(checkError);
  2052.            
  2053.             TimeValue IOwait = new TimeValue();
  2054.            
  2055.             // if negative, assume infinite
  2056.             if (microSeconds != -1) {
  2057.                 MicrosecondsToTimeValue((long)(uint)microSeconds, ref IOwait);
  2058.             }
  2059.            
  2060.                 // ignored value
  2061.             int socketCount = UnsafeNclNativeMethods.OSSOCK.select(0, readfileDescriptorSet, writefileDescriptorSet, errfileDescriptorSet, ref IOwait);
  2062.            
  2063.             GlobalLog.Print("Socket::Select() UnsafeNclNativeMethods.OSSOCK.select returns socketCount:" + socketCount);
  2064.            
  2065.             //
  2066.             // if the native call fails we'll throw a SocketException
  2067.             //
  2068.             if ((SocketError)socketCount == SocketError.SocketError) {
  2069.                 throw new SocketException();
  2070.             }
  2071.             SelectFileDescriptor(checkRead, readfileDescriptorSet);
  2072.             SelectFileDescriptor(checkWrite, writefileDescriptorSet);
  2073.             SelectFileDescriptor(checkError, errfileDescriptorSet);
  2074.         }
  2075.        
  2076.        
  2077.        
  2078.         //
  2079.         // Async Winsock Support, the following functions use either
  2080.         // the Async Winsock support to do overlapped I/O WSASend/WSARecv
  2081.         // or a WSAEventSelect call to enable selection and non-blocking mode
  2082.         // of otherwise normal Winsock calls.
  2083.         //
  2084.         // Currently the following Async Socket calls are supported:
  2085.         // Send, Recv, SendTo, RecvFrom, Connect, Accept
  2086.         //
  2087.        
  2088. /*++
  2089.         Routine Description:
  2090.           BeginConnect - Does a async winsock connect, by calling
  2091.           WSAEventSelect to enable Connect Events to signal an event and
  2092.           wake up a callback which involkes a callback.
  2093.             So note: This routine may go pending at which time,
  2094.             but any case the callback Delegate will be called upon completion
  2095.         Arguments:
  2096.           remoteEP - status line that we wish to parse
  2097.           Callback - Async Callback Delegate that is called upon Async Completion
  2098.           State - State used to track callback, set by caller, not required
  2099.         Return Value:
  2100.           IAsyncResult - Async result used to retreive result
  2101.         --*/       
  2102.        
  2103.        
  2104.         /// <devdoc>
  2105.         /// <para>[To be supplied.]</para>
  2106.         /// </devdoc>
  2107.         [HostProtection(ExternalThreading = true)]
  2108.         public IAsyncResult BeginConnect(EndPoint remoteEP, AsyncCallback callback, object state)
  2109.         {
  2110.             //
  2111.             // parameter validation
  2112.             //
  2113.             if (Logging.On)
  2114.                 Logging.Enter(Logging.Sockets, this, "BeginConnect", remoteEP);
  2115.            
  2116.             if (CleanedUp) {
  2117.                 throw new ObjectDisposedException(this.GetType().FullName);
  2118.             }
  2119.            
  2120.             if (remoteEP == null) {
  2121.                 throw new ArgumentNullException("remoteEP");
  2122.             }
  2123.            
  2124.             if (isListening) {
  2125.                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustnotlisten));
  2126.             }
  2127.            
  2128.             if (CanUseConnectEx(remoteEP)) {
  2129.                 return BeginConnectEx(remoteEP, true, callback, state);
  2130.             }
  2131.            
  2132.             // This will check the permissions for connect.
  2133.             EndPoint endPointSnapshot = remoteEP;
  2134.             SocketAddress socketAddress = CheckCacheRemote(ref endPointSnapshot, true);
  2135.            
  2136.             // Flow the context. No need to lock it since we don't use it until the callback.
  2137.             ConnectAsyncResult asyncResult = new ConnectAsyncResult(this, state, callback);
  2138.             asyncResult.StartPostingAsyncOp(false);
  2139.            
  2140.             // Post the connect.
  2141.             DoBeginConnect(endPointSnapshot, socketAddress, asyncResult);
  2142.            
  2143.             // We didn't throw, so finish the posting op. This will call the callback if the operation already completed.
  2144.             asyncResult.FinishPostingAsyncOp(ref Caches.ConnectClosureCache);
  2145.            
  2146.             if (Logging.On)
  2147.                 Logging.Exit(Logging.Sockets, this, "BeginConnect", asyncResult);
  2148.             return asyncResult;
  2149.         }
  2150.        
  2151.        
  2152.        
  2153.        
  2154.         public SocketInformation DuplicateAndClose(int targetProcessId)
  2155.         {
  2156.             if (Logging.On)
  2157.                 Logging.Enter(Logging.Sockets, this, "DuplicateAndClose", null);
  2158.            
  2159.             if (CleanedUp) {
  2160.                 throw new ObjectDisposedException(GetType().FullName);
  2161.             }
  2162.            
  2163.             ExceptionHelper.UnrestrictedSocketPermission.Demand();
  2164.            
  2165.             SocketInformation info = new SocketInformation();
  2166.             info.ProtocolInformation = new byte[protocolInformationSize];
  2167.            
  2168.             // This can throw ObjectDisposedException.
  2169.             SocketError errorCode;
  2170.             // ROTORTODO
  2171.             errorCode = SocketError.SocketError;
  2172.            
  2173.             if (errorCode != SocketError.Success) {
  2174.                 SocketException socketException = new SocketException();
  2175.                 if (Logging.On)
  2176.                     Logging.Exception(Logging.Sockets, this, "DuplicateAndClose", socketException);
  2177.                 throw socketException;
  2178.             }
  2179.            
  2180.            
  2181.             info.IsConnected = Connected;
  2182.             info.IsNonBlocking = !Blocking;
  2183.             info.IsListening = isListening;
  2184.             info.UseOnlyOverlappedIO = UseOnlyOverlappedIO;
  2185.            
  2186.             //make sure we don't shutdown, etc.
  2187.             Close(-1);
  2188.            
  2189.             if (Logging.On)
  2190.                 Logging.Exit(Logging.Sockets, this, "DuplicateAndClose", null);
  2191.             return info;
  2192.         }
  2193.        
  2194.        
  2195.        
  2196.        
  2197.         internal IAsyncResult UnsafeBeginConnect(EndPoint remoteEP, AsyncCallback callback, object state)
  2198.         {
  2199.             if (CanUseConnectEx(remoteEP)) {
  2200.                 return BeginConnectEx(remoteEP, false, callback, state);
  2201.             }
  2202.             EndPoint endPointSnapshot = remoteEP;
  2203.             SocketAddress socketAddress = SnapshotAndSerialize(ref endPointSnapshot);
  2204.            
  2205.             // No context flow here. Can use Lazy.
  2206.             ConnectAsyncResult asyncResult = new ConnectAsyncResult(this, state, callback);
  2207.             DoBeginConnect(endPointSnapshot, socketAddress, asyncResult);
  2208.             return asyncResult;
  2209.         }
  2210.        
  2211.         // Leaving the public logging as "BeginConnect" since that makes sense to the people looking at the output.
  2212.         // Private logging can remain "DoBeginConnect".
  2213.         private void DoBeginConnect(EndPoint endPointSnapshot, SocketAddress socketAddress, LazyAsyncResult asyncResult)
  2214.         {
  2215.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginConnect() endPointSnapshot:" + endPointSnapshot.ToString());
  2216.            
  2217.             EndPoint oldEndPoint = m_RightEndPoint;
  2218.            
  2219.             // get async going
  2220.             if (m_AcceptQueueOrConnectResult != null) {
  2221.                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_no_duplicate_async));
  2222.             }
  2223.            
  2224.             m_AcceptQueueOrConnectResult = asyncResult;
  2225.            
  2226.             if (!SetAsyncEventSelect(AsyncEventBits.FdConnect)) {
  2227.                 m_AcceptQueueOrConnectResult = null;
  2228.                 throw new ObjectDisposedException(this.GetType().FullName);
  2229.             }
  2230.            
  2231.             // This can throw ObjectDisposedException.
  2232.             IntPtr handle = m_Handle.DangerousGetHandle();
  2233.            
  2234.             if (m_RightEndPoint == null) {
  2235.                 m_RightEndPoint = endPointSnapshot;
  2236.             }
  2237.            
  2238.             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.WSAConnect(handle, socketAddress.m_Buffer, socketAddress.m_Size, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
  2239.            
  2240.             if (errorCode != SocketError.Success) {
  2241.                 errorCode = (SocketError)Marshal.GetLastWin32Error();
  2242.             }
  2243.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginConnect() UnsafeNclNativeMethods.OSSOCK.WSAConnect returns errorCode:" + errorCode);
  2244.            
  2245.             if (errorCode != SocketError.WouldBlock) {
  2246.                 bool completeSynchronously = true;
  2247.                 if (errorCode == SocketError.Success) {
  2248.                     SetToConnected();
  2249.                 }
  2250.                 else {
  2251.                     asyncResult.ErrorCode = (int)errorCode;
  2252.                 }
  2253.                
  2254.                 // Using interlocked to avoid a race condition with RegisteredWaitCallback
  2255.                 // Although UnsetAsyncEventSelect() below should cancel the callback, but
  2256.                 // it may already be in progress and therefore resulting in simultaneous
  2257.                 // registeredWaitCallback calling ConnectCallback() and the synchronous
  2258.                 // completion here.
  2259.                 if (Interlocked.Exchange(ref m_RegisteredWait, null) == null)
  2260.                     completeSynchronously = false;
  2261.                 //
  2262.                 // Cancel async event and go back to blocking mode.
  2263.                 //
  2264.                 UnsetAsyncEventSelect();
  2265.                 InternalSetBlocking(true);
  2266.                
  2267.                 if (errorCode == SocketError.Success) {
  2268.                     //
  2269.                     // synchronously complete the IO and call the user's callback.
  2270.                     //
  2271.                     if (completeSynchronously)
  2272.                         asyncResult.InvokeCallback();
  2273.                 }
  2274.                 else {
  2275.                     //
  2276.                     // if the asynchronous native call fails synchronously
  2277.                     // we'll throw a SocketException
  2278.                     //
  2279.                     m_RightEndPoint = oldEndPoint;
  2280.                     SocketException socketException = new SocketException(errorCode);
  2281.                     UpdateStatusAfterSocketError(socketException);
  2282.                     m_AcceptQueueOrConnectResult = null;
  2283.                     if (Logging.On)
  2284.                         Logging.Exception(Logging.Sockets, this, "BeginConnect", socketException);
  2285.                     throw socketException;
  2286.                 }
  2287.             }
  2288.            
  2289.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginConnect() to:" + endPointSnapshot.ToString() + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
  2290.         }
  2291.        
  2292.         // Begin ConnectEx is only supported for connection oriented protocols
  2293.         // for now this is only supported on win32 platforms. We need to fix this
  2294.         // when the getdelegatefrom function methods are available on 64bit.
  2295.         // to use this, the endpoint must either be an IP endpoint, or the
  2296.         // socket must already be bound.
  2297.         private bool CanUseConnectEx(EndPoint remoteEP)
  2298.         {
  2299.             return false;
  2300.         }
  2301.        
  2302.         //
  2303.         // This is the internal callback that will be called when
  2304.         // the IO we issued for the user to winsock has completed.
  2305.         // when this function gets called it must:
  2306.         // 1) update the AsyncResult object with the results of the completed IO
  2307.         // 2) signal events that the user might be waiting on
  2308.         // 3) call the callback function that the user might have specified
  2309.         //
  2310.         // This method was copied from a ConnectAsyncResult class that became useless.
  2311.         private void ConnectCallback()
  2312.         {
  2313.             LazyAsyncResult asyncResult = (LazyAsyncResult)m_AcceptQueueOrConnectResult;
  2314.            
  2315.            
  2316.             GlobalLog.Enter("Socket#" + ValidationHelper.HashString(this) + "::ConnectCallback");
  2317.             //
  2318.             // If we came here due to a race between BeginConnect and Dispose
  2319.             //
  2320.             if (asyncResult.InternalPeekCompleted) {
  2321.                 GlobalLog.Assert(CleanedUp, "Socket#{0}::ConnectCallback()|asyncResult is compelted but the socket does not have CleanedUp set.", ValidationHelper.HashString(this));
  2322.                 GlobalLog.Leave("Socket#" + ValidationHelper.HashString(this) + "::ConnectCallback", "Already completed, socket must be closed");
  2323.                 return;
  2324.             }
  2325.            
  2326.            
  2327.             //
  2328.            
  2329.             //
  2330.             // get async completion
  2331.             //
  2332.             /*
  2333.             int errorCode = (int)socket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Error);
  2334.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(socket) + "::ConnectCallback() GetSocketOption() returns errorCode:" + errorCode.ToString());
  2335.             */           
  2336.            
  2337. NetworkEvents networkEvents = new NetworkEvents();
  2338.             networkEvents.Events = AsyncEventBits.FdConnect;
  2339.            
  2340.             SocketError errorCode = SocketError.OperationAborted;
  2341.             object result = null;
  2342.            
  2343.             try {
  2344.                 if (!CleanedUp) {
  2345.                     try {
  2346.                         errorCode = UnsafeNclNativeMethods.OSSOCK.WSAEnumNetworkEvents(m_Handle, m_AsyncEvent.SafeWaitHandle, ref networkEvents);
  2347.                        
  2348.                         if (errorCode != SocketError.Success) {
  2349.                             errorCode = (SocketError)Marshal.GetLastWin32Error();
  2350.                             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::ConnectCallback() WSAEnumNetworkEvents() failed with errorCode:" + errorCode.ToString());
  2351.                         }
  2352.                         else {
  2353.                             errorCode = (SocketError)networkEvents.ErrorCodes[(int)AsyncEventBitsPos.FdConnectBit];
  2354.                             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::ConnectCallback() ErrorCodes(FdConnect) got errorCode:" + errorCode.ToString());
  2355.                         }
  2356.                         //
  2357.                         // Cancel async event and go back to blocking mode.
  2358.                         //
  2359.                         UnsetAsyncEventSelect();
  2360.                         InternalSetBlocking(true);
  2361.                     }
  2362.                     catch (ObjectDisposedException) {
  2363.                         errorCode = SocketError.OperationAborted;
  2364.                     }
  2365.                 }
  2366.                
  2367.                 //
  2368.                 // if the native non-blocking call failed we'll throw a SocketException in EndConnect()
  2369.                 //
  2370.                 if (errorCode == SocketError.Success) {
  2371.                     //
  2372.                     // the Socket is connected, update our state and performance counter
  2373.                     //
  2374.                     SetToConnected();
  2375.                 }
  2376.             }
  2377.             catch (Exception exception) {
  2378.                 if (NclUtilities.IsFatal(exception))
  2379.                     throw;
  2380.                
  2381.                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::ConnectCallback() caught exception:" + exception.Message + ", CleanedUp:" + CleanedUp);
  2382.                 result = exception;
  2383.             }
  2384.             catch {
  2385.                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::ConnectCallback() caught exception: Non-CLS Compliant Exception" + " CleanedUp:" + CleanedUp);
  2386.                 result = new Exception(SR.GetString(SR.net_nonClsCompliantException));
  2387.             }
  2388.            
  2389.             if (!asyncResult.InternalPeekCompleted) {
  2390.                 // A "ErrorCode" concept is questionable, for ex. below lines are subject to a race condition
  2391.                 asyncResult.ErrorCode = (int)errorCode;
  2392.                 asyncResult.InvokeCallback(result);
  2393.             }
  2394.            
  2395.             GlobalLog.Leave("Socket#" + ValidationHelper.HashString(this) + "::ConnectCallback", errorCode.ToString());
  2396.         }
  2397.        
  2398.         [HostProtection(ExternalThreading = true)]
  2399.         public IAsyncResult BeginConnect(string host, int port, AsyncCallback requestCallback, object state)
  2400.         {
  2401.             if (Logging.On)
  2402.                 Logging.Enter(Logging.Sockets, this, "BeginConnect", host);
  2403.            
  2404.             if (CleanedUp) {
  2405.                 throw new ObjectDisposedException(this.GetType().FullName);
  2406.             }
  2407.            
  2408.             if (host == null) {
  2409.                 throw new ArgumentNullException("host");
  2410.             }
  2411.             if (!ValidationHelper.ValidateTcpPort(port)) {
  2412.                 throw new ArgumentOutOfRangeException("port");
  2413.             }
  2414.             if (addressFamily != AddressFamily.InterNetwork && addressFamily != AddressFamily.InterNetworkV6) {
  2415.                 throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
  2416.             }
  2417.            
  2418.             if (isListening) {
  2419.                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustnotlisten));
  2420.             }
  2421.            
  2422.             // Here, want to flow the context. No need to lock.
  2423.             MultipleAddressConnectAsyncResult result = new MultipleAddressConnectAsyncResult(null, port, this, state, requestCallback);
  2424.             result.StartPostingAsyncOp(false);
  2425.            
  2426.             IAsyncResult dnsResult = Dns.UnsafeBeginGetHostAddresses(host, new AsyncCallback(DnsCallback), result);
  2427.             if (dnsResult.CompletedSynchronously) {
  2428.                 DoDnsCallback(dnsResult, result);
  2429.             }
  2430.            
  2431.             // Done posting.
  2432.             result.FinishPostingAsyncOp(ref Caches.ConnectClosureCache);
  2433.            
  2434.             if (Logging.On)
  2435.                 Logging.Exit(Logging.Sockets, this, "BeginConnect", result);
  2436.             return result;
  2437.         }
  2438.        
  2439. /* Uncomment when needed.
  2440.         internal IAsyncResult UnsafeBeginConnect(string host, int port, AsyncCallback requestCallback, object state)
  2441.         {
  2442.             if (Logging.On) Logging.Enter(Logging.Sockets, this, "BeginConnect", host);
  2443.             if (CleanedUp)
  2444.             {
  2445.                 throw new ObjectDisposedException(this.GetType().FullName);
  2446.             }
  2447.             MultipleAddressConnectAsyncResult result = new MultipleAddressConnectAsyncResult(null, port, this, state, requestCallback);
  2448.             IAsyncResult dnsResult = Dns.UnsafeBeginGetHostAddresses(host, new AsyncCallback(DnsCallback), result);
  2449.             if (dnsResult.CompletedSynchronously)
  2450.             {
  2451.                 DoDnsCallback(dnsResult, result);
  2452.             }
  2453.             if (Logging.On) Logging.Exit(Logging.Sockets, this, "BeginConnect", result);
  2454.             return result;
  2455.         }
  2456. */       
  2457.        
  2458.         [HostProtection(ExternalThreading = true)]
  2459.         public IAsyncResult BeginConnect(IPAddress address, int port, AsyncCallback requestCallback, object state)
  2460.         {
  2461.             if (Logging.On)
  2462.                 Logging.Enter(Logging.Sockets, this, "BeginConnect", address);
  2463.             if (CleanedUp) {
  2464.                 throw new ObjectDisposedException(this.GetType().FullName);
  2465.             }
  2466.            
  2467.             if (address == null) {
  2468.                 throw new ArgumentNullException("address");
  2469.             }
  2470.             if (!ValidationHelper.ValidateTcpPort(port)) {
  2471.                 throw new ArgumentOutOfRangeException("port");
  2472.             }
  2473.             //if address family isn't the socket address family throw
  2474.             if (addressFamily != address.AddressFamily) {
  2475.                 throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
  2476.             }
  2477.            
  2478.             IAsyncResult result = BeginConnect(new IPEndPoint(address, port), requestCallback, state);
  2479.             if (Logging.On)
  2480.                 Logging.Exit(Logging.Sockets, this, "BeginConnect", result);
  2481.             return result;
  2482.         }
  2483.        
  2484. /* Uncomment when needed.
  2485.         internal IAsyncResult UnsafeBeginConnect(IPAddress address, int port, AsyncCallback requestCallback, object state)
  2486.         {
  2487.             if (Logging.On) Logging.Enter(Logging.Sockets, this, "BeginConnect", address);
  2488.             if (CleanedUp)
  2489.             {
  2490.                 throw new ObjectDisposedException(this.GetType().FullName);
  2491.             }
  2492.             IAsyncResult result = UnsafeBeginConnect(new IPEndPoint(address, port), requestCallback, state);
  2493.             if (Logging.On) Logging.Exit(Logging.Sockets, this, "BeginConnect", result);
  2494.             return result;
  2495.         }
  2496. */       
  2497.        
  2498.         [HostProtection(ExternalThreading = true)]
  2499.         public IAsyncResult BeginConnect(IPAddress[] addresses, int port, AsyncCallback requestCallback, object state)
  2500.         {
  2501.             if (Logging.On)
  2502.                 Logging.Enter(Logging.Sockets, this, "BeginConnect", addresses);
  2503.             if (CleanedUp) {
  2504.                 throw new ObjectDisposedException(this.GetType().FullName);
  2505.             }
  2506.            
  2507.             if (addresses == null) {
  2508.                 throw new ArgumentNullException("addresses");
  2509.             }
  2510.             if (addresses.Length == 0) {
  2511.                 throw new ArgumentException(SR.GetString(SR.net_invalidAddressList), "addresses");
  2512.             }
  2513.             if (!ValidationHelper.ValidateTcpPort(port)) {
  2514.                 throw new ArgumentOutOfRangeException("port");
  2515.             }
  2516.             if (addressFamily != AddressFamily.InterNetwork && addressFamily != AddressFamily.InterNetworkV6) {
  2517.                 throw new NotSupportedException(SR.GetString(SR.net_invalidversion));
  2518.             }
  2519.            
  2520.             if (isListening) {
  2521.                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustnotlisten));
  2522.             }
  2523.            
  2524.             // Set up the result to capture the context. No need for a lock.
  2525.             MultipleAddressConnectAsyncResult result = new MultipleAddressConnectAsyncResult(addresses, port, this, state, requestCallback);
  2526.             result.StartPostingAsyncOp(false);
  2527.            
  2528.             DoMultipleAddressConnectCallback(PostOneBeginConnect(result), result);
  2529.            
  2530.             // Finished posting async op. Possibly will call callback.
  2531.             result.FinishPostingAsyncOp(ref Caches.ConnectClosureCache);
  2532.            
  2533.             if (Logging.On)
  2534.                 Logging.Exit(Logging.Sockets, this, "BeginConnect", result);
  2535.             return result;
  2536.         }
  2537.        
  2538. /* Uncomment when needed.
  2539.         internal IAsyncResult UnsafeBeginConnect(IPAddress[] addresses, int port, AsyncCallback requestCallback, object state)
  2540.         {
  2541.             if (Logging.On) Logging.Enter(Logging.Sockets, this, "BeginConnect", addresses);
  2542.             if (CleanedUp)
  2543.             {
  2544.                 throw new ObjectDisposedException(this.GetType().FullName);
  2545.             }
  2546.             // No need to capture context.
  2547.             MultipleAddressConnectAsyncResult result = new MultipleAddressConnectAsyncResult(addresses, port, this, state, requestCallback);
  2548.             DoMultipleAddressConnectCallback(PostOneBeginConnect(result), result);
  2549.             if (Logging.On) Logging.Exit(Logging.Sockets, this, "Connect", result);
  2550.             return result;
  2551.         }
  2552. */       
  2553.        
  2554.        
  2555.         // Supports DisconnectEx - this provides completion port IO and support for
  2556.         //disconnect and reconnects
  2557.         [HostProtection(ExternalThreading = true)]
  2558.         public IAsyncResult BeginDisconnect(bool reuseSocket, AsyncCallback callback, object state)
  2559.         {
  2560.             // Start context-flowing op. No need to lock - we don't use the context till the callback.
  2561.             DisconnectOverlappedAsyncResult asyncResult = new DisconnectOverlappedAsyncResult(this, state, callback);
  2562.             asyncResult.StartPostingAsyncOp(false);
  2563.            
  2564.             // Post the disconnect.
  2565.             DoBeginDisconnect(reuseSocket, asyncResult);
  2566.            
  2567.             // Finish flowing (or call the callback), and return.
  2568.             asyncResult.FinishPostingAsyncOp();
  2569.             return asyncResult;
  2570.         }
  2571.        
  2572. /* Uncomment when needed.
  2573.         internal IAsyncResult UnsafeBeginDisconnect(bool reuseSocket, AsyncCallback callback, object state)
  2574.         {
  2575.             // No flowing in this version.
  2576.             DisconnectOverlappedAsyncResult asyncResult = new DisconnectOverlappedAsyncResult(this, state, callback);
  2577.             DoBeginDisconnect(reuseSocket, asyncResult);
  2578.             return asyncResult;
  2579.         }
  2580. */       
  2581.        
  2582.         private void DoBeginDisconnect(bool reuseSocket, DisconnectOverlappedAsyncResult asyncResult)
  2583.         {
  2584.             if (Logging.On)
  2585.                 Logging.Enter(Logging.Sockets, this, "BeginDisconnect", null);
  2586.             if (CleanedUp) {
  2587.                 throw new ObjectDisposedException(this.GetType().FullName);
  2588.             }
  2589.            
  2590.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginDisconnect() ");
  2591.            
  2592.            
  2593.             throw new PlatformNotSupportedException(SR.GetString(SR.WinXPRequired));
  2594.            
  2595.            
  2596.             asyncResult.SetUnmanagedStructures(null);
  2597.            
  2598.             SocketError errorCode = SocketError.Success;
  2599.            
  2600.             // This can throw ObjectDisposedException (handle, and retrieving the delegate).
  2601.             if (!DisconnectEx(m_Handle, asyncResult.OverlappedHandle, (int)(reuseSocket ? TransmitFileOptions.ReuseSocket : 0), 0)) {
  2602.                 errorCode = (SocketError)Marshal.GetLastWin32Error();
  2603.             }
  2604.            
  2605.             if (errorCode == SocketError.Success) {
  2606.                 SetToDisconnected();
  2607.                 m_RemoteEndPoint = null;
  2608.             }
  2609.            
  2610.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginDisconnect() UnsafeNclNativeMethods.OSSOCK.DisConnectEx returns:" + errorCode.ToString());
  2611.            
  2612.             // if the asynchronous native call fails synchronously
  2613.             // we'll throw a SocketException
  2614.             //
  2615.             errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode);
  2616.            
  2617.             if (errorCode != SocketError.Success) {
  2618.                 //
  2619.                 // update our internal state after this socket error and throw
  2620.                 //
  2621.                 SocketException socketException = new SocketException(errorCode);
  2622.                 UpdateStatusAfterSocketError(socketException);
  2623.                 if (Logging.On)
  2624.                     Logging.Exception(Logging.Sockets, this, "BeginDisconnect", socketException);
  2625.                 throw socketException;
  2626.             }
  2627.            
  2628.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginDisconnect() returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
  2629.             if (Logging.On)
  2630.                 Logging.Exit(Logging.Sockets, this, "BeginDisconnect", asyncResult);
  2631.         }
  2632.        
  2633.        
  2634.         // Supports DisconnectEx - this provides support for disconnect and reconnects
  2635.         public void Disconnect(bool reuseSocket)
  2636.         {
  2637.            
  2638.             if (Logging.On)
  2639.                 Logging.Enter(Logging.Sockets, this, "Disconnect", null);
  2640.             if (CleanedUp) {
  2641.                 throw new ObjectDisposedException(this.GetType().FullName);
  2642.             }
  2643.            
  2644.             throw new PlatformNotSupportedException(SR.GetString(SR.WinXPRequired));
  2645.            
  2646.            
  2647.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Disconnect() ");
  2648.            
  2649.             SocketError errorCode = SocketError.Success;
  2650.            
  2651.             // This can throw ObjectDisposedException (handle, and retrieving the delegate).
  2652.             if (!DisconnectEx_Blocking(m_Handle.DangerousGetHandle(), IntPtr.Zero, (int)(reuseSocket ? TransmitFileOptions.ReuseSocket : 0), 0)) {
  2653.                 errorCode = (SocketError)Marshal.GetLastWin32Error();
  2654.             }
  2655.            
  2656.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Disconnect() UnsafeNclNativeMethods.OSSOCK.DisConnectEx returns:" + errorCode.ToString());
  2657.            
  2658.            
  2659.             if (errorCode != SocketError.Success) {
  2660.                 //
  2661.                 // update our internal state after this socket error and throw
  2662.                 //
  2663.                 SocketException socketException = new SocketException(errorCode);
  2664.                 UpdateStatusAfterSocketError(socketException);
  2665.                 if (Logging.On)
  2666.                     Logging.Exception(Logging.Sockets, this, "Disconnect", socketException);
  2667.                 throw socketException;
  2668.             }
  2669.            
  2670.             SetToDisconnected();
  2671.             m_RemoteEndPoint = null;
  2672.            
  2673.             //set the blocking mode back to what it was
  2674.             InternalSetBlocking(willBlockInternal);
  2675.             if (Logging.On)
  2676.                 Logging.Exit(Logging.Sockets, this, "Disconnect", null);
  2677.         }
  2678.        
  2679. /*++
  2680.         Routine Description:
  2681.           EndConnect - Called addressFamilyter receiving callback from BeginConnect,
  2682.             in order to retrive the result of async call
  2683.         Arguments:
  2684.           AsyncResult - the AsyncResult Returned fron BeginConnect call
  2685.         Return Value:
  2686.           int - Return code from aync Connect, 0 for success, SocketError.NotConnected otherwise
  2687.         --*/       
  2688.         /// <devdoc>
  2689.         /// <para>[To be supplied.]</para>
  2690.         /// </devdoc>
  2691.         public void EndConnect(IAsyncResult asyncResult)
  2692.         {
  2693.             if (Logging.On)
  2694.                 Logging.Enter(Logging.Sockets, this, "EndConnect", asyncResult);
  2695.             if (CleanedUp) {
  2696.                 throw new ObjectDisposedException(this.GetType().FullName);
  2697.             }
  2698.             //
  2699.             // parameter validation
  2700.             //
  2701.             if (asyncResult == null) {
  2702.                 throw new ArgumentNullException("asyncResult");
  2703.             }
  2704.            
  2705.            
  2706.             LazyAsyncResult castedAsyncResult = asyncResult as ConnectOverlappedAsyncResult;
  2707.             if (castedAsyncResult == null) {
  2708.                 castedAsyncResult = asyncResult as MultipleAddressConnectAsyncResult;
  2709.                 if (castedAsyncResult == null) {
  2710.                     castedAsyncResult = asyncResult as ConnectAsyncResult;
  2711.                 }
  2712.             }
  2713.            
  2714.             if (castedAsyncResult == null || castedAsyncResult.AsyncObject != this) {
  2715.                 throw new ArgumentException(SR.GetString(SR.net_io_invalidasyncresult), "asyncResult");
  2716.             }
  2717.             if (castedAsyncResult.EndCalled) {
  2718.                 throw new InvalidOperationException(SR.GetString(SR.net_io_invalidendcall, "EndConnect"));
  2719.             }
  2720.            
  2721.             castedAsyncResult.InternalWaitForCompletion();
  2722.             castedAsyncResult.EndCalled = true;
  2723.             m_AcceptQueueOrConnectResult = null;
  2724.            
  2725.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::EndConnect() asyncResult:" + ValidationHelper.HashString(asyncResult));
  2726.            
  2727.             if (castedAsyncResult.Result is Exception) {
  2728.                 if (Logging.On)
  2729.                     Logging.Exception(Logging.Sockets, this, "EndConnect", (Exception)castedAsyncResult.Result);
  2730.                 throw (Exception)castedAsyncResult.Result;
  2731.             }
  2732.             if ((SocketError)castedAsyncResult.ErrorCode != SocketError.Success) {
  2733.                 //
  2734.                 // update our internal state after this socket error and throw
  2735.                 //
  2736.                 SocketException socketException = new SocketException(castedAsyncResult.ErrorCode);
  2737.                 UpdateStatusAfterSocketError(socketException);
  2738.                 if (Logging.On)
  2739.                     Logging.Exception(Logging.Sockets, this, "EndConnect", socketException);
  2740.                 throw socketException;
  2741.             }
  2742.             if (Logging.On)
  2743.                 Logging.Exit(Logging.Sockets, this, "EndConnect", "");
  2744.         }
  2745.        
  2746.         public void EndDisconnect(IAsyncResult asyncResult)
  2747.         {
  2748.            
  2749.             if (Logging.On)
  2750.                 Logging.Enter(Logging.Sockets, this, "EndDisconnect", asyncResult);
  2751.             if (CleanedUp) {
  2752.                 throw new ObjectDisposedException(this.GetType().FullName);
  2753.             }
  2754.            
  2755.             throw new PlatformNotSupportedException(SR.GetString(SR.WinNTRequired));
  2756.            
  2757.             if (asyncResult == null) {
  2758.                 throw new ArgumentNullException("asyncResult");
  2759.             }
  2760.            
  2761.            
  2762.             //get async result and check for errors
  2763.             LazyAsyncResult castedAsyncResult = asyncResult as LazyAsyncResult;
  2764.             if (castedAsyncResult == null || castedAsyncResult.AsyncObject != this) {
  2765.                 throw new ArgumentException(SR.GetString(SR.net_io_invalidasyncresult), "asyncResult");
  2766.             }
  2767.             if (castedAsyncResult.EndCalled) {
  2768.                 throw new InvalidOperationException(SR.GetString(SR.net_io_invalidendcall, "EndDisconnect"));
  2769.             }
  2770.            
  2771.             //wait for completion if it hasn't occured
  2772.             castedAsyncResult.InternalWaitForCompletion();
  2773.             castedAsyncResult.EndCalled = true;
  2774.            
  2775.            
  2776.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::EndDisconnect()");
  2777.            
  2778.             //
  2779.             // if the asynchronous native call failed asynchronously
  2780.             // we'll throw a SocketException
  2781.             //
  2782.             if ((SocketError)castedAsyncResult.ErrorCode != SocketError.Success) {
  2783.                 //
  2784.                 // update our internal state after this socket error and throw
  2785.                 //
  2786.                 SocketException socketException = new SocketException(castedAsyncResult.ErrorCode);
  2787.                 UpdateStatusAfterSocketError(socketException);
  2788.                 if (Logging.On)
  2789.                     Logging.Exception(Logging.Sockets, this, "EndDisconnect", socketException);
  2790.                 throw socketException;
  2791.             }
  2792.            
  2793.             if (Logging.On)
  2794.                 Logging.Exit(Logging.Sockets, this, "EndDisconnect", null);
  2795.             return;
  2796.         }
  2797.        
  2798.        
  2799. /*++
  2800.         Routine Description:
  2801.           BeginSend - Async implimentation of Send call, mirrored addressFamilyter BeginReceive
  2802.           This routine may go pending at which time,
  2803.           but any case the callback Delegate will be called upon completion
  2804.         Arguments:
  2805.           WriteBuffer - status line that we wish to parse
  2806.           Index - Offset into WriteBuffer to begin sending from
  2807.           Size - Size of Buffer to transmit
  2808.           Callback - Delegate function that holds callback, called on completeion of I/O
  2809.           State - State used to track callback, set by caller, not required
  2810.         Return Value:
  2811.           IAsyncResult - Async result used to retreive result
  2812.         --*/       
  2813.        
  2814.         /// <devdoc>
  2815.         /// <para>[To be supplied.]</para>
  2816.         /// </devdoc>
  2817.        
  2818.         [HostProtection(ExternalThreading = true)]
  2819.         public IAsyncResult BeginSend(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback, object state)
  2820.         {
  2821.             SocketError errorCode;
  2822.             IAsyncResult result = BeginSend(buffer, offset, size, socketFlags, out errorCode, callback, state);
  2823.             if (errorCode != SocketError.Success && errorCode != SocketError.IOPending) {
  2824.                 throw new SocketException(errorCode);
  2825.             }
  2826.             return result;
  2827.         }
  2828.        
  2829.         [HostProtection(ExternalThreading = true)]
  2830.         public IAsyncResult BeginSend(byte[] buffer, int offset, int size, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
  2831.         {
  2832.            
  2833.             if (Logging.On)
  2834.                 Logging.Enter(Logging.Sockets, this, "BeginSend", "");
  2835.            
  2836.             if (CleanedUp) {
  2837.                 throw new ObjectDisposedException(this.GetType().FullName);
  2838.             }
  2839.             //
  2840.             // parameter validation
  2841.             //
  2842.             if (buffer == null) {
  2843.                 throw new ArgumentNullException("buffer");
  2844.             }
  2845.             if (offset < 0 || offset > buffer.Length) {
  2846.                 throw new ArgumentOutOfRangeException("offset");
  2847.             }
  2848.             if (size < 0 || size > buffer.Length - offset) {
  2849.                 throw new ArgumentOutOfRangeException("size");
  2850.             }
  2851.            
  2852.             // We need to flow the context here. But we don't need to lock the context - we don't use it until the callback.
  2853.             OverlappedAsyncResult asyncResult = new OverlappedAsyncResult(this, state, callback);
  2854.             asyncResult.StartPostingAsyncOp(false);
  2855.            
  2856.             // Run the send with this asyncResult.
  2857.             errorCode = DoBeginSend(buffer, offset, size, socketFlags, asyncResult);
  2858.            
  2859.             if (errorCode != SocketError.Success && errorCode != SocketError.IOPending) {
  2860.                 asyncResult = null;
  2861.             }
  2862.             else {
  2863.                 // We're not throwing, so finish the async op posting code so we can return to the user.
  2864.                 // If the operation already finished, the callback will be called from here.
  2865.                 asyncResult.FinishPostingAsyncOp(ref Caches.SendClosureCache);
  2866.             }
  2867.            
  2868.             if (Logging.On)
  2869.                 Logging.Exit(Logging.Sockets, this, "BeginSend", asyncResult);
  2870.             return asyncResult;
  2871.         }
  2872.        
  2873.        
  2874.        
  2875.        
  2876.         internal IAsyncResult UnsafeBeginSend(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback, object state)
  2877.         {
  2878.             if (Logging.On)
  2879.                 Logging.Enter(Logging.Sockets, this, "UnsafeBeginSend", "");
  2880.            
  2881.             if (CleanedUp) {
  2882.                 throw new ObjectDisposedException(this.GetType().FullName);
  2883.             }
  2884.            
  2885.             // No need to flow the context.
  2886.             OverlappedAsyncResult asyncResult = new OverlappedAsyncResult(this, state, callback);
  2887.            
  2888.             SocketError errorCode = DoBeginSend(buffer, offset, size, socketFlags, asyncResult);
  2889.             if (errorCode != SocketError.Success && errorCode != SocketError.IOPending) {
  2890.                 throw new SocketException(errorCode);
  2891.             }
  2892.            
  2893.             if (Logging.On)
  2894.                 Logging.Exit(Logging.Sockets, this, "UnsafeBeginSend", asyncResult);
  2895.             return asyncResult;
  2896.         }
  2897.        
  2898.         private SocketError DoBeginSend(byte[] buffer, int offset, int size, SocketFlags socketFlags, OverlappedAsyncResult asyncResult)
  2899.         {
  2900.            
  2901.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginSend() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " DST:" + ValidationHelper.ToString(RemoteEndPoint) + " size:" + size.ToString());
  2902.            
  2903.             // Guarantee to call CheckAsyncCallOverlappedResult if we call SetUnamangedStructures with a cache in order to
  2904.             // avoid a Socket leak in case of error.
  2905.             SocketError errorCode = SocketError.SocketError;
  2906.             try {
  2907.                 // Set up asyncResult for overlapped WSASend.
  2908.                 // This call will use completion ports on WinNT and Overlapped IO on Win9x.
  2909.                     /*don't pin null remoteEP*/                asyncResult.SetUnmanagedStructures(buffer, offset, size, null, false, ref Caches.SendOverlappedCache);
  2910.                
  2911.                 //
  2912.                 // Get the Send going.
  2913.                 //
  2914.                 GlobalLog.Print("BeginSend: asyncResult:" + ValidationHelper.HashString(asyncResult) + " size:" + size.ToString());
  2915.                 int bytesTransferred;
  2916.                
  2917.                 // This can throw ObjectDisposedException.
  2918.                     // only ever 1 buffer being sent
  2919.                 errorCode = UnsafeNclNativeMethods.OSSOCK.WSASend(m_Handle, ref asyncResult.m_SingleBuffer, 1, out bytesTransferred, socketFlags, asyncResult.OverlappedHandle, IntPtr.Zero);
  2920.                
  2921.                 if (errorCode != SocketError.Success) {
  2922.                     errorCode = (SocketError)Marshal.GetLastWin32Error();
  2923.                 }
  2924.                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginSend() UnsafeNclNativeMethods.OSSOCK.WSASend returns:" + errorCode.ToString() + " size:" + size.ToString() + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
  2925.             }
  2926.             finally {
  2927.                 errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode);
  2928.             }
  2929.            
  2930.             //
  2931.             // if the asynchronous native call fails synchronously
  2932.             // we'll throw a SocketException
  2933.             //
  2934.             if (errorCode != SocketError.Success) {
  2935.                 asyncResult.ExtractCache(ref Caches.SendOverlappedCache);
  2936.                 UpdateStatusAfterSocketError(errorCode);
  2937.                 if (Logging.On)
  2938.                     Logging.Exception(Logging.Sockets, this, "BeginSend", new SocketException(errorCode));
  2939.             }
  2940.             return errorCode;
  2941.         }
  2942.        
  2943.        
  2944.         /// <devdoc>
  2945.         /// <para>[To be supplied.]</para>
  2946.         /// </devdoc>
  2947.        
  2948.        
  2949.         /// <devdoc>
  2950.         /// <para>[To be supplied.]</para>
  2951.         /// </devdoc>
  2952.         [HostProtection(ExternalThreading = true)]
  2953.         public IAsyncResult BeginSend(IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, AsyncCallback callback, object state)
  2954.         {
  2955.             SocketError errorCode;
  2956.             IAsyncResult result = BeginSend(buffers, socketFlags, out errorCode, callback, state);
  2957.             if (errorCode != SocketError.Success && errorCode != SocketError.IOPending) {
  2958.                 throw new SocketException(errorCode);
  2959.             }
  2960.             return result;
  2961.         }
  2962.        
  2963.        
  2964.         [CLSCompliant(false)]
  2965.         [HostProtection(ExternalThreading = true)]
  2966.         public IAsyncResult BeginSend(IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
  2967.         {
  2968.            
  2969.             if (Logging.On)
  2970.                 Logging.Enter(Logging.Sockets, this, "BeginSend", "");
  2971.            
  2972.             if (CleanedUp) {
  2973.                 throw new ObjectDisposedException(this.GetType().FullName);
  2974.             }
  2975.            
  2976.             //
  2977.             // parameter validation
  2978.             //
  2979.             if (buffers == null) {
  2980.                 throw new ArgumentNullException("buffers");
  2981.             }
  2982.            
  2983.             if (buffers.Count == 0) {
  2984.                 throw new ArgumentException(SR.GetString(SR.net_sockets_zerolist, "buffers"), "buffers");
  2985.             }
  2986.            
  2987.             // We need to flow the context here. But we don't need to lock the context - we don't use it until the callback.
  2988.             OverlappedAsyncResult asyncResult = new OverlappedAsyncResult(this, state, callback);
  2989.             asyncResult.StartPostingAsyncOp(false);
  2990.            
  2991.             // Run the send with this asyncResult.
  2992.             errorCode = DoBeginSend(buffers, socketFlags, asyncResult);
  2993.            
  2994.             // We're not throwing, so finish the async op posting code so we can return to the user.
  2995.             // If the operation already finished, the callback will be called from here.
  2996.             asyncResult.FinishPostingAsyncOp(ref Caches.SendClosureCache);
  2997.            
  2998.             if (errorCode != SocketError.Success && errorCode != SocketError.IOPending) {
  2999.                 asyncResult = null;
  3000.             }
  3001.            
  3002.             if (Logging.On)
  3003.                 Logging.Exit(Logging.Sockets, this, "BeginSend", asyncResult);
  3004.             return asyncResult;
  3005.         }
  3006.        
  3007. /* Uncomment when needed.
  3008.         internal IAsyncResult UnsafeBeginSend(IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, AsyncCallback callback, object state)
  3009.         {
  3010.             // No need to flow the context.
  3011.             OverlappedAsyncResult asyncResult = new OverlappedAsyncResult(this, state, callback);
  3012.             DoBeginSend(buffers, socketFlags, asyncResult);
  3013.             return asyncResult;
  3014.         }
  3015. */       
  3016.        
  3017.         private SocketError DoBeginSend(IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, OverlappedAsyncResult asyncResult)
  3018.         {
  3019.            
  3020.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginSend() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " DST:" + ValidationHelper.ToString(RemoteEndPoint) + " buffers:" + buffers);
  3021.            
  3022.             // Guarantee to call CheckAsyncCallOverlappedResult if we call SetUnamangedStructures with a cache in order to
  3023.             // avoid a Socket leak in case of error.
  3024.             SocketError errorCode = SocketError.SocketError;
  3025.             try {
  3026.                 // Set up asyncResult for overlapped WSASend.
  3027.                 // This call will use completion ports on WinNT and Overlapped IO on Win9x.
  3028.                 asyncResult.SetUnmanagedStructures(buffers, ref Caches.SendOverlappedCache);
  3029.                
  3030.                 GlobalLog.Print("BeginSend: asyncResult:" + ValidationHelper.HashString(asyncResult));
  3031.                
  3032.                 // This can throw ObjectDisposedException.
  3033.                 int bytesTransferred;
  3034.                 errorCode = UnsafeNclNativeMethods.OSSOCK.WSASend(m_Handle, asyncResult.m_WSABuffers, asyncResult.m_WSABuffers.Length, out bytesTransferred, socketFlags, asyncResult.OverlappedHandle, IntPtr.Zero);
  3035.                
  3036.                 if (errorCode != SocketError.Success) {
  3037.                     errorCode = (SocketError)Marshal.GetLastWin32Error();
  3038.                 }
  3039.                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginSend() UnsafeNclNativeMethods.OSSOCK.WSASend returns:" + errorCode.ToString() + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
  3040.             }
  3041.             finally {
  3042.                 errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode);
  3043.             }
  3044.            
  3045.             //
  3046.             // if the asynchronous native call fails synchronously
  3047.             // we'll throw a SocketException
  3048.             //
  3049.             if (errorCode != SocketError.Success) {
  3050.                 asyncResult.ExtractCache(ref Caches.SendOverlappedCache);
  3051.                 UpdateStatusAfterSocketError(errorCode);
  3052.                 if (Logging.On)
  3053.                     Logging.Exception(Logging.Sockets, this, "BeginSend", new SocketException(errorCode));
  3054.             }
  3055.             return errorCode;
  3056.         }
  3057.        
  3058.        
  3059. /*++
  3060.         Routine Description:
  3061.           EndSend -  Called by user code addressFamilyter I/O is done or the user wants to wait.
  3062.                         until Async completion, needed to retrieve error result from call
  3063.         Arguments:
  3064.           AsyncResult - the AsyncResult Returned fron BeginSend call
  3065.         Return Value:
  3066.           int - Number of bytes transferred
  3067.         --*/       
  3068.         /// <devdoc>
  3069.         /// <para>[To be supplied.]</para>
  3070.         /// </devdoc>
  3071.        
  3072.        
  3073.         public int EndSend(IAsyncResult asyncResult)
  3074.         {
  3075.             SocketError errorCode;
  3076.             int bytesTransferred = EndSend(asyncResult, out errorCode);
  3077.             if (errorCode != SocketError.Success) {
  3078.                 throw new SocketException(errorCode);
  3079.             }
  3080.             return bytesTransferred;
  3081.         }
  3082.        
  3083.        
  3084.         public int EndSend(IAsyncResult asyncResult, out SocketError errorCode)
  3085.         {
  3086.             if (Logging.On)
  3087.                 Logging.Enter(Logging.Sockets, this, "EndSend", asyncResult);
  3088.             if (CleanedUp) {
  3089.                 throw new ObjectDisposedException(this.GetType().FullName);
  3090.             }
  3091.             //
  3092.             // parameter validation
  3093.             //
  3094.             if (asyncResult == null) {
  3095.                 throw new ArgumentNullException("asyncResult");
  3096.             }
  3097.             OverlappedAsyncResult castedAsyncResult = asyncResult as OverlappedAsyncResult;
  3098.             if (castedAsyncResult == null || castedAsyncResult.AsyncObject != this) {
  3099.                 throw new ArgumentException(SR.GetString(SR.net_io_invalidasyncresult), "asyncResult");
  3100.             }
  3101.             if (castedAsyncResult.EndCalled) {
  3102.                 throw new InvalidOperationException(SR.GetString(SR.net_io_invalidendcall, "EndSend"));
  3103.             }
  3104.            
  3105.             int bytesTransferred = (int)castedAsyncResult.InternalWaitForCompletion();
  3106.             castedAsyncResult.EndCalled = true;
  3107.             castedAsyncResult.ExtractCache(ref Caches.SendOverlappedCache);
  3108.            
  3109.            
  3110.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::EndSend() bytesTransferred:" + bytesTransferred.ToString());
  3111.            
  3112.             //
  3113.             // if the asynchronous native call failed asynchronously
  3114.             // we'll throw a SocketException
  3115.             //
  3116.             errorCode = (SocketError)castedAsyncResult.ErrorCode;
  3117.             if (errorCode != SocketError.Success) {
  3118.                 //
  3119.                 // update our internal state after this socket error and throw
  3120.                 //
  3121.                 UpdateStatusAfterSocketError(errorCode);
  3122.                 if (Logging.On) {
  3123.                     Logging.Exception(Logging.Sockets, this, "EndSend", new SocketException(errorCode));
  3124.                     Logging.Exit(Logging.Sockets, this, "EndSend", 0);
  3125.                 }
  3126.                 return 0;
  3127.             }
  3128.             if (Logging.On)
  3129.                 Logging.Exit(Logging.Sockets, this, "EndSend", bytesTransferred);
  3130.             return bytesTransferred;
  3131.         }
  3132.        
  3133.        
  3134.        
  3135. /*++
  3136.         Routine Description:
  3137.           BeginSendTo - Async implimentation of SendTo,
  3138.           This routine may go pending at which time,
  3139.           but any case the callback Delegate will be called upon completion
  3140.         Arguments:
  3141.           WriteBuffer - Buffer to transmit
  3142.           Index - Offset into WriteBuffer to begin sending from
  3143.           Size - Size of Buffer to transmit
  3144.           Flags - Specific Socket flags to pass to winsock
  3145.           remoteEP - EndPoint to transmit To
  3146.           Callback - Delegate function that holds callback, called on completeion of I/O
  3147.           State - State used to track callback, set by caller, not required
  3148.         Return Value:
  3149.           IAsyncResult - Async result used to retreive result
  3150.         --*/       
  3151.         /// <devdoc>
  3152.         /// <para>[To be supplied.]</para>
  3153.         /// </devdoc>
  3154.         [HostProtection(ExternalThreading = true)]
  3155.         public IAsyncResult BeginSendTo(byte[] buffer, int offset, int size, SocketFlags socketFlags, EndPoint remoteEP, AsyncCallback callback, object state)
  3156.         {
  3157.            
  3158.             if (Logging.On)
  3159.                 Logging.Enter(Logging.Sockets, this, "BeginSendTo", "");
  3160.            
  3161.             if (CleanedUp) {
  3162.                 throw new ObjectDisposedException(this.GetType().FullName);
  3163.             }
  3164.            
  3165.             //
  3166.             // parameter validation
  3167.             //
  3168.             if (buffer == null) {
  3169.                 throw new ArgumentNullException("buffer");
  3170.             }
  3171.             if (remoteEP == null) {
  3172.                 throw new ArgumentNullException("remoteEP");
  3173.             }
  3174.             if (offset < 0 || offset > buffer.Length) {
  3175.                 throw new ArgumentOutOfRangeException("offset");
  3176.             }
  3177.             if (size < 0 || size > buffer.Length - offset) {
  3178.                 throw new ArgumentOutOfRangeException("size");
  3179.             }
  3180.            
  3181.             // This will check the permissions for connect.
  3182.             EndPoint endPointSnapshot = remoteEP;
  3183.             SocketAddress socketAddress = CheckCacheRemote(ref endPointSnapshot, false);
  3184.            
  3185.             // Set up the async result and indicate to flow the context.
  3186.             OverlappedAsyncResult asyncResult = new OverlappedAsyncResult(this, state, callback);
  3187.             asyncResult.StartPostingAsyncOp(false);
  3188.            
  3189.             // Post the send.
  3190.             DoBeginSendTo(buffer, offset, size, socketFlags, endPointSnapshot, socketAddress, asyncResult);
  3191.            
  3192.             // Finish, possibly posting the callback. The callback won't be posted before this point is reached.
  3193.             asyncResult.FinishPostingAsyncOp(ref Caches.SendClosureCache);
  3194.            
  3195.             if (Logging.On)
  3196.                 Logging.Exit(Logging.Sockets, this, "BeginSendTo", asyncResult);
  3197.             return asyncResult;
  3198.         }
  3199.        
  3200. /* Uncomment when needed.
  3201.         internal IAsyncResult UnsafeBeginSendTo(byte[] buffer, int offset, int size, SocketFlags socketFlags, EndPoint remoteEP, AsyncCallback callback, object state)
  3202.         {
  3203.             EndPoint endPointSnapshot = remoteEP;
  3204.             SocketAddress socketAddress = SnapshotAndSerialize(ref endPointSnapshot);
  3205.             OverlappedAsyncResult asyncResult = new OverlappedAsyncResult(this, state, callback);
  3206.             DoBeginSendTo(buffer, offset, size, socketFlags, endPointSnapshot, socketAddress, asyncResult);
  3207.             return asyncResult;
  3208.         }
  3209. */       
  3210.        
  3211.         private void DoBeginSendTo(byte[] buffer, int offset, int size, SocketFlags socketFlags, EndPoint endPointSnapshot, SocketAddress socketAddress, OverlappedAsyncResult asyncResult)
  3212.         {
  3213.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginSendTo() size:" + size.ToString());
  3214.             EndPoint oldEndPoint = m_RightEndPoint;
  3215.            
  3216.             // Guarantee to call CheckAsyncCallOverlappedResult if we call SetUnamangedStructures with a cache in order to
  3217.             // avoid a Socket leak in case of error.
  3218.             SocketError errorCode = SocketError.SocketError;
  3219.             try {
  3220.                 // Set up asyncResult for overlapped WSASendTo.
  3221.                 // This call will use completion ports on WinNT and Overlapped IO on Win9x.
  3222.                     /* don't pin RemoteEP*/                asyncResult.SetUnmanagedStructures(buffer, offset, size, socketAddress, false, ref Caches.SendOverlappedCache);
  3223.                
  3224.                 if (m_RightEndPoint == null) {
  3225.                     m_RightEndPoint = endPointSnapshot;
  3226.                 }
  3227.                
  3228.                 int bytesTransferred;
  3229.                     // only ever 1 buffer being sent
  3230.                 errorCode = UnsafeNclNativeMethods.OSSOCK.WSASendTo(m_Handle, ref asyncResult.m_SingleBuffer, 1, out bytesTransferred, socketFlags, asyncResult.GetSocketAddressPtr(), asyncResult.SocketAddress.Size, asyncResult.OverlappedHandle, IntPtr.Zero);
  3231.                
  3232.                 if (errorCode != SocketError.Success) {
  3233.                     errorCode = (SocketError)Marshal.GetLastWin32Error();
  3234.                 }
  3235.                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginSendTo() UnsafeNclNativeMethods.OSSOCK.WSASend returns:" + errorCode.ToString() + " size:" + size + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
  3236.             }
  3237.             catch (ObjectDisposedException) {
  3238.                 m_RightEndPoint = oldEndPoint;
  3239.                 throw;
  3240.             }
  3241.             finally {
  3242.                 errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode);
  3243.             }
  3244.            
  3245.             //
  3246.             // if the asynchronous native call fails synchronously
  3247.             // we'll throw a SocketException
  3248.             //
  3249.             if (errorCode != SocketError.Success) {
  3250.                 //
  3251.                 // update our internal state after this socket error and throw
  3252.                 //
  3253.                 m_RightEndPoint = oldEndPoint;
  3254.                 asyncResult.ExtractCache(ref Caches.SendOverlappedCache);
  3255.                 SocketException socketException = new SocketException(errorCode);
  3256.                 UpdateStatusAfterSocketError(socketException);
  3257.                 if (Logging.On)
  3258.                     Logging.Exception(Logging.Sockets, this, "BeginSendTo", socketException);
  3259.                 throw socketException;
  3260.             }
  3261.            
  3262.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginSendTo() size:" + size.ToString() + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
  3263.         }
  3264.        
  3265. /*++
  3266.         Routine Description:
  3267.           EndSendTo -  Called by user code addressFamilyter I/O is done or the user wants to wait.
  3268.                         until Async completion, needed to retrieve error result from call
  3269.         Arguments:
  3270.           AsyncResult - the AsyncResult Returned fron BeginSend call
  3271.         Return Value:
  3272.           int - Number of bytes transferred
  3273.         --*/       
  3274.         /// <devdoc>
  3275.         /// <para>[To be supplied.]</para>
  3276.         /// </devdoc>
  3277.         public int EndSendTo(IAsyncResult asyncResult)
  3278.         {
  3279.             if (Logging.On)
  3280.                 Logging.Enter(Logging.Sockets, this, "EndSendTo", asyncResult);
  3281.             if (CleanedUp) {
  3282.                 throw new ObjectDisposedException(this.GetType().FullName);
  3283.             }
  3284.             //
  3285.             // parameter validation
  3286.             //
  3287.             if (asyncResult == null) {
  3288.                 throw new ArgumentNullException("asyncResult");
  3289.             }
  3290.             OverlappedAsyncResult castedAsyncResult = asyncResult as OverlappedAsyncResult;
  3291.             if (castedAsyncResult == null || castedAsyncResult.AsyncObject != this) {
  3292.                 throw new ArgumentException(SR.GetString(SR.net_io_invalidasyncresult), "asyncResult");
  3293.             }
  3294.             if (castedAsyncResult.EndCalled) {
  3295.                 throw new InvalidOperationException(SR.GetString(SR.net_io_invalidendcall, "EndSendTo"));
  3296.             }
  3297.            
  3298.             int bytesTransferred = (int)castedAsyncResult.InternalWaitForCompletion();
  3299.             castedAsyncResult.EndCalled = true;
  3300.             castedAsyncResult.ExtractCache(ref Caches.SendOverlappedCache);
  3301.            
  3302.            
  3303.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::EndSendTo() bytesTransferred:" + bytesTransferred.ToString());
  3304.            
  3305.             //
  3306.             // if the asynchronous native call failed asynchronously
  3307.             // we'll throw a SocketException
  3308.             //
  3309.             if ((SocketError)castedAsyncResult.ErrorCode != SocketError.Success) {
  3310.                 //
  3311.                 // update our internal state after this socket error and throw
  3312.                 //
  3313.                 SocketException socketException = new SocketException(castedAsyncResult.ErrorCode);
  3314.                 UpdateStatusAfterSocketError(socketException);
  3315.                 if (Logging.On)
  3316.                     Logging.Exception(Logging.Sockets, this, "EndSendTo", socketException);
  3317.                 throw socketException;
  3318.             }
  3319.             if (Logging.On)
  3320.                 Logging.Exit(Logging.Sockets, this, "EndSendTo", bytesTransferred);
  3321.             return bytesTransferred;
  3322.         }
  3323.        
  3324.        
  3325. /*++
  3326.         Routine Description:
  3327.           BeginReceive - Async implimentation of Recv call,
  3328.           Called when we want to start an async receive.
  3329.           We kick off the receive, and if it completes synchronously we'll
  3330.           call the callback. Otherwise we'll return an IASyncResult, which
  3331.           the caller can use to wait on or retrieve the final status, as needed.
  3332.           Uses Winsock 2 overlapped I/O.
  3333.         Arguments:
  3334.           ReadBuffer - status line that we wish to parse
  3335.           Index - Offset into ReadBuffer to begin reading from
  3336.           Size - Size of Buffer to recv
  3337.           Callback - Delegate function that holds callback, called on completeion of I/O
  3338.           State - State used to track callback, set by caller, not required
  3339.         Return Value:
  3340.           IAsyncResult - Async result used to retreive result
  3341.         --*/       
  3342.        
  3343.        
  3344.         /// <devdoc>
  3345.         /// <para>[To be supplied.]</para>
  3346.         /// </devdoc>
  3347.        
  3348.         [HostProtection(ExternalThreading = true)]
  3349.         public IAsyncResult BeginReceive(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback, object state)
  3350.         {
  3351.             SocketError errorCode;
  3352.             IAsyncResult result = BeginReceive(buffer, offset, size, socketFlags, out errorCode, callback, state);
  3353.             if (errorCode != SocketError.Success && errorCode != SocketError.IOPending) {
  3354.                 throw new SocketException(errorCode);
  3355.             }
  3356.             return result;
  3357.         }
  3358.        
  3359.        
  3360.         [HostProtection(ExternalThreading = true)]
  3361.         public IAsyncResult BeginReceive(byte[] buffer, int offset, int size, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
  3362.         {
  3363.            
  3364.             if (Logging.On)
  3365.                 Logging.Enter(Logging.Sockets, this, "BeginReceive", "");
  3366.            
  3367.             if (CleanedUp) {
  3368.                 throw new ObjectDisposedException(this.GetType().FullName);
  3369.             }
  3370.            
  3371.             //
  3372.             // parameter validation
  3373.             //
  3374.             if (buffer == null) {
  3375.                 throw new ArgumentNullException("buffer");
  3376.             }
  3377.             if (offset < 0 || offset > buffer.Length) {
  3378.                 throw new ArgumentOutOfRangeException("offset");
  3379.             }
  3380.             if (size < 0 || size > buffer.Length - offset) {
  3381.                 throw new ArgumentOutOfRangeException("size");
  3382.             }
  3383.            
  3384.             // We need to flow the context here. But we don't need to lock the context - we don't use it until the callback.
  3385.             OverlappedAsyncResult asyncResult = new OverlappedAsyncResult(this, state, callback);
  3386.             asyncResult.StartPostingAsyncOp(false);
  3387.            
  3388.             // Run the receive with this asyncResult.
  3389.             errorCode = DoBeginReceive(buffer, offset, size, socketFlags, asyncResult);
  3390.            
  3391.             if (errorCode != SocketError.Success && errorCode != SocketError.IOPending) {
  3392.                 asyncResult = null;
  3393.             }
  3394.             else {
  3395.                 // We're not throwing, so finish the async op posting code so we can return to the user.
  3396.                 // If the operation already finished, the callback will be called from here.
  3397.                 asyncResult.FinishPostingAsyncOp(ref Caches.ReceiveClosureCache);
  3398.             }
  3399.            
  3400.             if (Logging.On)
  3401.                 Logging.Exit(Logging.Sockets, this, "BeginReceive", asyncResult);
  3402.             return asyncResult;
  3403.         }
  3404.        
  3405.         internal IAsyncResult UnsafeBeginReceive(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback, object state)
  3406.         {
  3407.            
  3408.             if (Logging.On)
  3409.                 Logging.Enter(Logging.Sockets, this, "UnsafeBeginReceive", "");
  3410.            
  3411.             if (CleanedUp) {
  3412.                 throw new ObjectDisposedException(this.GetType().FullName);
  3413.             }
  3414.            
  3415.             // No need to flow the context.
  3416.             OverlappedAsyncResult asyncResult = new OverlappedAsyncResult(this, state, callback);
  3417.             DoBeginReceive(buffer, offset, size, socketFlags, asyncResult);
  3418.            
  3419.             if (Logging.On)
  3420.                 Logging.Exit(Logging.Sockets, this, "UnsafeBeginReceive", asyncResult);
  3421.             return asyncResult;
  3422.         }
  3423.        
  3424.         private SocketError DoBeginReceive(byte[] buffer, int offset, int size, SocketFlags socketFlags, OverlappedAsyncResult asyncResult)
  3425.         {
  3426.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginReceive() size:" + size.ToString());
  3427.            
  3428.             #if DEBUG
  3429.             IntPtr lastHandle = m_Handle.DangerousGetHandle();
  3430.             #endif
  3431.             // Guarantee to call CheckAsyncCallOverlappedResult if we call SetUnamangedStructures with a cache in order to
  3432.             // avoid a Socket leak in case of error.
  3433.             SocketError errorCode = SocketError.SocketError;
  3434.             try {
  3435.                 // Set up asyncResult for overlapped WSARecv.
  3436.                 // This call will use completion ports on WinNT and Overlapped IO on Win9x.
  3437.                     /* don't pin null RemoteEP*/                asyncResult.SetUnmanagedStructures(buffer, offset, size, null, false, ref Caches.ReceiveOverlappedCache);
  3438.                
  3439.                 // This can throw ObjectDisposedException.
  3440.                 int bytesTransferred;
  3441.                 errorCode = UnsafeNclNativeMethods.OSSOCK.WSARecv(m_Handle, ref asyncResult.m_SingleBuffer, 1, out bytesTransferred, ref socketFlags, asyncResult.OverlappedHandle, IntPtr.Zero);
  3442.                
  3443.                 if (errorCode != SocketError.Success) {
  3444.                     errorCode = (SocketError)Marshal.GetLastWin32Error();
  3445.                     GlobalLog.Assert(errorCode != SocketError.Success, "Socket#{0}::DoBeginReceive()|GetLastWin32Error() returned zero.", ValidationHelper.HashString(this));
  3446.                 }
  3447.                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginReceive() UnsafeNclNativeMethods.OSSOCK.WSARecv returns:" + errorCode.ToString() + " bytesTransferred:" + bytesTransferred.ToString() + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
  3448.             }
  3449.             finally {
  3450.                 errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode);
  3451.             }
  3452.            
  3453.             //
  3454.             // if the asynchronous native call fails synchronously
  3455.             // we'll throw a SocketException
  3456.             //
  3457.             if (errorCode != SocketError.Success) {
  3458.                 //
  3459.                 // update our internal state after this socket error and throw
  3460.                 asyncResult.ExtractCache(ref Caches.ReceiveOverlappedCache);
  3461.                 UpdateStatusAfterSocketError(errorCode);
  3462.                 if (Logging.On)
  3463.                     Logging.Exception(Logging.Sockets, this, "BeginReceive", new SocketException(errorCode));
  3464.             }
  3465.             #if DEBUG
  3466.             else {
  3467.                 m_LastReceiveHandle = lastHandle;
  3468.                 m_LastReceiveThread = Thread.CurrentThread.ManagedThreadId;
  3469.                 m_LastReceiveTick = Environment.TickCount;
  3470.             }
  3471.             #endif
  3472.            
  3473.             return errorCode;
  3474.         }
  3475.        
  3476.        
  3477.         [CLSCompliant(false)]
  3478.         [HostProtection(ExternalThreading = true)]
  3479.         public IAsyncResult BeginReceive(IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, AsyncCallback callback, object state)
  3480.         {
  3481.             SocketError errorCode;
  3482.             IAsyncResult result = BeginReceive(buffers, socketFlags, out errorCode, callback, state);
  3483.             if (errorCode != SocketError.Success && errorCode != SocketError.IOPending) {
  3484.                 throw new SocketException(errorCode);
  3485.             }
  3486.             return result;
  3487.         }
  3488.        
  3489.        
  3490.         [CLSCompliant(false)]
  3491.         [HostProtection(ExternalThreading = true)]
  3492.         public IAsyncResult BeginReceive(IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
  3493.         {
  3494.            
  3495.             if (Logging.On)
  3496.                 Logging.Enter(Logging.Sockets, this, "BeginReceive", "");
  3497.            
  3498.             if (CleanedUp) {
  3499.                 throw new ObjectDisposedException(this.GetType().FullName);
  3500.             }
  3501.            
  3502.             //
  3503.             // parameter validation
  3504.             //
  3505.             if (buffers == null) {
  3506.                 throw new ArgumentNullException("buffers");
  3507.             }
  3508.            
  3509.             if (buffers.Count == 0) {
  3510.                 throw new ArgumentException(SR.GetString(SR.net_sockets_zerolist, "buffers"), "buffers");
  3511.             }
  3512.            
  3513.             // We need to flow the context here. But we don't need to lock the context - we don't use it until the callback.
  3514.             OverlappedAsyncResult asyncResult = new OverlappedAsyncResult(this, state, callback);
  3515.             asyncResult.StartPostingAsyncOp(false);
  3516.            
  3517.             // Run the receive with this asyncResult.
  3518.             errorCode = DoBeginReceive(buffers, socketFlags, asyncResult);
  3519.            
  3520.             if (errorCode != SocketError.Success && errorCode != SocketError.IOPending) {
  3521.                 asyncResult = null;
  3522.             }
  3523.             else {
  3524.                 // We're not throwing, so finish the async op posting code so we can return to the user.
  3525.                 // If the operation already finished, the callback will be called from here.
  3526.                 asyncResult.FinishPostingAsyncOp(ref Caches.ReceiveClosureCache);
  3527.             }
  3528.            
  3529.             if (Logging.On)
  3530.                 Logging.Exit(Logging.Sockets, this, "BeginReceive", asyncResult);
  3531.             return asyncResult;
  3532.         }
  3533.        
  3534. /* Uncomment when needed.
  3535.         internal IAsyncResult UnsafeBeginReceive(IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, AsyncCallback callback, object state)
  3536.         {
  3537.             // No need to flow the context.
  3538.             OverlappedAsyncResult asyncResult = new OverlappedAsyncResult(this, state, callback);
  3539.             DoBeginReceive(buffers, socketFlags, asyncResult);
  3540.             return asyncResult;
  3541.         }
  3542. */       
  3543.        
  3544.         private SocketError DoBeginReceive(IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, OverlappedAsyncResult asyncResult)
  3545.         {
  3546.             #if DEBUG
  3547.             IntPtr lastHandle = m_Handle.DangerousGetHandle();
  3548.             #endif
  3549.             // Guarantee to call CheckAsyncCallOverlappedResult if we call SetUnamangedStructures with a cache in order to
  3550.             // avoid a Socket leak in case of error.
  3551.             SocketError errorCode = SocketError.SocketError;
  3552.             try {
  3553.                 // Set up asyncResult for overlapped WSASend.
  3554.                 // This call will use completion ports on WinNT and Overlapped IO on Win9x.
  3555.                 asyncResult.SetUnmanagedStructures(buffers, ref Caches.ReceiveOverlappedCache);
  3556.                
  3557.                 // This can throw ObjectDisposedException.
  3558.                 int bytesTransferred;
  3559.                 errorCode = UnsafeNclNativeMethods.OSSOCK.WSARecv(m_Handle, asyncResult.m_WSABuffers, asyncResult.m_WSABuffers.Length, out bytesTransferred, ref socketFlags, asyncResult.OverlappedHandle, IntPtr.Zero);
  3560.                
  3561.                 if (errorCode != SocketError.Success) {
  3562.                     errorCode = (SocketError)Marshal.GetLastWin32Error();
  3563.                     GlobalLog.Assert(errorCode != SocketError.Success, "Socket#{0}::DoBeginReceive()|GetLastWin32Error() returned zero.", ValidationHelper.HashString(this));
  3564.                 }
  3565.                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginReceive() UnsafeNclNativeMethods.OSSOCK.WSARecv returns:" + errorCode.ToString() + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
  3566.             }
  3567.             finally {
  3568.                 errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode);
  3569.             }
  3570.            
  3571.             //
  3572.             // if the asynchronous native call fails synchronously
  3573.             // we'll throw a SocketException
  3574.             //
  3575.             if (errorCode != SocketError.Success) {
  3576.                 //
  3577.                 // update our internal state after this socket error and throw
  3578.                 asyncResult.ExtractCache(ref Caches.ReceiveOverlappedCache);
  3579.                 UpdateStatusAfterSocketError(errorCode);
  3580.                 if (Logging.On)
  3581.                     Logging.Exception(Logging.Sockets, this, "BeginReceive", new SocketException(errorCode));
  3582.             }
  3583.             #if DEBUG
  3584.             else {
  3585.                 m_LastReceiveHandle = lastHandle;
  3586.                 m_LastReceiveThread = Thread.CurrentThread.ManagedThreadId;
  3587.                 m_LastReceiveTick = Environment.TickCount;
  3588.             }
  3589.             #endif
  3590.            
  3591.             return errorCode;
  3592.         }
  3593.        
  3594.         #if DEBUG
  3595.         private IntPtr m_LastReceiveHandle;
  3596.         private int m_LastReceiveThread;
  3597.         private int m_LastReceiveTick;
  3598.         #endif
  3599.        
  3600. /*++
  3601.         Routine Description:
  3602.           EndReceive -  Called when I/O is done or the user wants to wait. If
  3603.                     the I/O isn't done, we'll wait for it to complete, and then we'll return
  3604.                     the bytes of I/O done.
  3605.         Arguments:
  3606.           AsyncResult - the AsyncResult Returned fron BeginSend call
  3607.         Return Value:
  3608.           int - Number of bytes transferred
  3609.         --*/       
  3610.        
  3611.         /// <devdoc>
  3612.         /// <para>[To be supplied.]</para>
  3613.         /// </devdoc>
  3614.         public int EndReceive(IAsyncResult asyncResult)
  3615.         {
  3616.             SocketError errorCode;
  3617.             int bytesTransferred = EndReceive(asyncResult, out errorCode);
  3618.             if (errorCode != SocketError.Success) {
  3619.                 throw new SocketException(errorCode);
  3620.             }
  3621.             return bytesTransferred;
  3622.         }
  3623.        
  3624.        
  3625.         public int EndReceive(IAsyncResult asyncResult, out SocketError errorCode)
  3626.         {
  3627.             if (Logging.On)
  3628.                 Logging.Enter(Logging.Sockets, this, "EndReceive", asyncResult);
  3629.             if (CleanedUp) {
  3630.                 throw new ObjectDisposedException(this.GetType().FullName);
  3631.             }
  3632.             //
  3633.             // parameter validation
  3634.             //
  3635.             if (asyncResult == null) {
  3636.                 throw new ArgumentNullException("asyncResult");
  3637.             }
  3638.             OverlappedAsyncResult castedAsyncResult = asyncResult as OverlappedAsyncResult;
  3639.             if (castedAsyncResult == null || castedAsyncResult.AsyncObject != this) {
  3640.                 throw new ArgumentException(SR.GetString(SR.net_io_invalidasyncresult), "asyncResult");
  3641.             }
  3642.             if (castedAsyncResult.EndCalled) {
  3643.                 throw new InvalidOperationException(SR.GetString(SR.net_io_invalidendcall, "EndReceive"));
  3644.             }
  3645.            
  3646.             int bytesTransferred = (int)castedAsyncResult.InternalWaitForCompletion();
  3647.             castedAsyncResult.EndCalled = true;
  3648.             castedAsyncResult.ExtractCache(ref Caches.ReceiveOverlappedCache);
  3649.            
  3650.            
  3651.            
  3652.             //
  3653.             // if the asynchronous native call failed asynchronously
  3654.             // we'll throw a SocketException
  3655.             //
  3656.             errorCode = (SocketError)castedAsyncResult.ErrorCode;
  3657.             if (errorCode != SocketError.Success) {
  3658.                 //
  3659.                 // update our internal state after this socket error and throw
  3660.                 //
  3661.                 UpdateStatusAfterSocketError(errorCode);
  3662.                 if (Logging.On) {
  3663.                     Logging.Exception(Logging.Sockets, this, "EndReceive", new SocketException(errorCode));
  3664.                     Logging.Exit(Logging.Sockets, this, "EndReceive", 0);
  3665.                 }
  3666.                 return 0;
  3667.             }
  3668.             if (Logging.On)
  3669.                 Logging.Exit(Logging.Sockets, this, "EndReceive", bytesTransferred);
  3670.             return bytesTransferred;
  3671.         }
  3672.        
  3673.        
  3674.        
  3675.         public IAsyncResult BeginReceiveMessageFrom(byte[] buffer, int offset, int size, SocketFlags socketFlags, ref EndPoint remoteEP, AsyncCallback callback, object state)
  3676.         {
  3677.             if (Logging.On)
  3678.                 Logging.Enter(Logging.Sockets, this, "BeginReceiveMessageFrom", "");
  3679.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginReceiveMessageFrom() size:" + size.ToString());
  3680.            
  3681.             if (CleanedUp) {
  3682.                 throw new ObjectDisposedException(this.GetType().FullName);
  3683.             }
  3684.             if (buffer == null) {
  3685.                 throw new ArgumentNullException("buffer");
  3686.             }
  3687.             if (remoteEP == null) {
  3688.                 throw new ArgumentNullException("remoteEP");
  3689.             }
  3690.             if (offset < 0 || offset > buffer.Length) {
  3691.                 throw new ArgumentOutOfRangeException("offset");
  3692.             }
  3693.             if (size < 0 || size > buffer.Length - offset) {
  3694.                 throw new ArgumentOutOfRangeException("size");
  3695.             }
  3696.             if (m_RightEndPoint == null) {
  3697.                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustbind));
  3698.             }
  3699.            
  3700.            
  3701.             // Set up the result and set it to collect the context.
  3702.             ReceiveMessageOverlappedAsyncResult asyncResult = new ReceiveMessageOverlappedAsyncResult(this, state, callback);
  3703.             asyncResult.StartPostingAsyncOp(false);
  3704.            
  3705.             // Start the ReceiveFrom.
  3706.             EndPoint oldEndPoint = m_RightEndPoint;
  3707.            
  3708.             // This will check the permissions for connect.
  3709.             EndPoint endPointSnapshot = remoteEP;
  3710.             SocketAddress socketAddress = CheckCacheRemote(ref endPointSnapshot, false);
  3711.            
  3712.             // Guarantee to call CheckAsyncCallOverlappedResult if we call SetUnamangedStructures with a cache in order to
  3713.             // avoid a Socket leak in case of error.
  3714.             SocketError errorCode = SocketError.SocketError;
  3715.             try {
  3716.                 asyncResult.SetUnmanagedStructures(buffer, offset, size, socketAddress, socketFlags, ref Caches.ReceiveOverlappedCache);
  3717.                
  3718.                 // save a copy of the original EndPoint in the asyncResult
  3719.                 asyncResult.SocketAddressOriginal = endPointSnapshot.Serialize();
  3720.                
  3721.                 int bytesTransfered;
  3722.                
  3723.                 // This can throw ObjectDisposedException.
  3724.                 if (addressFamily == AddressFamily.InterNetwork) {
  3725.                     SetSocketOption(SocketOptionLevel.IP, SocketOptionName.PacketInformation, true);
  3726.                 }
  3727.                 else if (addressFamily == AddressFamily.InterNetworkV6) {
  3728.                     SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.PacketInformation, true);
  3729.                 }
  3730.                
  3731.                 if (m_RightEndPoint == null) {
  3732.                     m_RightEndPoint = endPointSnapshot;
  3733.                 }
  3734.                
  3735.                 errorCode = (SocketError)WSARecvMsg(m_Handle, Marshal.UnsafeAddrOfPinnedArrayElement(asyncResult.m_MessageBuffer, 0), out bytesTransfered, asyncResult.OverlappedHandle, IntPtr.Zero);
  3736.                
  3737.                 if (errorCode != SocketError.Success) {
  3738.                     errorCode = (SocketError)Marshal.GetLastWin32Error();
  3739.                    
  3740.                     // I have guarantees from Brad Williamson that WSARecvMsg() will never return WSAEMSGSIZE directly, since a completion
  3741.                     // is queued in this case. We wouldn't be able to handle this easily because of assumptions OverlappedAsyncResult
  3742.                     // makes about whether there would be a completion or not depending on the error code. If WSAEMSGSIZE would have been
  3743.                     // normally returned, it returns WSA_IO_PENDING instead. That same map is implemented here just in case.
  3744.                     if (errorCode == SocketError.MessageSize) {
  3745.                         GlobalLog.Assert("Socket#" + ValidationHelper.HashString(this) + "::BeginReceiveMessageFrom()|Returned WSAEMSGSIZE!");
  3746.                         errorCode = SocketError.IOPending;
  3747.                     }
  3748.                 }
  3749.                
  3750.                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginReceiveMessageFrom() UnsafeNclNativeMethods.OSSOCK.WSARecvMsg returns:" + errorCode.ToString() + " size:" + size.ToString() + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
  3751.             }
  3752.             catch (ObjectDisposedException) {
  3753.                 m_RightEndPoint = oldEndPoint;
  3754.                 throw;
  3755.             }
  3756.             finally {
  3757.                 errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode);
  3758.             }
  3759.            
  3760.             //
  3761.             // if the asynchronous native call fails synchronously
  3762.             // we'll throw a SocketException
  3763.             //
  3764.             if (errorCode != SocketError.Success) {
  3765.                 //
  3766.                 // update our internal state after this socket error and throw
  3767.                 //
  3768.                 m_RightEndPoint = oldEndPoint;
  3769.                 asyncResult.ExtractCache(ref Caches.ReceiveOverlappedCache);
  3770.                 SocketException socketException = new SocketException(errorCode);
  3771.                 UpdateStatusAfterSocketError(socketException);
  3772.                 if (Logging.On)
  3773.                     Logging.Exception(Logging.Sockets, this, "BeginReceiveMessageFrom", socketException);
  3774.                 throw socketException;
  3775.             }
  3776.            
  3777.             // Capture the context, maybe call the callback, and return.
  3778.             asyncResult.FinishPostingAsyncOp(ref Caches.ReceiveClosureCache);
  3779.            
  3780.             if (asyncResult.CompletedSynchronously && !asyncResult.SocketAddressOriginal.Equals(asyncResult.SocketAddress)) {
  3781.                 try {
  3782.                     remoteEP = endPointSnapshot.Create(asyncResult.SocketAddress);
  3783.                 }
  3784.                 catch {
  3785.                 }
  3786.             }
  3787.            
  3788.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginReceiveMessageFrom() size:" + size.ToString() + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
  3789.             if (Logging.On)
  3790.                 Logging.Exit(Logging.Sockets, this, "BeginReceiveMessageFrom", asyncResult);
  3791.             return asyncResult;
  3792.         }
  3793.        
  3794.        
  3795.         public int EndReceiveMessageFrom(IAsyncResult asyncResult, ref SocketFlags socketFlags, ref EndPoint endPoint, out IPPacketInformation ipPacketInformation)
  3796.         {
  3797.             if (Logging.On)
  3798.                 Logging.Enter(Logging.Sockets, this, "EndReceiveMessageFrom", asyncResult);
  3799.             if (CleanedUp) {
  3800.                 throw new ObjectDisposedException(this.GetType().FullName);
  3801.             }
  3802.             if (endPoint == null) {
  3803.                 throw new ArgumentNullException("endPoint");
  3804.             }
  3805.             if (asyncResult == null) {
  3806.                 throw new ArgumentNullException("asyncResult");
  3807.             }
  3808.             ReceiveMessageOverlappedAsyncResult castedAsyncResult = asyncResult as ReceiveMessageOverlappedAsyncResult;
  3809.             if (castedAsyncResult == null || castedAsyncResult.AsyncObject != this) {
  3810.                 throw new ArgumentException(SR.GetString(SR.net_io_invalidasyncresult), "asyncResult");
  3811.             }
  3812.             if (castedAsyncResult.EndCalled) {
  3813.                 throw new InvalidOperationException(SR.GetString(SR.net_io_invalidendcall, "EndReceiveMessageFrom"));
  3814.             }
  3815.            
  3816.             int bytesTransferred = (int)castedAsyncResult.InternalWaitForCompletion();
  3817.             castedAsyncResult.EndCalled = true;
  3818.             castedAsyncResult.ExtractCache(ref Caches.ReceiveOverlappedCache);
  3819.            
  3820.             // Update socket address size
  3821.             castedAsyncResult.SocketAddress.SetSize(castedAsyncResult.GetSocketAddressSizePtr());
  3822.            
  3823.             // pick up the saved copy of the original EndPoint from the asyncResult
  3824.             SocketAddress socketAddressOriginal = endPoint.Serialize();
  3825.            
  3826.             if (!socketAddressOriginal.Equals(castedAsyncResult.SocketAddress)) {
  3827.                 try {
  3828.                     endPoint = endPoint.Create(castedAsyncResult.SocketAddress);
  3829.                 }
  3830.                 catch {
  3831.                 }
  3832.             }
  3833.            
  3834.            
  3835.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::EndReceiveMessageFrom() bytesTransferred:" + bytesTransferred.ToString());
  3836.            
  3837.             //
  3838.             // if the asynchronous native call failed asynchronously
  3839.             // we'll throw a SocketException
  3840.             //
  3841.             if ((SocketError)castedAsyncResult.ErrorCode != SocketError.Success && (SocketError)castedAsyncResult.ErrorCode != SocketError.MessageSize) {
  3842.                 //
  3843.                 // update our internal state after this socket error and throw
  3844.                 //
  3845.                 SocketException socketException = new SocketException(castedAsyncResult.ErrorCode);
  3846.                 UpdateStatusAfterSocketError(socketException);
  3847.                 if (Logging.On)
  3848.                     Logging.Exception(Logging.Sockets, this, "EndReceiveMessageFrom", socketException);
  3849.                 throw socketException;
  3850.             }
  3851.            
  3852.             socketFlags = castedAsyncResult.m_flags;
  3853.             ipPacketInformation = castedAsyncResult.m_IPPacketInformation;
  3854.            
  3855.             if (Logging.On)
  3856.                 Logging.Exit(Logging.Sockets, this, "EndReceiveMessageFrom", bytesTransferred);
  3857.             return bytesTransferred;
  3858.         }
  3859.        
  3860.        
  3861.        
  3862. /*++
  3863.         Routine Description:
  3864.           BeginReceiveFrom - Async implimentation of RecvFrom call,
  3865.           Called when we want to start an async receive.
  3866.           We kick off the receive, and if it completes synchronously we'll
  3867.           call the callback. Otherwise we'll return an IASyncResult, which
  3868.           the caller can use to wait on or retrieve the final status, as needed.
  3869.           Uses Winsock 2 overlapped I/O.
  3870.         Arguments:
  3871.           ReadBuffer - status line that we wish to parse
  3872.           Index - Offset into ReadBuffer to begin reading from
  3873.           Request - Size of Buffer to recv
  3874.           Flags - Additonal Flags that may be passed to the underlying winsock call
  3875.           remoteEP - EndPoint that are to receive from
  3876.           Callback - Delegate function that holds callback, called on completeion of I/O
  3877.           State - State used to track callback, set by caller, not required
  3878.         Return Value:
  3879.           IAsyncResult - Async result used to retreive result
  3880.         --*/       
  3881.        
  3882.         /// <devdoc>
  3883.         /// <para>[To be supplied.]</para>
  3884.         /// </devdoc>
  3885.         [HostProtection(ExternalThreading = true)]
  3886.         public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset, int size, SocketFlags socketFlags, ref EndPoint remoteEP, AsyncCallback callback, object state)
  3887.         {
  3888.            
  3889.             if (Logging.On)
  3890.                 Logging.Enter(Logging.Sockets, this, "BeginReceiveFrom", "");
  3891.            
  3892.             if (CleanedUp) {
  3893.                 throw new ObjectDisposedException(this.GetType().FullName);
  3894.             }
  3895.             //
  3896.             // parameter validation
  3897.             //
  3898.             if (buffer == null) {
  3899.                 throw new ArgumentNullException("buffer");
  3900.             }
  3901.             if (remoteEP == null) {
  3902.                 throw new ArgumentNullException("remoteEP");
  3903.             }
  3904.             if (offset < 0 || offset > buffer.Length) {
  3905.                 throw new ArgumentOutOfRangeException("offset");
  3906.             }
  3907.             if (size < 0 || size > buffer.Length - offset) {
  3908.                 throw new ArgumentOutOfRangeException("size");
  3909.             }
  3910.             if (m_RightEndPoint == null) {
  3911.                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustbind));
  3912.             }
  3913.            
  3914.             // This will check the permissions for connect.
  3915.             EndPoint endPointSnapshot = remoteEP;
  3916.             SocketAddress socketAddress = CheckCacheRemote(ref endPointSnapshot, false);
  3917.            
  3918.             // Set up the result and set it to collect the context.
  3919.             OverlappedAsyncResult asyncResult = new OverlappedAsyncResult(this, state, callback);
  3920.             asyncResult.StartPostingAsyncOp(false);
  3921.            
  3922.             // Start the ReceiveFrom.
  3923.             DoBeginReceiveFrom(buffer, offset, size, socketFlags, endPointSnapshot, socketAddress, asyncResult);
  3924.            
  3925.             // Capture the context, maybe call the callback, and return.
  3926.             asyncResult.FinishPostingAsyncOp(ref Caches.ReceiveClosureCache);
  3927.            
  3928.             if (asyncResult.CompletedSynchronously && !asyncResult.SocketAddressOriginal.Equals(asyncResult.SocketAddress)) {
  3929.                 try {
  3930.                     remoteEP = endPointSnapshot.Create(asyncResult.SocketAddress);
  3931.                 }
  3932.                 catch {
  3933.                 }
  3934.             }
  3935.            
  3936.            
  3937.             if (Logging.On)
  3938.                 Logging.Exit(Logging.Sockets, this, "BeginReceiveFrom", asyncResult);
  3939.             return asyncResult;
  3940.         }
  3941.        
  3942. /* Uncomment when needed.
  3943.         internal IAsyncResult UnsafeBeginReceiveFrom(byte[] buffer, int offset, int size, SocketFlags socketFlags, ref EndPoint remoteEP, AsyncCallback callback, object state)
  3944.         {
  3945.             EndPoint endPointSnapshot = remoteEP;
  3946.             SocketAddress socketAddress = SnapshotAndSerialize(ref endPointSnapshot);
  3947.             // Set up the result, no need to collect the context.
  3948.             OverlappedAsyncResult asyncResult = new OverlappedAsyncResult(this, state, callback);
  3949.             DoBeginReceiveFrom(buffer, offset, size, socketFlags, endPointSnapshot, socketAddress, asyncResult);
  3950.             return asyncResult;
  3951.         }
  3952. */       
  3953.        
  3954.         private void DoBeginReceiveFrom(byte[] buffer, int offset, int size, SocketFlags socketFlags, EndPoint endPointSnapshot, SocketAddress socketAddress, OverlappedAsyncResult asyncResult)
  3955.         {
  3956.             EndPoint oldEndPoint = m_RightEndPoint;
  3957.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginReceiveFrom() size:" + size.ToString());
  3958.            
  3959.             // Guarantee to call CheckAsyncCallOverlappedResult if we call SetUnamangedStructures with a cache in order to
  3960.             // avoid a Socket leak in case of error.
  3961.             SocketError errorCode = SocketError.SocketError;
  3962.             try {
  3963.                 // Set up asyncResult for overlapped WSARecvFrom.
  3964.                 // This call will use completion ports on WinNT and Overlapped IO on Win9x.
  3965.                     /* pin remoteEP*/                asyncResult.SetUnmanagedStructures(buffer, offset, size, socketAddress, true, ref Caches.ReceiveOverlappedCache);
  3966.                
  3967.                 // save a copy of the original EndPoint in the asyncResult
  3968.                 asyncResult.SocketAddressOriginal = endPointSnapshot.Serialize();
  3969.                
  3970.                 if (m_RightEndPoint == null) {
  3971.                     m_RightEndPoint = endPointSnapshot;
  3972.                 }
  3973.                
  3974.                 int bytesTransferred;
  3975.                 errorCode = UnsafeNclNativeMethods.OSSOCK.WSARecvFrom(m_Handle, ref asyncResult.m_SingleBuffer, 1, out bytesTransferred, ref socketFlags, asyncResult.GetSocketAddressPtr(), asyncResult.GetSocketAddressSizePtr(), asyncResult.OverlappedHandle, IntPtr.Zero);
  3976.                
  3977.                 if (errorCode != SocketError.Success) {
  3978.                     errorCode = (SocketError)Marshal.GetLastWin32Error();
  3979.                 }
  3980.                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginReceiveFrom() UnsafeNclNativeMethods.OSSOCK.WSARecvFrom returns:" + errorCode.ToString() + " size:" + size.ToString() + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
  3981.             }
  3982.             catch (ObjectDisposedException) {
  3983.                 m_RightEndPoint = oldEndPoint;
  3984.                 throw;
  3985.             }
  3986.             finally {
  3987.                 errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode);
  3988.             }
  3989.            
  3990.             //
  3991.             // if the asynchronous native call fails synchronously
  3992.             // we'll throw a SocketException
  3993.             //
  3994.             if (errorCode != SocketError.Success) {
  3995.                 //
  3996.                 // update our internal state after this socket error and throw
  3997.                 //
  3998.                 m_RightEndPoint = oldEndPoint;
  3999.                 asyncResult.ExtractCache(ref Caches.ReceiveOverlappedCache);
  4000.                 SocketException socketException = new SocketException(errorCode);
  4001.                 UpdateStatusAfterSocketError(socketException);
  4002.                 if (Logging.On)
  4003.                     Logging.Exception(Logging.Sockets, this, "BeginReceiveFrom", socketException);
  4004.                 throw socketException;
  4005.             }
  4006.            
  4007.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginReceiveFrom() size:" + size.ToString() + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
  4008.         }
  4009.        
  4010.        
  4011. /*++
  4012.         Routine Description:
  4013.           EndReceiveFrom -  Called when I/O is done or the user wants to wait. If
  4014.                     the I/O isn't done, we'll wait for it to complete, and then we'll return
  4015.                     the bytes of I/O done.
  4016.         Arguments:
  4017.           AsyncResult - the AsyncResult Returned fron BeginReceiveFrom call
  4018.         Return Value:
  4019.           int - Number of bytes transferred
  4020.         --*/       
  4021.        
  4022.         /// <devdoc>
  4023.         /// <para>[To be supplied.]</para>
  4024.         /// </devdoc>
  4025.         public int EndReceiveFrom(IAsyncResult asyncResult, ref EndPoint endPoint)
  4026.         {
  4027.             if (Logging.On)
  4028.                 Logging.Enter(Logging.Sockets, this, "EndReceiveFrom", asyncResult);
  4029.             if (CleanedUp) {
  4030.                 throw new ObjectDisposedException(this.GetType().FullName);
  4031.             }
  4032.             //
  4033.             // parameter validation
  4034.             //
  4035.             if (endPoint == null) {
  4036.                 throw new ArgumentNullException("endPoint");
  4037.             }
  4038.             if (asyncResult == null) {
  4039.                 throw new ArgumentNullException("asyncResult");
  4040.             }
  4041.             OverlappedAsyncResult castedAsyncResult = asyncResult as OverlappedAsyncResult;
  4042.             if (castedAsyncResult == null || castedAsyncResult.AsyncObject != this) {
  4043.                 throw new ArgumentException(SR.GetString(SR.net_io_invalidasyncresult), "asyncResult");
  4044.             }
  4045.             if (castedAsyncResult.EndCalled) {
  4046.                 throw new InvalidOperationException(SR.GetString(SR.net_io_invalidendcall, "EndReceiveFrom"));
  4047.             }
  4048.            
  4049.             int bytesTransferred = (int)castedAsyncResult.InternalWaitForCompletion();
  4050.             castedAsyncResult.EndCalled = true;
  4051.             castedAsyncResult.ExtractCache(ref Caches.ReceiveOverlappedCache);
  4052.            
  4053.             // Update socket address size
  4054.             castedAsyncResult.SocketAddress.SetSize(castedAsyncResult.GetSocketAddressSizePtr());
  4055.            
  4056.             SocketAddress socketAddressOriginal = endPoint.Serialize();
  4057.            
  4058.             if (!socketAddressOriginal.Equals(castedAsyncResult.SocketAddress)) {
  4059.                 try {
  4060.                     endPoint = endPoint.Create(castedAsyncResult.SocketAddress);
  4061.                 }
  4062.                 catch {
  4063.                 }
  4064.             }
  4065.            
  4066.            
  4067.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::EndReceiveFrom() bytesTransferred:" + bytesTransferred.ToString());
  4068.            
  4069.             //
  4070.             // if the asynchronous native call failed asynchronously
  4071.             // we'll throw a SocketException
  4072.             //
  4073.             if ((SocketError)castedAsyncResult.ErrorCode != SocketError.Success) {
  4074.                 //
  4075.                 // update our internal state after this socket error and throw
  4076.                 //
  4077.                 SocketException socketException = new SocketException(castedAsyncResult.ErrorCode);
  4078.                 UpdateStatusAfterSocketError(socketException);
  4079.                 if (Logging.On)
  4080.                     Logging.Exception(Logging.Sockets, this, "EndReceiveFrom", socketException);
  4081.                 throw socketException;
  4082.             }
  4083.             if (Logging.On)
  4084.                 Logging.Exit(Logging.Sockets, this, "EndReceiveFrom", bytesTransferred);
  4085.             return bytesTransferred;
  4086.         }
  4087.        
  4088.        
  4089. /*++
  4090.         Routine Description:
  4091.           BeginAccept - Does a async winsock accept, creating a new socket on success
  4092.             Works by creating a pending accept request the first time,
  4093.             and subsequent calls are queued so that when the first accept completes,
  4094.             the next accept can be resubmitted in the callback.
  4095.             this routine may go pending at which time,
  4096.             but any case the callback Delegate will be called upon completion
  4097.         Arguments:
  4098.           Callback - Async Callback Delegate that is called upon Async Completion
  4099.           State - State used to track callback, set by caller, not required
  4100.         Return Value:
  4101.           IAsyncResult - Async result used to retreive resultant new socket
  4102.         --*/       
  4103.        
  4104.         /// <devdoc>
  4105.         /// <para>[To be supplied.]</para>
  4106.         /// </devdoc>
  4107.         [HostProtection(ExternalThreading = true)]
  4108.         public IAsyncResult BeginAccept(AsyncCallback callback, object state)
  4109.         {
  4110.            
  4111.             if (Logging.On)
  4112.                 Logging.Enter(Logging.Sockets, this, "BeginAccept", "");
  4113.             if (CleanedUp) {
  4114.                 throw new ObjectDisposedException(this.GetType().FullName);
  4115.             }
  4116.            
  4117.             // Set up the context flow.
  4118.             AcceptAsyncResult asyncResult = new AcceptAsyncResult(this, state, callback);
  4119.             asyncResult.StartPostingAsyncOp(false);
  4120.            
  4121.             // Do the accept.
  4122.             DoBeginAccept(asyncResult);
  4123.            
  4124.             // Set up for return.
  4125.             asyncResult.FinishPostingAsyncOp(ref Caches.AcceptClosureCache);
  4126.            
  4127.             if (Logging.On)
  4128.                 Logging.Exit(Logging.Sockets, this, "BeginAccept", asyncResult);
  4129.             return asyncResult;
  4130.         }
  4131.        
  4132. /* Uncomment when needed.
  4133.         internal IAsyncResult UnsafeBeginAccept(AsyncCallback callback, object state)
  4134.         {
  4135.             if (CanUseAcceptEx)
  4136.             {
  4137.                 return UnsafeBeginAccept(0, callback, state);
  4138.             }
  4139.             // Set up the async result.  Can use Lazy since there's no context flow.
  4140.             LazyAsyncResult asyncResult = new LazyAsyncResult(this, state, callback);
  4141.             DoBeginAccept(asyncResult);
  4142.             return asyncResult;
  4143.         }
  4144. */       
  4145.        
  4146.         private void DoBeginAccept(LazyAsyncResult asyncResult)
  4147.         {
  4148.             if (m_RightEndPoint == null) {
  4149.                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustbind));
  4150.             }
  4151.            
  4152.             if (!isListening) {
  4153.                 throw new InvalidOperationException(SR.GetString(SR.net_sockets_mustlisten));
  4154.             }
  4155.            
  4156.             //
  4157.             // We keep a queue, which lists the set of requests that want to
  4158.             // be called when an accept queue completes. We call accept
  4159.             // once, and then as it completes asyncrounsly we pull the
  4160.             // requests out of the queue and call their callback.
  4161.             //
  4162.             // We start by grabbing Critical Section, then attempt to
  4163.             // determine if we haven an empty Queue of Accept Sockets
  4164.             // or if its in a Callback on the Callback thread.
  4165.             //
  4166.             // If its in the callback thread proocessing of the callback, then we
  4167.             // just need to notify the callback by adding an additional request
  4168.             // to the queue.
  4169.             //
  4170.             // If its an empty queue, and its not in the callback, then
  4171.             // we just need to get the Accept going, make it go async
  4172.             // and leave.
  4173.             //
  4174.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginAccept()");
  4175.            
  4176.             bool needFinishedCall = false;
  4177.             SocketError errorCode = 0;
  4178.            
  4179.             Queue acceptQueue = GetAcceptQueue();
  4180.             lock (this) {
  4181.                 if (acceptQueue.Count == 0) {
  4182.                     SocketAddress socketAddress = m_RightEndPoint.Serialize();
  4183.                    
  4184.                     GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginAccept() queue is empty calling UnsafeNclNativeMethods.OSSOCK.accept");
  4185.                    
  4186.                     // Check if a socket is already available. We need to be non-blocking to do this.
  4187.                     InternalSetBlocking(false);
  4188.                    
  4189.                     SafeCloseSocket acceptedSocketHandle = null;
  4190.                     try {
  4191.                         acceptedSocketHandle = SafeCloseSocket.Accept(m_Handle, socketAddress.m_Buffer, ref socketAddress.m_Size);
  4192.                         errorCode = acceptedSocketHandle.IsInvalid ? (SocketError)Marshal.GetLastWin32Error() : SocketError.Success;
  4193.                     }
  4194.                     catch (ObjectDisposedException) {
  4195.                         errorCode = SocketError.NotSocket;
  4196.                     }
  4197.                    
  4198.                     GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginAccept() UnsafeNclNativeMethods.OSSOCK.accept returns:" + errorCode.ToString());
  4199.                    
  4200.                     if (errorCode != SocketError.WouldBlock) {
  4201.                         if (errorCode == SocketError.Success) {
  4202.                             asyncResult.Result = CreateAcceptSocket(acceptedSocketHandle, m_RightEndPoint.Create(socketAddress), false);
  4203.                         }
  4204.                         else {
  4205.                             asyncResult.ErrorCode = (int)errorCode;
  4206.                         }
  4207.                        
  4208.                         // Reset the blocking.
  4209.                         InternalSetBlocking(true);
  4210.                        
  4211.                         // Continue outside the lock.
  4212.                         needFinishedCall = true;
  4213.                     }
  4214.                     else {
  4215.                         // It would block. Start listening for accepts, and add ourselves to the queue.
  4216.                         acceptQueue.Enqueue(asyncResult);
  4217.                         if (!SetAsyncEventSelect(AsyncEventBits.FdAccept)) {
  4218.                             acceptQueue.Dequeue();
  4219.                             throw new ObjectDisposedException(this.GetType().FullName);
  4220.                         }
  4221.                     }
  4222.                 }
  4223.                 else {
  4224.                     acceptQueue.Enqueue(asyncResult);
  4225.                    
  4226.                     GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginAccept() queue is not empty Count:" + acceptQueue.Count.ToString());
  4227.                 }
  4228.             }
  4229.            
  4230.             if (needFinishedCall) {
  4231.                 if (errorCode == SocketError.Success) {
  4232.                     // Completed synchronously, invoke the callback.
  4233.                     asyncResult.InvokeCallback();
  4234.                 }
  4235.                 else {
  4236.                     //
  4237.                     // update our internal state after this socket error and throw
  4238.                     //
  4239.                     SocketException socketException = new SocketException(errorCode);
  4240.                     UpdateStatusAfterSocketError(socketException);
  4241.                     if (Logging.On)
  4242.                         Logging.Exception(Logging.Sockets, this, "BeginAccept", socketException);
  4243.                     throw socketException;
  4244.                 }
  4245.             }
  4246.            
  4247.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginAccept() returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
  4248.         }
  4249.        
  4250.         //
  4251.         // This is a shortcut to AcceptCallback when called from dispose.
  4252.         // The only business is lock and complete all results with an error
  4253.         //
  4254.         private void CompleteAcceptResults(object nullState)
  4255.         {
  4256.             Queue acceptQueue = GetAcceptQueue();
  4257.             bool acceptNeeded = true;
  4258.             while (acceptNeeded) {
  4259.                 LazyAsyncResult asyncResult = null;
  4260.                 lock (this) {
  4261.                     // If the queue is empty, cancel the select and indicate not to loop anymore.
  4262.                     if (acceptQueue.Count == 0)
  4263.                         break;
  4264.                     asyncResult = (LazyAsyncResult)acceptQueue.Dequeue();
  4265.                    
  4266.                     if (acceptQueue.Count == 0)
  4267.                         acceptNeeded = false;
  4268.                 }
  4269.                
  4270.                 // Notify about the completion outside the lock.
  4271.                 try {
  4272.                     asyncResult.InvokeCallback(new SocketException(SocketError.OperationAborted));
  4273.                 }
  4274.                 catch {
  4275.                     // Exception from the user callback,
  4276.                     // If we need to loop, offload to a different thread and re-throw for debugging
  4277.                     if (acceptNeeded)
  4278.                         ThreadPool.UnsafeQueueUserWorkItem(new WaitCallback(CompleteAcceptResults), null);
  4279.                    
  4280.                     throw;
  4281.                 }
  4282.             }
  4283.         }
  4284.        
  4285.         // This method was originally in an AcceptAsyncResult class but that class got useless.
  4286.         private void AcceptCallback(object nullState)
  4287.         {
  4288.             // We know we need to try completing an accept at first. Keep going until the queue is empty (inside the lock).
  4289.             // At that point, BeginAccept() takes control of restarting the pump if necessary.
  4290.             bool acceptNeeded = true;
  4291.             Queue acceptQueue = GetAcceptQueue();
  4292.            
  4293.             while (acceptNeeded) {
  4294.                 LazyAsyncResult asyncResult = null;
  4295.                 SocketError errorCode = SocketError.OperationAborted;
  4296.                 SocketAddress socketAddress = null;
  4297.                 SafeCloseSocket acceptedSocket = null;
  4298.                 Exception otherException = null;
  4299.                 object result = null;
  4300.                
  4301.                 lock (this) {
  4302.                     //
  4303.                     // Accept Callback - called on the callback path, when we expect to release
  4304.                     // an accept socket that winsock says has completed.
  4305.                     //
  4306.                     // While we still have items in our Queued list of Accept Requests,
  4307.                     // we recall the Winsock accept, to attempt to gather new
  4308.                     // results, and then match them again the queued items,
  4309.                     // when accept call returns would_block, we reinvoke ourselves
  4310.                     // and rewait for the next asyc callback.
  4311.                     //
  4312.                    
  4313.                     //
  4314.                     // We may not have items in the queue because of possible race
  4315.                     // between re-entering this callback manually and from the thread pool.
  4316.                     //
  4317.                     if (acceptQueue.Count == 0)
  4318.                         break;
  4319.                    
  4320.                     // pick an element from the head of the list
  4321.                     asyncResult = (LazyAsyncResult)acceptQueue.Peek();
  4322.                    
  4323.                     if (!CleanedUp) {
  4324.                         socketAddress = m_RightEndPoint.Serialize();
  4325.                        
  4326.                         try {
  4327.                             // We know we're in non-blocking because of SetAsyncEventSelect().
  4328.                             GlobalLog.Assert(!willBlockInternal, "Socket#{0}::AcceptCallback|Socket should be in non-blocking state.", ValidationHelper.HashString(this));
  4329.                             acceptedSocket = SafeCloseSocket.Accept(m_Handle, socketAddress.m_Buffer, ref socketAddress.m_Size);
  4330.                            
  4331.                             errorCode = acceptedSocket.IsInvalid ? (SocketError)Marshal.GetLastWin32Error() : SocketError.Success;
  4332.                            
  4333.                             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::AcceptCallback() UnsafeNclNativeMethods.OSSOCK.accept returns:" + errorCode.ToString());
  4334.                         }
  4335.                         catch (ObjectDisposedException) {
  4336.                             // Listener socket was closed.
  4337.                             errorCode = SocketError.OperationAborted;
  4338.                         }
  4339.                         catch (Exception exception) {
  4340.                             if (NclUtilities.IsFatal(exception))
  4341.                                 throw;
  4342.                            
  4343.                             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::AcceptCallback() caught exception:" + exception.Message + " CleanedUp:" + CleanedUp);
  4344.                             otherException = exception;
  4345.                         }
  4346.                         catch {
  4347.                             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::AcceptCallback() caught exception: Non-CLS Compliant Exception" + " CleanedUp:" + CleanedUp);
  4348.                             otherException = new Exception(SR.GetString(SR.net_nonClsCompliantException));
  4349.                         }
  4350.                     }
  4351.                    
  4352.                     if (errorCode == SocketError.WouldBlock && otherException == null) {
  4353.                         // The accept found no waiting connections, so start listening for more.
  4354.                         if (SetAsyncEventSelect(AsyncEventBits.FdAccept))
  4355.                             break;
  4356.                         otherException = new ObjectDisposedException(this.GetType().FullName);
  4357.                     }
  4358.                    
  4359.                     // CreateAcceptSocket() must be done before InternalSetBlocking() so that the fixup is correct inside
  4360.                     // UpdateAcceptSocket(). InternalSetBlocking() must happen in the lock.
  4361.                     if (otherException != null) {
  4362.                         result = otherException;
  4363.                     }
  4364.                     else if (errorCode == SocketError.Success) {
  4365.                         result = CreateAcceptSocket(acceptedSocket, m_RightEndPoint.Create(socketAddress), true);
  4366.                     }
  4367.                     else {
  4368.                         asyncResult.ErrorCode = (int)errorCode;
  4369.                     }
  4370.                    
  4371.                     // This request completed, so it can be taken off the queue.
  4372.                     acceptQueue.Dequeue();
  4373.                    
  4374.                     // If the queue is empty, cancel the select and indicate not to loop anymore.
  4375.                     if (acceptQueue.Count == 0) {
  4376.                         if (!CleanedUp)
  4377.                             UnsetAsyncEventSelect();
  4378.                         InternalSetBlocking(true);
  4379.                         acceptNeeded = false;
  4380.                     }
  4381.                 }
  4382.                
  4383.                 // Notify about the completion outside the lock.
  4384.                 try {
  4385.                     asyncResult.InvokeCallback(result);
  4386.                 }
  4387.                 catch {
  4388.                     // Exception from the user callback,
  4389.                     // If we need to loop, offload to a different thread and re-throw for debugging
  4390.                     if (acceptNeeded)
  4391.                         ThreadPool.UnsafeQueueUserWorkItem(new WaitCallback(AcceptCallback), nullState);
  4392.                    
  4393.                     throw;
  4394.                 }
  4395.             }
  4396.         }
  4397.        
  4398.        
  4399.        
  4400. /*++
  4401.         Routine Description:
  4402.           EndAccept -  Called by user code addressFamilyter I/O is done or the user wants to wait.
  4403.                         until Async completion, so it provides End handling for aync Accept calls,
  4404.                         and retrieves new Socket object
  4405.         Arguments:
  4406.           AsyncResult - the AsyncResult Returned fron BeginAccept call
  4407.         Return Value:
  4408.           Socket - a valid socket if successful
  4409.         --*/       
  4410.        
  4411.         /// <devdoc>
  4412.         /// <para>[To be supplied.]</para>
  4413.         /// </devdoc>
  4414.        
  4415.        
  4416.        
  4417.         public Socket EndAccept(IAsyncResult asyncResult)
  4418.         {
  4419.             if (Logging.On)
  4420.                 Logging.Enter(Logging.Sockets, this, "EndAccept", asyncResult);
  4421.             if (CleanedUp) {
  4422.                 throw new ObjectDisposedException(this.GetType().FullName);
  4423.             }
  4424.            
  4425.            
  4426.             //
  4427.             // parameter validation
  4428.             //
  4429.             if (asyncResult == null) {
  4430.                 throw new ArgumentNullException("asyncResult");
  4431.             }
  4432.            
  4433.             AcceptAsyncResult castedAsyncResult = asyncResult as AcceptAsyncResult;
  4434.             if (castedAsyncResult == null || castedAsyncResult.AsyncObject != this) {
  4435.                 throw new ArgumentException(SR.GetString(SR.net_io_invalidasyncresult), "asyncResult");
  4436.             }
  4437.             if (castedAsyncResult.EndCalled) {
  4438.                 throw new InvalidOperationException(SR.GetString(SR.net_io_invalidendcall, "EndAccept"));
  4439.             }
  4440.            
  4441.             object result = castedAsyncResult.InternalWaitForCompletion();
  4442.             castedAsyncResult.EndCalled = true;
  4443.            
  4444.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::EndAccept() acceptedSocket:" + ValidationHelper.HashString(result));
  4445.            
  4446.             //
  4447.             // if the asynchronous native call failed asynchronously
  4448.             // we'll throw a SocketException
  4449.             //
  4450.             Exception exception = result as Exception;
  4451.             if (exception != null) {
  4452.                 throw exception;
  4453.             }
  4454.            
  4455.             if ((SocketError)castedAsyncResult.ErrorCode != SocketError.Success) {
  4456.                 //
  4457.                 // update our internal state after this socket error and throw
  4458.                 //
  4459.                 SocketException socketException = new SocketException(castedAsyncResult.ErrorCode);
  4460.                 UpdateStatusAfterSocketError(socketException);
  4461.                 if (Logging.On)
  4462.                     Logging.Exception(Logging.Sockets, this, "EndAccept", socketException);
  4463.                 throw socketException;
  4464.             }
  4465.            
  4466.             if (Logging.On)
  4467.                 Logging.Exit(Logging.Sockets, this, "EndAccept", result);
  4468.             return (Socket)result;
  4469.         }
  4470.        
  4471.        
  4472.        
  4473.        
  4474.        
  4475.        
  4476.         /// <devdoc>
  4477.         /// <para>
  4478.         /// Disables sends and receives on a socket.
  4479.         /// </para>
  4480.         /// </devdoc>
  4481.         public void Shutdown(SocketShutdown how)
  4482.         {
  4483.             if (Logging.On)
  4484.                 Logging.Enter(Logging.Sockets, this, "Shutdown", how);
  4485.             if (CleanedUp) {
  4486.                 throw new ObjectDisposedException(this.GetType().FullName);
  4487.             }
  4488.            
  4489.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Shutdown() how:" + how.ToString());
  4490.            
  4491.             // This can throw ObjectDisposedException.
  4492.             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.shutdown(m_Handle, (int)how);
  4493.            
  4494.             //
  4495.             // if the native call fails we'll throw a SocketException
  4496.             //
  4497.             errorCode = errorCode != SocketError.SocketError ? SocketError.Success : (SocketError)Marshal.GetLastWin32Error();
  4498.            
  4499.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Shutdown() UnsafeNclNativeMethods.OSSOCK.shutdown returns errorCode:" + errorCode);
  4500.            
  4501.             //
  4502.             // skip good cases: success, socket already closed
  4503.             //
  4504.             if (errorCode != SocketError.Success && errorCode != SocketError.NotSocket) {
  4505.                 //
  4506.                 // update our internal state after this socket error and throw
  4507.                 //
  4508.                 SocketException socketException = new SocketException(errorCode);
  4509.                 UpdateStatusAfterSocketError(socketException);
  4510.                 if (Logging.On)
  4511.                     Logging.Exception(Logging.Sockets, this, "Shutdown", socketException);
  4512.                 throw socketException;
  4513.             }
  4514.            
  4515.             SetToDisconnected();
  4516.             InternalSetBlocking(willBlockInternal);
  4517.             if (Logging.On)
  4518.                 Logging.Exit(Logging.Sockets, this, "Shutdown", "");
  4519.         }
  4520.        
  4521.        
  4522.        
  4523.         //************* internal and private properties *************************
  4524.        
  4525.         private static object InternalSyncObject {
  4526.             get {
  4527.                 if (s_InternalSyncObject == null) {
  4528.                     object o = new object();
  4529.                     Interlocked.CompareExchange(ref s_InternalSyncObject, o, null);
  4530.                 }
  4531.                 return s_InternalSyncObject;
  4532.             }
  4533.         }
  4534.        
  4535.         private CacheSet Caches {
  4536.             get {
  4537.                 if (m_Caches == null) {
  4538.                     // It's not too bad if extra of these are created and lost.
  4539.                     m_Caches = new CacheSet();
  4540.                 }
  4541.                 return m_Caches;
  4542.             }
  4543.         }
  4544.        
  4545.         private DisconnectExDelegate DisconnectEx {
  4546.             get {
  4547.                 //get the disconnect api
  4548.                 if (s_DisconnectEx == null) {
  4549.                     lock (InternalSyncObject) {
  4550.                         if (s_DisconnectEx == null) {
  4551.                             LoadDisconnectEx();
  4552.                         }
  4553.                     }
  4554.                 }
  4555.                 return s_DisconnectEx;
  4556.             }
  4557.         }
  4558.        
  4559.         private DisconnectExDelegate_Blocking DisconnectEx_Blocking {
  4560.             get {
  4561.                 //get the disconnect api
  4562.                 if (s_DisconnectEx_Blocking == null) {
  4563.                     lock (InternalSyncObject) {
  4564.                         if (s_DisconnectEx_Blocking == null) {
  4565.                             LoadDisconnectEx();
  4566.                         }
  4567.                     }
  4568.                 }
  4569.                 return s_DisconnectEx_Blocking;
  4570.             }
  4571.         }
  4572.        
  4573.         private void LoadDisconnectEx()
  4574.         {
  4575.             SocketError errorCode;
  4576.             IntPtr ptrDisconnectEx = IntPtr.Zero;
  4577.            
  4578.             unsafe {
  4579.                 int length;
  4580.                 Guid guid = new Guid("{0x7fda2e11,0x8630,0x436f,{0xa0, 0x31, 0xf5, 0x36, 0xa6, 0xee, 0xc1, 0x57}}");
  4581.                
  4582.                 // This can throw ObjectDisposedException.
  4583.                 errorCode = UnsafeNclNativeMethods.OSSOCK.WSAIoctl(m_Handle, IoctlSocketConstants.SIOGETEXTENSIONFUNCTIONPOINTER, ref guid, sizeof(Guid), out ptrDisconnectEx, sizeof(IntPtr), out length, IntPtr.Zero, IntPtr.Zero);
  4584.             }
  4585.            
  4586.             if (errorCode != SocketError.Success) {
  4587.                 throw new SocketException();
  4588.             }
  4589.             s_DisconnectEx = (DisconnectExDelegate)Marshal.GetDelegateForFunctionPointer(ptrDisconnectEx, typeof(DisconnectExDelegate));
  4590.             s_DisconnectEx_Blocking = (DisconnectExDelegate_Blocking)Marshal.GetDelegateForFunctionPointer(ptrDisconnectEx, typeof(DisconnectExDelegate_Blocking));
  4591.         }
  4592.        
  4593.         private ConnectExDelegate ConnectEx {
  4594.             get {
  4595.                 //get the disconnect api
  4596.                 if (s_ConnectEx == null) {
  4597.                     lock (InternalSyncObject) {
  4598.                         if (s_ConnectEx == null) {
  4599.                            
  4600.                             SocketError errorCode;
  4601.                             IntPtr ptrConnectEx = IntPtr.Zero;
  4602.                            
  4603.                             unsafe {
  4604.                                 int length;
  4605.                                 Guid guid = new Guid("{0x25a207b9,0x0ddf3,0x4660,{0x8e,0xe9,0x76,0xe5,0x8c,0x74,0x06,0x3e}}");
  4606.                                
  4607.                                 // This can throw ObjectDisposedException.
  4608.                                 errorCode = UnsafeNclNativeMethods.OSSOCK.WSAIoctl(m_Handle, IoctlSocketConstants.SIOGETEXTENSIONFUNCTIONPOINTER, ref guid, sizeof(Guid), out ptrConnectEx, sizeof(IntPtr), out length, IntPtr.Zero, IntPtr.Zero);
  4609.                             }
  4610.                            
  4611.                             if (errorCode != SocketError.Success) {
  4612.                                 throw new SocketException();
  4613.                             }
  4614.                             s_ConnectEx = (ConnectExDelegate)Marshal.GetDelegateForFunctionPointer(ptrConnectEx, typeof(ConnectExDelegate));
  4615.                         }
  4616.                     }
  4617.                 }
  4618.                 return s_ConnectEx;
  4619.             }
  4620.         }
  4621.        
  4622.        
  4623.         private WSARecvMsgDelegate WSARecvMsg {
  4624.             get {
  4625.                 //get the disconnect api
  4626.                 if (s_WSARecvMsg == null) {
  4627.                     lock (InternalSyncObject) {
  4628.                         if (s_WSARecvMsg == null) {
  4629.                             LoadWSARecvMsg();
  4630.                         }
  4631.                     }
  4632.                 }
  4633.                 return s_WSARecvMsg;
  4634.             }
  4635.         }
  4636.        
  4637.         private WSARecvMsgDelegate_Blocking WSARecvMsg_Blocking {
  4638.             get {
  4639.                 //get the disconnect api
  4640.                 if (s_WSARecvMsg_Blocking == null) {
  4641.                     lock (InternalSyncObject) {
  4642.                         if (s_WSARecvMsg_Blocking == null) {
  4643.                             LoadWSARecvMsg();
  4644.                         }
  4645.                     }
  4646.                 }
  4647.                 return s_WSARecvMsg_Blocking;
  4648.             }
  4649.         }
  4650.        
  4651.         private void LoadWSARecvMsg()
  4652.         {
  4653.             SocketError errorCode;
  4654.             IntPtr ptrWSARecvMsg = IntPtr.Zero;
  4655.            
  4656.             unsafe {
  4657.                 int length;
  4658.                 Guid guid = new Guid("{0xf689d7c8,0x6f1f,0x436b,{0x8a,0x53,0xe5,0x4f,0xe3,0x51,0xc3,0x22}}");
  4659.                
  4660.                 // This can throw ObjectDisposedException.
  4661.                 errorCode = UnsafeNclNativeMethods.OSSOCK.WSAIoctl(m_Handle, IoctlSocketConstants.SIOGETEXTENSIONFUNCTIONPOINTER, ref guid, sizeof(Guid), out ptrWSARecvMsg, sizeof(IntPtr), out length, IntPtr.Zero, IntPtr.Zero);
  4662.             }
  4663.            
  4664.             if (errorCode != SocketError.Success) {
  4665.                 throw new SocketException();
  4666.             }
  4667.             s_WSARecvMsg = (WSARecvMsgDelegate)Marshal.GetDelegateForFunctionPointer(ptrWSARecvMsg, typeof(WSARecvMsgDelegate));
  4668.             s_WSARecvMsg_Blocking = (WSARecvMsgDelegate_Blocking)Marshal.GetDelegateForFunctionPointer(ptrWSARecvMsg, typeof(WSARecvMsgDelegate_Blocking));
  4669.         }
  4670.        
  4671.        
  4672.         private Queue GetAcceptQueue()
  4673.         {
  4674.             if (m_AcceptQueueOrConnectResult == null)
  4675.                 Interlocked.CompareExchange(ref m_AcceptQueueOrConnectResult, new Queue(16), null);
  4676.             return (Queue)m_AcceptQueueOrConnectResult;
  4677.         }
  4678.        
  4679.         internal bool CleanedUp {
  4680.             get { return (m_IntCleanedUp == 1); }
  4681.         }
  4682.        
  4683.         internal TransportType Transport {
  4684.             get { return protocolType == Sockets.ProtocolType.Tcp ? TransportType.Tcp : protocolType == Sockets.ProtocolType.Udp ? TransportType.Udp : TransportType.All; }
  4685.         }
  4686.        
  4687.        
  4688.         //************* internal and private methods *************************
  4689.        
  4690.        
  4691.        
  4692.         private void CheckSetOptionPermissions(SocketOptionLevel optionLevel, SocketOptionName optionName)
  4693.         {
  4694.             // freely allow only those below
  4695.             //ipv6 protection level
  4696.             if (!(optionLevel == SocketOptionLevel.Tcp && (optionName == SocketOptionName.NoDelay || optionName == SocketOptionName.BsdUrgent || optionName == SocketOptionName.Expedited)) && !(optionLevel == SocketOptionLevel.Udp && (optionName == SocketOptionName.NoChecksum || optionName == SocketOptionName.ChecksumCoverage)) && !(optionLevel == SocketOptionLevel.Socket && (optionName == SocketOptionName.KeepAlive || optionName == SocketOptionName.Linger || optionName == SocketOptionName.DontLinger || optionName == SocketOptionName.SendBuffer || optionName == SocketOptionName.ReceiveBuffer || optionName == SocketOptionName.SendTimeout || optionName == SocketOptionName.ExclusiveAddressUse || optionName == SocketOptionName.ReceiveTimeout)) && !(optionLevel == SocketOptionLevel.IPv6 && optionName == (SocketOptionName)23)) {
  4697.                
  4698.                 ExceptionHelper.UnmanagedPermission.Demand();
  4699.             }
  4700.         }
  4701.        
  4702.         [SuppressUnmanagedCodeSecurity()]
  4703.         delegate bool ConnectExDelegate(SafeCloseSocket socketHandle, IntPtr socketAddress, int socketAddressSize, IntPtr buffer, int dataLength, int bytesSent, IntPtr overlapped);
  4704.        
  4705.         [SuppressUnmanagedCodeSecurity()]
  4706.         delegate bool DisconnectExDelegate(SafeCloseSocket socketHandle, IntPtr overlapped, int flags, int reserved);
  4707.        
  4708.         [SuppressUnmanagedCodeSecurity()]
  4709.         delegate bool DisconnectExDelegate_Blocking(IntPtr socketHandle, IntPtr overlapped, int flags, int reserved);
  4710.        
  4711.         [SuppressUnmanagedCodeSecurity()]
  4712.         unsafe delegate SocketError WSARecvMsgDelegate(SafeCloseSocket socketHandle, IntPtr msg, out int bytesTransferred, IntPtr overlapped, IntPtr completionRoutine);
  4713.        
  4714.         [SuppressUnmanagedCodeSecurity()]
  4715.         unsafe delegate SocketError WSARecvMsgDelegate_Blocking(IntPtr socketHandle, IntPtr msg, out int bytesTransferred, IntPtr overlapped, IntPtr completionRoutine);
  4716.        
  4717.         private SocketAddress SnapshotAndSerialize(ref EndPoint remoteEP)
  4718.         {
  4719.             IPEndPoint ipSnapshot = remoteEP as IPEndPoint;
  4720.            
  4721.             if (ipSnapshot != null) {
  4722.                 ipSnapshot = ipSnapshot.Snapshot();
  4723.                 remoteEP = ipSnapshot;
  4724.             }
  4725.            
  4726.             return remoteEP.Serialize();
  4727.         }
  4728.        
  4729.         //
  4730.         // socketAddress must always be the result of remoteEP.Serialize()
  4731.         //
  4732.         private SocketAddress CheckCacheRemote(ref EndPoint remoteEP, bool isOverwrite)
  4733.         {
  4734.             IPEndPoint ipSnapshot = remoteEP as IPEndPoint;
  4735.            
  4736.             if (ipSnapshot != null) {
  4737.                 ipSnapshot = ipSnapshot.Snapshot();
  4738.                 remoteEP = ipSnapshot;
  4739.             }
  4740.            
  4741.             // This doesn't use SnapshotAndSerialize() because we need the ipSnapshot later.
  4742.             SocketAddress socketAddress = remoteEP.Serialize();
  4743.            
  4744.             // We remember the first peer we have communicated with
  4745.             SocketAddress permittedRemoteAddress = m_PermittedRemoteAddress;
  4746.             if (permittedRemoteAddress != null && permittedRemoteAddress.Equals(socketAddress)) {
  4747.                 return permittedRemoteAddress;
  4748.             }
  4749.            
  4750.             //
  4751.             // for now SocketPermission supports only IPEndPoint
  4752.             //
  4753.             if (ipSnapshot != null) {
  4754.                 //
  4755.                 // create the permissions the user would need for the call
  4756.                 //
  4757.                 SocketPermission socketPermission = new SocketPermission(NetworkAccess.Connect, Transport, ipSnapshot.Address.ToString(), ipSnapshot.Port);
  4758.                 //
  4759.                 // demand for them
  4760.                 //
  4761.                 socketPermission.Demand();
  4762.             }
  4763.             else {
  4764.                 //
  4765.                 // for V1 we will demand permission to run UnmanagedCode for
  4766.                 // an EndPoint that is not an IPEndPoint until we figure out how these fit
  4767.                 // into the whole picture of SocketPermission
  4768.                 //
  4769.                
  4770.                 ExceptionHelper.UnmanagedPermission.Demand();
  4771.             }
  4772.             //cache only the first peer we communicated with
  4773.             if (m_PermittedRemoteAddress == null || isOverwrite) {
  4774.                 m_PermittedRemoteAddress = socketAddress;
  4775.             }
  4776.            
  4777.             return socketAddress;
  4778.         }
  4779.        
  4780.        
  4781.         static internal void InitializeSockets()
  4782.         {
  4783.             if (!s_Initialized) {
  4784.                 lock (InternalSyncObject) {
  4785.                     if (!s_Initialized) {
  4786.                        
  4787.                         WSAData wsaData = new WSAData();
  4788.                        
  4789.                             // we need 2.2
  4790.                         SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.WSAStartup((short)514, out wsaData);
  4791.                        
  4792.                         if (errorCode != SocketError.Success) {
  4793.                             //
  4794.                             // failed to initialize, throw
  4795.                             //
  4796.                             throw new SocketException();
  4797.                         }
  4798.                        
  4799.                        
  4800.                         s_SupportsIPv4 = true;
  4801.                         s_SupportsIPv6 = false;
  4802.                        
  4803.                        
  4804.                         s_Initialized = true;
  4805.                     }
  4806.                 }
  4807.             }
  4808.         }
  4809.        
  4810.        
  4811.         internal void InternalConnect(EndPoint remoteEP)
  4812.         {
  4813.             EndPoint endPointSnapshot = remoteEP;
  4814.             SocketAddress socketAddress = SnapshotAndSerialize(ref endPointSnapshot);
  4815.             DoConnect(endPointSnapshot, socketAddress);
  4816.         }
  4817.        
  4818.         private void DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
  4819.         {
  4820.             if (Logging.On)
  4821.                 Logging.Enter(Logging.Sockets, this, "Connect", endPointSnapshot);
  4822.            
  4823.             // This can throw ObjectDisposedException.
  4824.             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.WSAConnect(m_Handle.DangerousGetHandle(), socketAddress.m_Buffer, socketAddress.m_Size, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
  4825.            
  4826.            
  4827.             //
  4828.             // if the native call fails we'll throw a SocketException
  4829.             //
  4830.             if (errorCode != SocketError.Success) {
  4831.                 //
  4832.                 // update our internal state after this socket error and throw
  4833.                 //
  4834.                 SocketException socketException = new SocketException();
  4835.                 UpdateStatusAfterSocketError(socketException);
  4836.                 if (Logging.On)
  4837.                     Logging.Exception(Logging.Sockets, this, "Connect", socketException);
  4838.                 throw socketException;
  4839.             }
  4840.            
  4841.             if (m_RightEndPoint == null) {
  4842.                 //
  4843.                 // save a copy of the EndPoint so we can use it for Create()
  4844.                 //
  4845.                 m_RightEndPoint = endPointSnapshot;
  4846.             }
  4847.            
  4848.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoConnect() connection to:" + endPointSnapshot.ToString());
  4849.            
  4850.             //
  4851.             // update state and performance counter
  4852.             //
  4853.             SetToConnected();
  4854.             if (Logging.On)
  4855.                 Logging.Exit(Logging.Sockets, this, "Connect", "");
  4856.         }
  4857.        
  4858.        
  4859.         protected virtual void Dispose(bool disposing)
  4860.         {
  4861.             //we should swallow exceptions in the logging code for Dispose.
  4862.             try {
  4863.                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Dispose() disposing:" + disposing.ToString() + " CleanedUp:" + CleanedUp.ToString());
  4864.                 if (Logging.On)
  4865.                     Logging.Enter(Logging.Sockets, this, "Dispose", null);
  4866.             }
  4867.             catch (Exception exception) {
  4868.                 if (NclUtilities.IsFatal(exception))
  4869.                     throw;
  4870.             }
  4871.            
  4872.             // For finalization, we should close the handle if it's still alive, and nothing else. Use abortive close to not block
  4873.             // the finalizer thread.
  4874.             if (!disposing) {
  4875.                 if (m_Handle != null && !m_Handle.IsInvalid) {
  4876.                     GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Dispose() Calling m_Handle.Dispose()");
  4877.                     m_Handle.Dispose();
  4878.                 }
  4879.                 return;
  4880.             }
  4881.            
  4882.             // make sure we're the first call to Dispose and no SetAsyncEventSelect is in progress
  4883.             int last;
  4884.             while ((last = Interlocked.CompareExchange(ref m_IntCleanedUp, 1, 0)) == 2) {
  4885.                 Thread.SpinWait(1);
  4886.             }
  4887.             if (last == 1) {
  4888.                 try {
  4889.                     if (Logging.On)
  4890.                         Logging.Exit(Logging.Sockets, this, "Dispose", null);
  4891.                 }
  4892.                 catch (Exception exception) {
  4893.                     if (NclUtilities.IsFatal(exception))
  4894.                         throw;
  4895.                 }
  4896.                 return;
  4897.             }
  4898.            
  4899.             SetToDisconnected();
  4900.            
  4901.             AsyncEventBits pendingAsync = AsyncEventBits.FdNone;
  4902.             if (m_BlockEventBits != AsyncEventBits.FdNone) {
  4903.                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Dispose() Pending nonblocking operations! m_BlockEventBits:" + m_BlockEventBits.ToString());
  4904.                 UnsetAsyncEventSelect();
  4905.                 if (m_BlockEventBits == AsyncEventBits.FdConnect) {
  4906.                     LazyAsyncResult connectResult = m_AcceptQueueOrConnectResult as LazyAsyncResult;
  4907.                     if (connectResult != null && !connectResult.InternalPeekCompleted)
  4908.                         pendingAsync = AsyncEventBits.FdConnect;
  4909.                 }
  4910.                 else if (m_BlockEventBits == AsyncEventBits.FdAccept) {
  4911.                     Queue acceptQueue = m_AcceptQueueOrConnectResult as Queue;
  4912.                     if (acceptQueue != null && acceptQueue.Count != 0)
  4913.                         pendingAsync = AsyncEventBits.FdAccept;
  4914.                 }
  4915.             }
  4916.            
  4917.             // Close the handle in one of several ways depending on the timeout.
  4918.             // Swallow ObjectDisposedException just in case the handle somehow gets disposed elsewhere.
  4919.             try {
  4920.                 int timeout = m_CloseTimeout;
  4921.                 if (timeout == 0) {
  4922.                     // Abortive.
  4923.                     GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Dispose() Calling m_Handle.Dispose()");
  4924.                     m_Handle.Dispose();
  4925.                 }
  4926.                 else {
  4927.                     SocketError errorCode;
  4928.                    
  4929.                     // Go to blocking mode. We know no WSAEventSelect is pending because of the lock and UnsetAsyncEventSelect() above.
  4930.                     if (!willBlock || !willBlockInternal) {
  4931.                         int nonBlockCmd = 0;
  4932.                         errorCode = UnsafeNclNativeMethods.OSSOCK.ioctlsocket(m_Handle, IoctlSocketConstants.FIONBIO, ref nonBlockCmd);
  4933.                         GlobalLog.Print("SafeCloseSocket::Dispose(handle:" + m_Handle.DangerousGetHandle().ToString("x") + ") ioctlsocket(FIONBIO):" + (errorCode == SocketError.SocketError ? (SocketError)Marshal.GetLastWin32Error() : errorCode).ToString());
  4934.                     }
  4935.                    
  4936.                     if (timeout < 0) {
  4937.                         // Close with existing user-specified linger option.
  4938.                         GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Dispose() Calling m_Handle.CloseAsIs()");
  4939.                         m_Handle.CloseAsIs();
  4940.                     }
  4941.                     else {
  4942.                         // Since our timeout is in ms and linger is in seconds, implement our own sortof linger here.
  4943.                         errorCode = UnsafeNclNativeMethods.OSSOCK.shutdown(m_Handle, (int)SocketShutdown.Send);
  4944.                         GlobalLog.Print("SafeCloseSocket::Dispose(handle:" + m_Handle.DangerousGetHandle().ToString("x") + ") shutdown():" + (errorCode == SocketError.SocketError ? (SocketError)Marshal.GetLastWin32Error() : errorCode).ToString());
  4945.                        
  4946.                         // This should give us a timeout in milliseconds.
  4947.                         errorCode = UnsafeNclNativeMethods.OSSOCK.setsockopt(m_Handle, SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, ref timeout, sizeof(int));
  4948.                         GlobalLog.Print("SafeCloseSocket::Dispose(handle:" + m_Handle.DangerousGetHandle().ToString("x") + ") setsockopt():" + (errorCode == SocketError.SocketError ? (SocketError)Marshal.GetLastWin32Error() : errorCode).ToString());
  4949.                        
  4950.                         if (errorCode != SocketError.Success) {
  4951.                             m_Handle.Dispose();
  4952.                         }
  4953.                         else {
  4954.                             unsafe {
  4955.                                 errorCode = (SocketError)UnsafeNclNativeMethods.OSSOCK.recv(m_Handle.DangerousGetHandle(), null, 0, SocketFlags.None);
  4956.                             }
  4957.                             GlobalLog.Print("SafeCloseSocket::Dispose(handle:" + m_Handle.DangerousGetHandle().ToString("x") + ") recv():" + errorCode.ToString());
  4958.                            
  4959.                             if (errorCode != (SocketError)0) {
  4960.                                 // We got a timeout - abort.
  4961.                                 m_Handle.Dispose();
  4962.                             }
  4963.                             else {
  4964.                                 // We got a FIN or data. Use ioctlsocket to find out which.
  4965.                                 int dataAvailable = 0;
  4966.                                 errorCode = UnsafeNclNativeMethods.OSSOCK.ioctlsocket(m_Handle, IoctlSocketConstants.FIONREAD, ref dataAvailable);
  4967.                                 GlobalLog.Print("SafeCloseSocket::Dispose(handle:" + m_Handle.DangerousGetHandle().ToString("x") + ") ioctlsocket(FIONREAD):" + (errorCode == SocketError.SocketError ? (SocketError)Marshal.GetLastWin32Error() : errorCode).ToString());
  4968.                                
  4969.                                 if (errorCode != SocketError.Success || dataAvailable != 0) {
  4970.                                     // If we have data or don't know, safest thing is to reset.
  4971.                                     m_Handle.Dispose();
  4972.                                 }
  4973.                                 else {
  4974.                                     // We got a FIN. It'd be nice to block for the remainder of the timeout for the handshake to finsh.
  4975.                                     // Since there's no real way to do that, close the socket with the user's preferences. This lets
  4976.                                     // the user decide how best to handle this case via the linger options.
  4977.                                     m_Handle.CloseAsIs();
  4978.                                 }
  4979.                             }
  4980.                         }
  4981.                     }
  4982.                 }
  4983.             }
  4984.             catch (ObjectDisposedException) {
  4985.                 GlobalLog.Assert("SafeCloseSocket::Dispose(handle:" + m_Handle.DangerousGetHandle().ToString("x") + ")", "Closing the handle threw ObjectDisposedException.");
  4986.             }
  4987.            
  4988.             #if !DEBUG
  4989.             // Clear out the Overlapped caches.
  4990.             if (m_Caches != null) {
  4991.                 OverlappedCache.InterlockedFree(ref m_Caches.SendOverlappedCache);
  4992.                 OverlappedCache.InterlockedFree(ref m_Caches.ReceiveOverlappedCache);
  4993.             }
  4994.             #endif
  4995.            
  4996.             if (pendingAsync == AsyncEventBits.FdConnect) {
  4997.                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Dispose() QueueUserWorkItem for ConnectCallback");
  4998.                 // This will try to complete connectResult on a different thread
  4999.                 ThreadPool.UnsafeQueueUserWorkItem(new WaitCallback(((LazyAsyncResult)m_AcceptQueueOrConnectResult).InvokeCallback), new SocketException(SocketError.OperationAborted));
  5000.             }
  5001.             else if (pendingAsync == AsyncEventBits.FdAccept) {
  5002.                 // This will try to complete all acceptResults on a different thread
  5003.                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::Dispose() QueueUserWorkItem for AcceptCallback");
  5004.                 ThreadPool.UnsafeQueueUserWorkItem(new WaitCallback(CompleteAcceptResults), null);
  5005.             }
  5006.            
  5007.             if (m_AsyncEvent != null) {
  5008.                 m_AsyncEvent.Close();
  5009.             }
  5010.         }
  5011.        
  5012.         /// <internalonly/>
  5013.         void IDisposable.Dispose()
  5014.         {
  5015.             Dispose(true);
  5016.             GC.SuppressFinalize(this);
  5017.         }
  5018.        
  5019.         ~Socket()
  5020.         {
  5021.             #if DEBUG
  5022.             GlobalLog.SetThreadSource(ThreadKinds.Finalization);
  5023.             // using (GlobalLog.SetThreadKind(ThreadKinds.System | ThreadKinds.Async)) {
  5024.             #endif
  5025.             Dispose(false);
  5026.             #if DEBUG
  5027.             //}
  5028.             #endif
  5029.         }
  5030.        
  5031.         // this version does not throw.
  5032.         internal void InternalShutdown(SocketShutdown how)
  5033.         {
  5034.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::InternalShutdown() how:" + how.ToString());
  5035.            
  5036.             if (CleanedUp || m_Handle.IsInvalid) {
  5037.                 return;
  5038.             }
  5039.            
  5040.             try {
  5041.                 UnsafeNclNativeMethods.OSSOCK.shutdown(m_Handle, (int)how);
  5042.             }
  5043.             catch (ObjectDisposedException) {
  5044.             }
  5045.         }
  5046.        
  5047.        
  5048.         [ResourceExposure(ResourceScope.Machine)]
  5049.         [ResourceConsumption(ResourceScope.Machine)]
  5050.         private void DownLevelSendFile(string fileName)
  5051.         {
  5052.             if (Logging.On)
  5053.                 Logging.Enter(Logging.Sockets, this, "SendFile", "");
  5054.            
  5055.             if (CleanedUp) {
  5056.                 throw new ObjectDisposedException(this.GetType().FullName);
  5057.             }
  5058.            
  5059.             if (!Connected) {
  5060.                 throw new NotSupportedException(SR.GetString(SR.net_notconnected));
  5061.             }
  5062.            
  5063.             ValidateBlockingMode();
  5064.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SendFile() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " DST:" + ValidationHelper.ToString(RemoteEndPoint) + " fileName:" + fileName);
  5065.            
  5066.             FileStream fileStream = null;
  5067.             if (fileName != null && fileName.Length > 0) {
  5068.                 fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
  5069.             }
  5070.            
  5071.             try {
  5072.                 SocketError errorCode = SocketError.Success;
  5073.                
  5074.                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SendFile() DST:" + ValidationHelper.ToString(RemoteEndPoint) + " UnsafeNclNativeMethods.OSSOCK.TransmitFile returns errorCode:" + errorCode);
  5075.                
  5076.                 //
  5077.                 // if the native call fails we'll throw a SocketException
  5078.                 //
  5079.                 byte[] buffer = new byte[64000];
  5080.                 while (true) {
  5081.                     int read = fileStream.Read(buffer, 0, buffer.Length);
  5082.                     if (read == 0) {
  5083.                         break;
  5084.                     }
  5085.                     Send(buffer, 0, read, SocketFlags.None);
  5086.                 }
  5087.                 if (Logging.On)
  5088.                     Logging.Exit(Logging.Sockets, this, "SendFile", errorCode);
  5089.             }
  5090.             finally {
  5091.                 DownLevelSendFileCleanup(fileStream);
  5092.             }
  5093.             return;
  5094.         }
  5095.        
  5096.         unsafe internal void SetSocketOption(SocketOptionLevel optionLevel, SocketOptionName optionName, int optionValue, bool silent)
  5097.         {
  5098.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SetSocketOption() optionLevel:" + optionLevel + " optionName:" + optionName + " optionValue:" + optionValue + " silent:" + silent);
  5099.             if (silent && (CleanedUp || m_Handle.IsInvalid)) {
  5100.                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SetSocketOption() skipping the call");
  5101.                 return;
  5102.             }
  5103.             SocketError errorCode = SocketError.Success;
  5104.             try {
  5105.                 // This can throw ObjectDisposedException.
  5106.                 errorCode = UnsafeNclNativeMethods.OSSOCK.setsockopt(m_Handle, optionLevel, optionName, ref optionValue, sizeof(int));
  5107.                
  5108.                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SetSocketOption() UnsafeNclNativeMethods.OSSOCK.setsockopt returns errorCode:" + errorCode);
  5109.             }
  5110.             catch {
  5111.                 if (silent && m_Handle.IsInvalid) {
  5112.                     return;
  5113.                 }
  5114.                 throw;
  5115.             }
  5116.             if (silent) {
  5117.                 return;
  5118.             }
  5119.            
  5120.             //
  5121.             // if the native call fails we'll throw a SocketException
  5122.             //
  5123.             if (errorCode == SocketError.SocketError) {
  5124.                 //
  5125.                 // update our internal state after this socket error and throw
  5126.                 //
  5127.                 SocketException socketException = new SocketException();
  5128.                 UpdateStatusAfterSocketError(socketException);
  5129.                 if (Logging.On)
  5130.                     Logging.Exception(Logging.Sockets, this, "SetSocketOption", socketException);
  5131.                 throw socketException;
  5132.             }
  5133.         }
  5134.        
  5135.         private void setMulticastOption(SocketOptionName optionName, MulticastOption MR)
  5136.         {
  5137.             IPMulticastRequest ipmr = new IPMulticastRequest();
  5138.            
  5139.             ipmr.MulticastAddress = unchecked((int)MR.Group.m_Address);
  5140.            
  5141.            
  5142.             if (MR.LocalAddress != null) {
  5143.                 ipmr.InterfaceAddress = unchecked((int)MR.LocalAddress.m_Address);
  5144.             }
  5145.             else {
  5146.                 //this structure works w/ interfaces as well
  5147.                 int ifIndex = IPAddress.HostToNetworkOrder(MR.InterfaceIndex);
  5148.                 ipmr.InterfaceAddress = unchecked((int)ifIndex);
  5149.             }
  5150.            
  5151.             #if BIGENDIAN
  5152.             ipmr.MulticastAddress = (int)(((uint)ipmr.MulticastAddress << 24) | (((uint)ipmr.MulticastAddress & 65280) << 8) | (((uint)ipmr.MulticastAddress >> 8) & 65280) | ((uint)ipmr.MulticastAddress >> 24));
  5153.            
  5154.             if (MR.LocalAddress != null) {
  5155.                 ipmr.InterfaceAddress = (int)(((uint)ipmr.InterfaceAddress << 24) | (((uint)ipmr.InterfaceAddress & 65280) << 8) | (((uint)ipmr.InterfaceAddress >> 8) & 65280) | ((uint)ipmr.InterfaceAddress >> 24));
  5156.             }
  5157.             #endif // BIGENDIAN
  5158.            
  5159.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::setMulticastOption(): optionName:" + optionName.ToString() + " MR:" + MR.ToString() + " ipmr:" + ipmr.ToString() + " IPMulticastRequest.Size:" + IPMulticastRequest.Size.ToString());
  5160.            
  5161.             // This can throw ObjectDisposedException.
  5162.             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.setsockopt(m_Handle, SocketOptionLevel.IP, optionName, ref ipmr, IPMulticastRequest.Size);
  5163.            
  5164.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::setMulticastOption() UnsafeNclNativeMethods.OSSOCK.setsockopt returns errorCode:" + errorCode);
  5165.            
  5166.             //
  5167.             // if the native call fails we'll throw a SocketException
  5168.             //
  5169.             if (errorCode == SocketError.SocketError) {
  5170.                 //
  5171.                 // update our internal state after this socket error and throw
  5172.                 //
  5173.                 SocketException socketException = new SocketException();
  5174.                 UpdateStatusAfterSocketError(socketException);
  5175.                 if (Logging.On)
  5176.                     Logging.Exception(Logging.Sockets, this, "setMulticastOption", socketException);
  5177.                 throw socketException;
  5178.             }
  5179.         }
  5180.        
  5181.        
  5182.         /// <devdoc>
  5183.         /// <para>
  5184.         /// IPv6 setsockopt for JOIN / LEAVE multicast group
  5185.         /// </para>
  5186.         /// </devdoc>
  5187.         private void setIPv6MulticastOption(SocketOptionName optionName, IPv6MulticastOption MR)
  5188.         {
  5189.             IPv6MulticastRequest ipmr = new IPv6MulticastRequest();
  5190.            
  5191.             ipmr.MulticastAddress = MR.Group.GetAddressBytes();
  5192.             ipmr.InterfaceIndex = unchecked((int)MR.InterfaceIndex);
  5193.            
  5194.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::setIPv6MulticastOption(): optionName:" + optionName.ToString() + " MR:" + MR.ToString() + " ipmr:" + ipmr.ToString() + " IPv6MulticastRequest.Size:" + IPv6MulticastRequest.Size.ToString());
  5195.            
  5196.             // This can throw ObjectDisposedException.
  5197.             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.setsockopt(m_Handle, SocketOptionLevel.IPv6, optionName, ref ipmr, IPv6MulticastRequest.Size);
  5198.            
  5199.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::setIPv6MulticastOption() UnsafeNclNativeMethods.OSSOCK.setsockopt returns errorCode:" + errorCode);
  5200.            
  5201.             //
  5202.             // if the native call fails we'll throw a SocketException
  5203.             //
  5204.             if (errorCode == SocketError.SocketError) {
  5205.                 //
  5206.                 // update our internal state after this socket error and throw
  5207.                 //
  5208.                 SocketException socketException = new SocketException();
  5209.                 UpdateStatusAfterSocketError(socketException);
  5210.                 if (Logging.On)
  5211.                     Logging.Exception(Logging.Sockets, this, "setIPv6MulticastOption", socketException);
  5212.                 throw socketException;
  5213.             }
  5214.         }
  5215.        
  5216.         private void setLingerOption(LingerOption lref)
  5217.         {
  5218.             Linger lngopt = new Linger();
  5219.             lngopt.OnOff = lref.Enabled ? (short)1 : (short)0;
  5220.             lngopt.Time = (short)lref.LingerTime;
  5221.            
  5222.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::setLingerOption(): lref:" + lref.ToString());
  5223.            
  5224.             // This can throw ObjectDisposedException.
  5225.             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.setsockopt(m_Handle, SocketOptionLevel.Socket, SocketOptionName.Linger, ref lngopt, Linger.Size);
  5226.            
  5227.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::setLingerOption() UnsafeNclNativeMethods.OSSOCK.setsockopt returns errorCode:" + errorCode);
  5228.            
  5229.             //
  5230.             // if the native call fails we'll throw a SocketException
  5231.             //
  5232.             if (errorCode == SocketError.SocketError) {
  5233.                 //
  5234.                 // update our internal state after this socket error and throw
  5235.                 //
  5236.                 SocketException socketException = new SocketException();
  5237.                 UpdateStatusAfterSocketError(socketException);
  5238.                 if (Logging.On)
  5239.                     Logging.Exception(Logging.Sockets, this, "setLingerOption", socketException);
  5240.                 throw socketException;
  5241.             }
  5242.         }
  5243.        
  5244.         private LingerOption getLingerOpt()
  5245.         {
  5246.             Linger lngopt = new Linger();
  5247.             int optlen = Linger.Size;
  5248.            
  5249.             // This can throw ObjectDisposedException.
  5250.             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.getsockopt(m_Handle, SocketOptionLevel.Socket, SocketOptionName.Linger, out lngopt, ref optlen);
  5251.            
  5252.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::getLingerOpt() UnsafeNclNativeMethods.OSSOCK.getsockopt returns errorCode:" + errorCode);
  5253.            
  5254.             //
  5255.             // if the native call fails we'll throw a SocketException
  5256.             //
  5257.             if (errorCode == SocketError.SocketError) {
  5258.                 //
  5259.                 // update our internal state after this socket error and throw
  5260.                 //
  5261.                 SocketException socketException = new SocketException();
  5262.                 UpdateStatusAfterSocketError(socketException);
  5263.                 if (Logging.On)
  5264.                     Logging.Exception(Logging.Sockets, this, "getLingerOpt", socketException);
  5265.                 throw socketException;
  5266.             }
  5267.            
  5268.             LingerOption lingerOption = new LingerOption(lngopt.OnOff != 0, (int)lngopt.Time);
  5269.             return lingerOption;
  5270.         }
  5271.        
  5272.         private MulticastOption getMulticastOpt(SocketOptionName optionName)
  5273.         {
  5274.             IPMulticastRequest ipmr = new IPMulticastRequest();
  5275.             int optlen = IPMulticastRequest.Size;
  5276.            
  5277.             // This can throw ObjectDisposedException.
  5278.             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.getsockopt(m_Handle, SocketOptionLevel.IP, optionName, out ipmr, ref optlen);
  5279.            
  5280.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::getMulticastOpt() UnsafeNclNativeMethods.OSSOCK.getsockopt returns errorCode:" + errorCode);
  5281.            
  5282.             //
  5283.             // if the native call fails we'll throw a SocketException
  5284.             //
  5285.             if (errorCode == SocketError.SocketError) {
  5286.                 //
  5287.                 // update our internal state after this socket error and throw
  5288.                 //
  5289.                 SocketException socketException = new SocketException();
  5290.                 UpdateStatusAfterSocketError(socketException);
  5291.                 if (Logging.On)
  5292.                     Logging.Exception(Logging.Sockets, this, "getMulticastOpt", socketException);
  5293.                 throw socketException;
  5294.             }
  5295.            
  5296.             #if BIGENDIAN
  5297.             ipmr.MulticastAddress = (int)(((uint)ipmr.MulticastAddress << 24) | (((uint)ipmr.MulticastAddress & 65280) << 8) | (((uint)ipmr.MulticastAddress >> 8) & 65280) | ((uint)ipmr.MulticastAddress >> 24));
  5298.             ipmr.InterfaceAddress = (int)(((uint)ipmr.InterfaceAddress << 24) | (((uint)ipmr.InterfaceAddress & 65280) << 8) | (((uint)ipmr.InterfaceAddress >> 8) & 65280) | ((uint)ipmr.InterfaceAddress >> 24));
  5299.             #endif // BIGENDIAN
  5300.            
  5301.             IPAddress multicastAddr = new IPAddress(ipmr.MulticastAddress);
  5302.             IPAddress multicastIntr = new IPAddress(ipmr.InterfaceAddress);
  5303.            
  5304.             MulticastOption multicastOption = new MulticastOption(multicastAddr, multicastIntr);
  5305.            
  5306.             return multicastOption;
  5307.         }
  5308.        
  5309.        
  5310.         /// <devdoc>
  5311.         /// <para>
  5312.         /// IPv6 getsockopt for JOIN / LEAVE multicast group
  5313.         /// </para>
  5314.         /// </devdoc>
  5315.         private IPv6MulticastOption getIPv6MulticastOpt(SocketOptionName optionName)
  5316.         {
  5317.             IPv6MulticastRequest ipmr = new IPv6MulticastRequest();
  5318.            
  5319.             int optlen = IPv6MulticastRequest.Size;
  5320.            
  5321.             // This can throw ObjectDisposedException.
  5322.             SocketError errorCode = UnsafeNclNativeMethods.OSSOCK.getsockopt(m_Handle, SocketOptionLevel.IP, optionName, out ipmr, ref optlen);
  5323.            
  5324.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::getIPv6MulticastOpt() UnsafeNclNativeMethods.OSSOCK.getsockopt returns errorCode:" + errorCode);
  5325.            
  5326.             //
  5327.             // if the native call fails we'll throw a SocketException
  5328.             //
  5329.             if (errorCode == SocketError.SocketError) {
  5330.                 //
  5331.                 // update our internal state after this socket error and throw
  5332.                 //
  5333.                 SocketException socketException = new SocketException();
  5334.                 UpdateStatusAfterSocketError(socketException);
  5335.                 if (Logging.On)
  5336.                     Logging.Exception(Logging.Sockets, this, "getIPv6MulticastOpt", socketException);
  5337.                 throw socketException;
  5338.             }
  5339.            
  5340.             IPv6MulticastOption multicastOption = new IPv6MulticastOption(new IPAddress(ipmr.MulticastAddress), ipmr.InterfaceIndex);
  5341.            
  5342.             return multicastOption;
  5343.         }
  5344.        
  5345.         //
  5346.         // this version will ignore failures but it returns the win32
  5347.         // error code, and it will update internal state on success.
  5348.         //
  5349.         private SocketError InternalSetBlocking(bool desired, out bool current)
  5350.         {
  5351.             GlobalLog.Enter("Socket#" + ValidationHelper.HashString(this) + "::InternalSetBlocking", "desired:" + desired.ToString() + " willBlock:" + willBlock.ToString() + " willBlockInternal:" + willBlockInternal.ToString());
  5352.            
  5353.             if (CleanedUp) {
  5354.                 GlobalLog.Leave("Socket#" + ValidationHelper.HashString(this) + "::InternalSetBlocking", "ObjectDisposed");
  5355.                 current = willBlock;
  5356.                 return SocketError.Success;
  5357.             }
  5358.            
  5359.             int intBlocking = desired ? 0 : -1;
  5360.            
  5361.             SocketError errorCode;
  5362.             try {
  5363.                 errorCode = UnsafeNclNativeMethods.OSSOCK.ioctlsocket(m_Handle, IoctlSocketConstants.FIONBIO, ref intBlocking);
  5364.                
  5365.                 if (errorCode == SocketError.SocketError) {
  5366.                     errorCode = (SocketError)Marshal.GetLastWin32Error();
  5367.                 }
  5368.             }
  5369.             catch (ObjectDisposedException) {
  5370.                 errorCode = SocketError.NotSocket;
  5371.             }
  5372.            
  5373.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::InternalSetBlocking() UnsafeNclNativeMethods.OSSOCK.ioctlsocket returns errorCode:" + errorCode);
  5374.            
  5375.             //
  5376.             // we will update only internal state but only on successfull win32 call
  5377.             // so if the native call fails, the state will remain the same.
  5378.             //
  5379.             if (errorCode == SocketError.Success) {
  5380.                 //
  5381.                 // success, update internal state
  5382.                 //
  5383.                 willBlockInternal = intBlocking == 0;
  5384.             }
  5385.            
  5386.             GlobalLog.Leave("Socket#" + ValidationHelper.HashString(this) + "::InternalSetBlocking", "errorCode:" + errorCode.ToString() + " willBlock:" + willBlock.ToString() + " willBlockInternal:" + willBlockInternal.ToString());
  5387.             current = willBlockInternal;
  5388.             return errorCode;
  5389.         }
  5390.         //
  5391.         // this version will ignore all failures.
  5392.         //
  5393.         internal void InternalSetBlocking(bool desired)
  5394.         {
  5395.             bool current;
  5396.             InternalSetBlocking(desired, out current);
  5397.         }
  5398.        
  5399.         private static IntPtr[] SocketListToFileDescriptorSet(IList socketList)
  5400.         {
  5401.             if (socketList == null || socketList.Count == 0) {
  5402.                 return null;
  5403.             }
  5404.             IntPtr[] fileDescriptorSet = new IntPtr[socketList.Count + 1];
  5405.             fileDescriptorSet[0] = (IntPtr)socketList.Count;
  5406.             for (int current = 0; current < socketList.Count; current++) {
  5407.                 if (!(socketList[current] is Socket)) {
  5408.                     throw new ArgumentException(SR.GetString(SR.net_sockets_select, socketList[current].GetType().FullName, typeof(System.Net.Sockets.Socket).FullName), "socketList");
  5409.                 }
  5410.                 fileDescriptorSet[current + 1] = ((Socket)socketList[current]).m_Handle.DangerousGetHandle();
  5411.             }
  5412.             return fileDescriptorSet;
  5413.         }
  5414.        
  5415.         //
  5416.         // Transform the list socketList such that the only sockets left are those
  5417.         // with a file descriptor contained in the array "fileDescriptorArray"
  5418.         //
  5419.         private static void SelectFileDescriptor(IList socketList, IntPtr[] fileDescriptorSet)
  5420.         {
  5421.             // Walk the list in order
  5422.             // Note that the counter is not necessarily incremented at each step;
  5423.             // when the socket is removed, advancing occurs automatically as the
  5424.             // other elements are shifted down.
  5425.             if (socketList == null || socketList.Count == 0) {
  5426.                 return;
  5427.             }
  5428.             if ((int)fileDescriptorSet[0] == 0) {
  5429.                 // no socket present, will never find any socket, remove them all
  5430.                 socketList.Clear();
  5431.                 return;
  5432.             }
  5433.             lock (socketList) {
  5434.                 for (int currentSocket = 0; currentSocket < socketList.Count; currentSocket++) {
  5435.                     Socket socket = socketList[currentSocket] as Socket;
  5436.                     // Look for the file descriptor in the array
  5437.                     int currentFileDescriptor;
  5438.                     for (currentFileDescriptor = 0; currentFileDescriptor < (int)fileDescriptorSet[0]; currentFileDescriptor++) {
  5439.                         if (fileDescriptorSet[currentFileDescriptor + 1] == socket.m_Handle.DangerousGetHandle()) {
  5440.                             break;
  5441.                         }
  5442.                     }
  5443.                     if (currentFileDescriptor == (int)fileDescriptorSet[0]) {
  5444.                         // descriptor not found: remove the current socket and start again
  5445.                         socketList.RemoveAt(currentSocket--);
  5446.                     }
  5447.                 }
  5448.             }
  5449.         }
  5450.        
  5451.        
  5452.         private static void MicrosecondsToTimeValue(long microSeconds, ref TimeValue socketTime)
  5453.         {
  5454.             socketTime.Seconds = (int)(microSeconds / microcnv);
  5455.             socketTime.Microseconds = (int)(microSeconds % microcnv);
  5456.         }
  5457.         //Implements ConnectEx - this provides completion port IO and support for
  5458.         //disconnect and reconnects
  5459.        
  5460.         // Since this is private, the unsafe mode is specified with a flag instead of an overload.
  5461.         private IAsyncResult BeginConnectEx(EndPoint remoteEP, bool flowContext, AsyncCallback callback, object state)
  5462.         {
  5463.             if (Logging.On)
  5464.                 Logging.Enter(Logging.Sockets, this, "BeginConnectEx", "");
  5465.            
  5466.             // This will check the permissions for connect.
  5467.             EndPoint endPointSnapshot = remoteEP;
  5468.             SocketAddress socketAddress = flowContext ? CheckCacheRemote(ref endPointSnapshot, true) : SnapshotAndSerialize(ref endPointSnapshot);
  5469.            
  5470.             //socket must be bound first
  5471.             //the calling method BeginConnect will ensure that this method is only
  5472.             //called if m_RightEndPoint is not null, of that the endpoint is an ipendpoint
  5473.             if (m_RightEndPoint == null) {
  5474.                 GlobalLog.Assert(endPointSnapshot.GetType() == typeof(IPEndPoint), "Socket#{0}::BeginConnectEx()|Socket not bound and endpoint not IPEndPoint.", ValidationHelper.HashString(this));
  5475.                 if (endPointSnapshot.AddressFamily == AddressFamily.InterNetwork)
  5476.                     InternalBind(new IPEndPoint(IPAddress.Any, 0));
  5477.                 else
  5478.                     InternalBind(new IPEndPoint(IPAddress.IPv6Any, 0));
  5479.             }
  5480.            
  5481.             //
  5482.             // Allocate the async result and the event we'll pass to the
  5483.             // thread pool.
  5484.             //
  5485.             ConnectOverlappedAsyncResult asyncResult = new ConnectOverlappedAsyncResult(this, state, callback);
  5486.            
  5487.             // If context flowing is enabled, set it up here. No need to lock since the context isn't used until the callback.
  5488.             if (flowContext) {
  5489.                 asyncResult.StartPostingAsyncOp(false);
  5490.             }
  5491.            
  5492.             // This will pin socketAddress buffer
  5493.             asyncResult.SetUnmanagedStructures(socketAddress.m_Buffer);
  5494.            
  5495.             EndPoint oldEndPoint = m_RightEndPoint;
  5496.             if (m_RightEndPoint == null) {
  5497.                 m_RightEndPoint = endPointSnapshot;
  5498.             }
  5499.            
  5500.             SocketError errorCode = SocketError.Success;
  5501.            
  5502.             try {
  5503.                 if (!ConnectEx(m_Handle, Marshal.UnsafeAddrOfPinnedArrayElement(socketAddress.m_Buffer, 0), socketAddress.m_Size, IntPtr.Zero, 0, 0, asyncResult.OverlappedHandle)) {
  5504.                     errorCode = (SocketError)Marshal.GetLastWin32Error();
  5505.                 }
  5506.             }
  5507.             catch (ObjectDisposedException) {
  5508.                 m_RightEndPoint = oldEndPoint;
  5509.                 throw;
  5510.             }
  5511.            
  5512.             if (errorCode == SocketError.Success) {
  5513.                 SetToConnected();
  5514.             }
  5515.            
  5516.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginConnectEx() UnsafeNclNativeMethods.OSSOCK.connect returns:" + errorCode.ToString());
  5517.            
  5518.             errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode);
  5519.            
  5520.             //
  5521.             // if the asynchronous native call fails synchronously
  5522.             // we'll throw a SocketException
  5523.             //
  5524.             if (errorCode != SocketError.Success) {
  5525.                 //
  5526.                 // update our internal state after this socket error and throw
  5527.                 //
  5528.                 m_RightEndPoint = oldEndPoint;
  5529.                 SocketException socketException = new SocketException(errorCode);
  5530.                 UpdateStatusAfterSocketError(socketException);
  5531.                 if (Logging.On)
  5532.                     Logging.Exception(Logging.Sockets, this, "BeginConnectEx", socketException);
  5533.                 throw socketException;
  5534.             }
  5535.            
  5536.             // We didn't throw, so indicate that we're returning this result to the user. This may call the callback.
  5537.             // This is a nop if the context isn't being flowed.
  5538.             asyncResult.FinishPostingAsyncOp(ref Caches.ConnectClosureCache);
  5539.            
  5540.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginConnectEx() to:" + endPointSnapshot.ToString() + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
  5541.             if (Logging.On)
  5542.                 Logging.Exit(Logging.Sockets, this, "BeginConnectEx", asyncResult);
  5543.             return asyncResult;
  5544.         }
  5545.        
  5546.        
  5547.         internal void MultipleSend(BufferOffsetSize[] buffers, SocketFlags socketFlags)
  5548.         {
  5549.             if (Logging.On)
  5550.                 Logging.Enter(Logging.Sockets, this, "MultipleSend", "");
  5551.             if (CleanedUp) {
  5552.                 throw new ObjectDisposedException(this.GetType().FullName);
  5553.             }
  5554.             //
  5555.             // parameter validation
  5556.             //
  5557.             GlobalLog.Assert(buffers != null, "Socket#{0}::MultipleSend()|buffers == null", ValidationHelper.HashString(this));
  5558.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::MultipleSend() buffers.Length:" + buffers.Length.ToString());
  5559.            
  5560.             WSABuffer[] WSABuffers = new WSABuffer[buffers.Length];
  5561.             GCHandle[] objectsToPin = null;
  5562.             int bytesTransferred;
  5563.             SocketError errorCode;
  5564.            
  5565.             try {
  5566.                 objectsToPin = new GCHandle[buffers.Length];
  5567.                 for (int i = 0; i < buffers.Length; ++i) {
  5568.                     objectsToPin[i] = GCHandle.Alloc(buffers[i].Buffer, GCHandleType.Pinned);
  5569.                     WSABuffers[i].Length = buffers[i].Size;
  5570.                     WSABuffers[i].Pointer = Marshal.UnsafeAddrOfPinnedArrayElement(buffers[i].Buffer, buffers[i].Offset);
  5571.                 }
  5572.                
  5573.                 // This can throw ObjectDisposedException.
  5574.                 errorCode = UnsafeNclNativeMethods.OSSOCK.WSASend_Blocking(m_Handle.DangerousGetHandle(), WSABuffers, WSABuffers.Length, out bytesTransferred, socketFlags, IntPtr.Zero, IntPtr.Zero);
  5575.                
  5576.                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::MultipleSend() UnsafeNclNativeMethods.OSSOCK.WSASend returns:" + errorCode.ToString() + " size:" + buffers.Length.ToString());
  5577.                
  5578.             }
  5579.             finally {
  5580.                 if (objectsToPin != null)
  5581.                     for (int i = 0; i < objectsToPin.Length; ++i)
  5582.                         if (objectsToPin[i].IsAllocated)
  5583.                             objectsToPin[i].Free();
  5584.             }
  5585.            
  5586.             if (errorCode != SocketError.Success) {
  5587.                 SocketException socketException = new SocketException();
  5588.                 UpdateStatusAfterSocketError(socketException);
  5589.                 if (Logging.On)
  5590.                     Logging.Exception(Logging.Sockets, this, "MultipleSend", socketException);
  5591.                 throw socketException;
  5592.             }
  5593.            
  5594.             if (Logging.On)
  5595.                 Logging.Exit(Logging.Sockets, this, "MultipleSend", "");
  5596.         }
  5597.        
  5598.        
  5599.         private static void DnsCallback(IAsyncResult result)
  5600.         {
  5601.             if (result.CompletedSynchronously)
  5602.                 return;
  5603.            
  5604.             MultipleAddressConnectAsyncResult context = (MultipleAddressConnectAsyncResult)result.AsyncState;
  5605.             try {
  5606.                 DoDnsCallback(result, context);
  5607.             }
  5608.             catch (Exception exception) {
  5609.                 if (exception is ThreadAbortException || exception is StackOverflowException || exception is OutOfMemoryException)
  5610.                     throw;
  5611.                
  5612.                 context.InvokeCallback(exception);
  5613.             }
  5614.         }
  5615.        
  5616.         private static void DoDnsCallback(IAsyncResult result, MultipleAddressConnectAsyncResult context)
  5617.         {
  5618.             IPAddress[] addresses = Dns.EndGetHostAddresses(result);
  5619.             context.addresses = addresses;
  5620.             DoMultipleAddressConnectCallback(PostOneBeginConnect(context), context);
  5621.         }
  5622.        
  5623.         private class MultipleAddressConnectAsyncResult : ContextAwareResult
  5624.         {
  5625.             internal MultipleAddressConnectAsyncResult(IPAddress[] addresses, int port, Socket socket, object myState, AsyncCallback myCallBack) : base(socket, myState, myCallBack)
  5626.             {
  5627.                 this.addresses = addresses;
  5628.                 this.port = port;
  5629.                 this.socket = socket;
  5630.             }
  5631.            
  5632.             internal Socket socket;
  5633.             // Keep this member just to avoid all the casting.
  5634.             internal IPAddress[] addresses;
  5635.             internal int index;
  5636.             internal int port;
  5637.             internal Exception lastException;
  5638.         }
  5639.        
  5640.         private static object PostOneBeginConnect(MultipleAddressConnectAsyncResult context)
  5641.         {
  5642.             if (context.addresses[context.index].AddressFamily != context.socket.AddressFamily) {
  5643.                 return context.lastException != null ? context.lastException : new ArgumentException(SR.GetString(SR.net_invalidAddressList), "context");
  5644.             }
  5645.            
  5646.             try {
  5647.                 IAsyncResult connectResult = context.socket.UnsafeBeginConnect(new IPEndPoint(context.addresses[context.index], context.port), new AsyncCallback(MultipleAddressConnectCallback), context);
  5648.                 if (connectResult.CompletedSynchronously) {
  5649.                     return connectResult;
  5650.                 }
  5651.             }
  5652.             catch (Exception exception) {
  5653.                 if (exception is OutOfMemoryException || exception is StackOverflowException || exception is ThreadAbortException)
  5654.                     throw;
  5655.                
  5656.                 return exception;
  5657.             }
  5658.            
  5659.             return null;
  5660.         }
  5661.        
  5662.         private static void MultipleAddressConnectCallback(IAsyncResult result)
  5663.         {
  5664.             if (result.CompletedSynchronously)
  5665.                 return;
  5666.            
  5667.             MultipleAddressConnectAsyncResult context = (MultipleAddressConnectAsyncResult)result.AsyncState;
  5668.             try {
  5669.                 DoMultipleAddressConnectCallback(result, context);
  5670.             }
  5671.             catch (Exception exception) {
  5672.                 if (exception is ThreadAbortException || exception is StackOverflowException || exception is OutOfMemoryException)
  5673.                     throw;
  5674.                
  5675.                 context.InvokeCallback(exception);
  5676.             }
  5677.         }
  5678.        
  5679.         // This is like a regular async callback worker, except the result can be an exception. This is a useful pattern when
  5680.         // processing should continue whether or not an async step failed.
  5681.         private static void DoMultipleAddressConnectCallback(object result, MultipleAddressConnectAsyncResult context)
  5682.         {
  5683.             while (result != null) {
  5684.                 Exception ex = result as Exception;
  5685.                 if (ex == null) {
  5686.                     try {
  5687.                         context.socket.EndConnect((IAsyncResult)result);
  5688.                     }
  5689.                     catch (Exception exception) {
  5690.                         if (exception is ThreadAbortException || exception is StackOverflowException || exception is OutOfMemoryException)
  5691.                             throw;
  5692.                        
  5693.                         ex = exception;
  5694.                     }
  5695.                     catch {
  5696.                         ex = new Exception(SR.GetString(SR.net_nonClsCompliantException));
  5697.                     }
  5698.                 }
  5699.                
  5700.                 if (ex == null) {
  5701.                     context.InvokeCallback();
  5702.                     break;
  5703.                 }
  5704.                 else {
  5705.                     if (++context.index >= context.addresses.Length)
  5706.                         throw ex;
  5707.                    
  5708.                     context.lastException = ex;
  5709.                     result = PostOneBeginConnect(context);
  5710.                 }
  5711.             }
  5712.         }
  5713.        
  5714.         private class DownLevelSendFileAsyncResult : ContextAwareResult
  5715.         {
  5716.             internal DownLevelSendFileAsyncResult(FileStream stream, Socket socket, object myState, AsyncCallback myCallBack) : base(socket, myState, myCallBack)
  5717.             {
  5718.                 this.socket = socket;
  5719.                 // This field just avoids the cast.
  5720.                 this.fileStream = stream;
  5721.                 buffer = new byte[64000];
  5722.             }
  5723.            
  5724.             internal Socket socket;
  5725.             internal FileStream fileStream;
  5726.             internal byte[] buffer;
  5727.             internal bool writing;
  5728.         }
  5729.        
  5730.         private static void DownLevelSendFileCallback(IAsyncResult result)
  5731.         {
  5732.             if (result.CompletedSynchronously)
  5733.                 return;
  5734.            
  5735.             DownLevelSendFileAsyncResult context = (DownLevelSendFileAsyncResult)result.AsyncState;
  5736.             DoDownLevelSendFileCallback(result, context);
  5737.         }
  5738.        
  5739.         private static void DoDownLevelSendFileCallback(IAsyncResult result, DownLevelSendFileAsyncResult context)
  5740.         {
  5741.             try {
  5742.                 while (true) {
  5743.                     if (!context.writing) {
  5744.                         int read = context.fileStream.EndRead(result);
  5745.                        
  5746.                         if (read > 0) {
  5747.                             context.writing = true;
  5748.                             result = context.socket.BeginSend(context.buffer, 0, read, SocketFlags.None, new AsyncCallback(DownLevelSendFileCallback), context);
  5749.                             if (!result.CompletedSynchronously)
  5750.                                 break;
  5751.                         }
  5752.                         else {
  5753.                             DownLevelSendFileCleanup(context.fileStream);
  5754.                             context.InvokeCallback();
  5755.                             break;
  5756.                         }
  5757.                     }
  5758.                     else {
  5759.                         int written = context.socket.EndSend(result);
  5760.                         context.writing = false;
  5761.                         result = context.fileStream.BeginRead(context.buffer, 0, context.buffer.Length, new AsyncCallback(DownLevelSendFileCallback), context);
  5762.                         if (!result.CompletedSynchronously)
  5763.                             break;
  5764.                     }
  5765.                 }
  5766.             }
  5767.             catch (Exception exception) {
  5768.                 if (NclUtilities.IsFatal(exception))
  5769.                     throw;
  5770.                
  5771.                 DownLevelSendFileCleanup(context.fileStream);
  5772.                 context.InvokeCallback(exception);
  5773.             }
  5774.            
  5775.         }
  5776.        
  5777.         //Utility function to cleanup context structures
  5778.         private static void DownLevelSendFileCleanup(FileStream fileStream)
  5779.         {
  5780.             // Release filestream, we're done with it
  5781.            
  5782.             if (fileStream != null) {
  5783.                 fileStream.Close();
  5784.                 fileStream = null;
  5785.             }
  5786.         }
  5787.        
  5788.        
  5789.         // Since this is private, "Unsafe" is indicated with a flag.
  5790.         [ResourceExposure(ResourceScope.Machine)]
  5791.         [ResourceConsumption(ResourceScope.Machine)]
  5792.         private IAsyncResult BeginDownLevelSendFile(string fileName, bool flowContext, AsyncCallback callback, object state)
  5793.         {
  5794.             if (Logging.On)
  5795.                 Logging.Enter(Logging.Sockets, this, "BeginSendFile", "");
  5796.            
  5797.             if (CleanedUp) {
  5798.                 throw new ObjectDisposedException(this.GetType().FullName);
  5799.             }
  5800.            
  5801.             if (!Connected) {
  5802.                 throw new NotSupportedException(SR.GetString(SR.net_notconnected));
  5803.             }
  5804.            
  5805.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginDownLevelSendFile() SRC:" + ValidationHelper.ToString(LocalEndPoint) + " DST:" + ValidationHelper.ToString(RemoteEndPoint) + " fileName:" + fileName);
  5806.            
  5807.             FileStream fileStream = null;
  5808.             if (fileName != null && fileName.Length > 0) {
  5809.                 fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
  5810.             }
  5811.            
  5812.             DownLevelSendFileAsyncResult asyncResult = null;
  5813.             IAsyncResult fileResult = null;
  5814.             try {
  5815.                 asyncResult = new DownLevelSendFileAsyncResult(fileStream, this, state, callback);
  5816.                
  5817.                 // If we're flowing context, indicate that here.
  5818.                 if (flowContext) {
  5819.                     asyncResult.StartPostingAsyncOp(false);
  5820.                 }
  5821.                
  5822.                 fileResult = fileStream.BeginRead(asyncResult.buffer, 0, asyncResult.buffer.Length, new AsyncCallback(DownLevelSendFileCallback), asyncResult);
  5823.             }
  5824.             catch (Exception e) {
  5825.                 if (!NclUtilities.IsFatal(e)) {
  5826.                     DownLevelSendFileCleanup(fileStream);
  5827.                 }
  5828.                 throw;
  5829.             }
  5830.            
  5831.             if (fileResult.CompletedSynchronously) {
  5832.                 DoDownLevelSendFileCallback(fileResult, asyncResult);
  5833.             }
  5834.            
  5835.             // Finished without throwing - seal up the result and give it out. NOP if we're not flowing.
  5836.             asyncResult.FinishPostingAsyncOp(ref Caches.SendClosureCache);
  5837.             if (Logging.On)
  5838.                 Logging.Exit(Logging.Sockets, this, "BeginSendFile", 0);
  5839.            
  5840.             return asyncResult;
  5841.         }
  5842.        
  5843.        
  5844.         internal IAsyncResult BeginMultipleSend(BufferOffsetSize[] buffers, SocketFlags socketFlags, AsyncCallback callback, object state)
  5845.         {
  5846.             // Set up the async result and start the flow.
  5847.             OverlappedAsyncResult asyncResult = new OverlappedAsyncResult(this, state, callback);
  5848.             asyncResult.StartPostingAsyncOp(false);
  5849.            
  5850.             // Start the send.
  5851.             DoBeginMultipleSend(buffers, socketFlags, asyncResult);
  5852.            
  5853.             // Finish it up (capture, complete).
  5854.             asyncResult.FinishPostingAsyncOp(ref Caches.SendClosureCache);
  5855.             return asyncResult;
  5856.         }
  5857.        
  5858.         internal IAsyncResult UnsafeBeginMultipleSend(BufferOffsetSize[] buffers, SocketFlags socketFlags, AsyncCallback callback, object state)
  5859.         {
  5860.             // Unsafe - don't flow.
  5861.             OverlappedAsyncResult asyncResult = new OverlappedAsyncResult(this, state, callback);
  5862.             DoBeginMultipleSend(buffers, socketFlags, asyncResult);
  5863.             return asyncResult;
  5864.         }
  5865.        
  5866.         private void DoBeginMultipleSend(BufferOffsetSize[] buffers, SocketFlags socketFlags, OverlappedAsyncResult asyncResult)
  5867.         {
  5868.             if (Logging.On)
  5869.                 Logging.Enter(Logging.Sockets, this, "BeginMultipleSend", "");
  5870.             if (CleanedUp) {
  5871.                 throw new ObjectDisposedException(this.GetType().FullName);
  5872.             }
  5873.             //
  5874.             // parameter validation
  5875.             //
  5876.             GlobalLog.Assert(buffers != null, "Socket#{0}::DoBeginMultipleSend()|buffers == null", ValidationHelper.HashString(this));
  5877.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::DoBeginMultipleSend() buffers.Length:" + buffers.Length.ToString());
  5878.            
  5879.             // Guarantee to call CheckAsyncCallOverlappedResult if we call SetUnamangedStructures with a cache in order to
  5880.             // avoid a Socket leak in case of error.
  5881.             SocketError errorCode = SocketError.SocketError;
  5882.             try {
  5883.                 // Set up asyncResult for overlapped WSASend.
  5884.                 // This call will use completion ports on WinNT and Overlapped IO on Win9x.
  5885.                 asyncResult.SetUnmanagedStructures(buffers, ref Caches.SendOverlappedCache);
  5886.                
  5887.                 // This can throw ObjectDisposedException.
  5888.                 int bytesTransferred;
  5889.                 errorCode = UnsafeNclNativeMethods.OSSOCK.WSASend(m_Handle, asyncResult.m_WSABuffers, asyncResult.m_WSABuffers.Length, out bytesTransferred, socketFlags, asyncResult.OverlappedHandle, IntPtr.Zero);
  5890.                
  5891.                 if (errorCode != SocketError.Success) {
  5892.                     errorCode = (SocketError)Marshal.GetLastWin32Error();
  5893.                 }
  5894.                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BeginMultipleSend() UnsafeNclNativeMethods.OSSOCK.WSASend returns:" + errorCode.ToString() + " size:" + buffers.Length.ToString() + " returning AsyncResult:" + ValidationHelper.HashString(asyncResult));
  5895.             }
  5896.             finally {
  5897.                 errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode);
  5898.             }
  5899.            
  5900.             //
  5901.             // if the asynchronous native call fails synchronously
  5902.             // we'll throw a SocketException
  5903.             //
  5904.             if (errorCode != SocketError.Success) {
  5905.                 //
  5906.                 // update our internal state after this socket error and throw
  5907.                 //
  5908.                 asyncResult.ExtractCache(ref Caches.SendOverlappedCache);
  5909.                 SocketException socketException = new SocketException(errorCode);
  5910.                 UpdateStatusAfterSocketError(socketException);
  5911.                 if (Logging.On)
  5912.                     Logging.Exception(Logging.Sockets, this, "BeginMultipleSend", socketException);
  5913.                 throw socketException;
  5914.             }
  5915.             if (Logging.On)
  5916.                 Logging.Exit(Logging.Sockets, this, "BeginMultipleSend", asyncResult);
  5917.         }
  5918.        
  5919.        
  5920.         private void EndDownLevelSendFile(IAsyncResult asyncResult)
  5921.         {
  5922.             if (Logging.On)
  5923.                 Logging.Enter(Logging.Sockets, this, "EndSendFile", asyncResult);
  5924.            
  5925.            
  5926.             if (CleanedUp) {
  5927.                 throw new ObjectDisposedException(this.GetType().FullName);
  5928.             }
  5929.             //
  5930.             // parameter validation
  5931.             //
  5932.             if (asyncResult == null) {
  5933.                 throw new ArgumentNullException("asyncResult");
  5934.             }
  5935.             LazyAsyncResult castedAsyncResult = asyncResult as DownLevelSendFileAsyncResult;
  5936.             if (castedAsyncResult == null || castedAsyncResult.AsyncObject != this) {
  5937.                 throw new ArgumentException(SR.GetString(SR.net_io_invalidasyncresult), "asyncResult");
  5938.             }
  5939.             if (castedAsyncResult.EndCalled) {
  5940.                 throw new InvalidOperationException(SR.GetString(SR.net_io_invalidendcall, "EndSendFile"));
  5941.             }
  5942.            
  5943.             castedAsyncResult.InternalWaitForCompletion();
  5944.             castedAsyncResult.EndCalled = true;
  5945.            
  5946.            
  5947.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::EndSendFile()");
  5948.            
  5949.             //check for failure
  5950.             Exception exception = castedAsyncResult.Result as Exception;
  5951.             if (exception != null) {
  5952.                 throw exception;
  5953.             }
  5954.            
  5955.             if (Logging.On)
  5956.                 Logging.Exit(Logging.Sockets, this, "EndSendFile", "");
  5957.         }
  5958.        
  5959.         internal int EndMultipleSend(IAsyncResult asyncResult)
  5960.         {
  5961.             if (Logging.On)
  5962.                 Logging.Enter(Logging.Sockets, this, "EndMultipleSend", asyncResult);
  5963.             //
  5964.             // parameter validation
  5965.             //
  5966.             GlobalLog.Assert(asyncResult != null, "Socket#{0}::EndMultipleSend()|asyncResult == null", ValidationHelper.HashString(this));
  5967.            
  5968.             OverlappedAsyncResult castedAsyncResult = asyncResult as OverlappedAsyncResult;
  5969.            
  5970.             GlobalLog.Assert(castedAsyncResult != null, "Socket#{0}::EndMultipleSend()|castedAsyncResult == null", ValidationHelper.HashString(this));
  5971.             GlobalLog.Assert(castedAsyncResult.AsyncObject == this, "Socket#{0}::EndMultipleSend()|castedAsyncResult.AsyncObject != this", ValidationHelper.HashString(this));
  5972.             GlobalLog.Assert(!castedAsyncResult.EndCalled, "Socket#{0}::EndMultipleSend()|castedAsyncResult.EndCalled", ValidationHelper.HashString(this));
  5973.            
  5974.             int bytesTransferred = (int)castedAsyncResult.InternalWaitForCompletion();
  5975.             castedAsyncResult.EndCalled = true;
  5976.             castedAsyncResult.ExtractCache(ref Caches.SendOverlappedCache);
  5977.            
  5978.            
  5979.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::EndMultipleSend() bytesTransferred:" + bytesTransferred.ToString());
  5980.            
  5981.             //
  5982.             // if the asynchronous native call failed asynchronously
  5983.             // we'll throw a SocketException
  5984.             //
  5985.             if ((SocketError)castedAsyncResult.ErrorCode != SocketError.Success) {
  5986.                 //
  5987.                 // update our internal state after this socket error and throw
  5988.                 //
  5989.                 SocketException socketException = new SocketException(castedAsyncResult.ErrorCode);
  5990.                 if (Logging.On)
  5991.                     Logging.Exception(Logging.Sockets, this, "EndMultipleSend", socketException);
  5992.                 throw socketException;
  5993.             }
  5994.             if (Logging.On)
  5995.                 Logging.Exit(Logging.Sockets, this, "EndMultipleSend", bytesTransferred);
  5996.             return bytesTransferred;
  5997.         }
  5998.        
  5999.         //
  6000.         // CreateAcceptSocket - pulls unmanaged results and assembles them
  6001.         // into a new Socket object
  6002.         //
  6003.         private Socket CreateAcceptSocket(SafeCloseSocket fd, EndPoint remoteEP, bool needCancelSelect)
  6004.         {
  6005.             //
  6006.             // Internal state of the socket is inherited from listener
  6007.             //
  6008.             Socket socket = new Socket(fd);
  6009.             return UpdateAcceptSocket(socket, remoteEP, needCancelSelect);
  6010.         }
  6011.        
  6012.         internal Socket UpdateAcceptSocket(Socket socket, EndPoint remoteEP, bool needCancelSelect)
  6013.         {
  6014.             //
  6015.             // Internal state of the socket is inherited from listener
  6016.             //
  6017.             socket.addressFamily = addressFamily;
  6018.             socket.socketType = socketType;
  6019.             socket.protocolType = protocolType;
  6020.             socket.m_RightEndPoint = m_RightEndPoint;
  6021.             socket.m_RemoteEndPoint = remoteEP;
  6022.             //
  6023.             // the socket is connected
  6024.             //
  6025.             socket.SetToConnected();
  6026.             //
  6027.             // if the socket is returned by an Endb), the socket might have
  6028.             // inherited the WSAEventSelect() call from the accepting socket.
  6029.             // we need to cancel this otherwise the socket will be in non-blocking
  6030.             // mode and we cannot force blocking mode using the ioctlsocket() in
  6031.             // Socket.set_Blocking(), since it fails returing 10022 as documented in MSDN.
  6032.             // (note that the m_AsyncEvent event will not be created in this case.
  6033.             //
  6034.            
  6035.            
  6036.             if (needCancelSelect)
  6037.                 socket.UnsetAsyncEventSelect();
  6038.             //
  6039.             // the new socket will inherit the win32 blocking mode from the accepting socket.
  6040.             // if the user desired blocking mode is different from the win32 blocking mode
  6041.             // we need to force the desired blocking behaviour.
  6042.             //
  6043.             socket.willBlock = willBlock;
  6044.             if (willBlock != willBlockInternal) {
  6045.                 socket.InternalSetBlocking(willBlock);
  6046.             }
  6047.            
  6048.             return socket;
  6049.         }
  6050.        
  6051.        
  6052.        
  6053.         //
  6054.         // SetToConnected - updates the status of the socket to connected
  6055.         //
  6056.         internal void SetToConnected()
  6057.         {
  6058.             if (m_IsConnected) {
  6059.                 //
  6060.                 // socket was already connected
  6061.                 //
  6062.                 return;
  6063.             }
  6064.             //
  6065.             // update the status: this socket was indeed connected at
  6066.             // some point in time update the perf counter as well.
  6067.             //
  6068.             m_IsConnected = true;
  6069.             m_IsDisconnected = false;
  6070.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SetToConnected() now connected SRC:" + ValidationHelper.ToString(LocalEndPoint) + " DST:" + ValidationHelper.ToString(RemoteEndPoint));
  6071.         }
  6072.        
  6073.         //
  6074.         // SetToDisconnected - updates the status of the socket to disconnected
  6075.         //
  6076.         internal void SetToDisconnected()
  6077.         {
  6078.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SetToDisconnected()");
  6079.             if (!m_IsConnected) {
  6080.                 //
  6081.                 // socket was already disconnected
  6082.                 //
  6083.                 return;
  6084.             }
  6085.             //
  6086.             // update the status: this socket was indeed disconnected at
  6087.             // some point in time, clear any async select bits.
  6088.             //
  6089.             m_IsConnected = false;
  6090.             m_IsDisconnected = true;
  6091.            
  6092.             if (!CleanedUp) {
  6093.                 //
  6094.                 // if socket is still alive cancel WSAEventSelect()
  6095.                 //
  6096.                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SetToDisconnected()");
  6097.                
  6098.                 UnsetAsyncEventSelect();
  6099.             }
  6100.         }
  6101.        
  6102.         //
  6103.         // UpdateStatusAfterSocketError(socketException) - updates the status of a connected socket
  6104.         // on which a failure occured. it'll go to winsock and check if the connection
  6105.         // is still open and if it needs to update our internal state.
  6106.         //
  6107.         internal void UpdateStatusAfterSocketError(SocketException socketException)
  6108.         {
  6109.             UpdateStatusAfterSocketError((SocketError)socketException.NativeErrorCode);
  6110.         }
  6111.        
  6112.         internal void UpdateStatusAfterSocketError(SocketError errorCode)
  6113.         {
  6114.             //
  6115.             // if we already know the socket is disconnected
  6116.             // we don't need to do anything else.
  6117.             //
  6118.             GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::UpdateStatusAfterSocketError(socketException)");
  6119.            
  6120.             if (m_IsConnected && (m_Handle.IsInvalid || (errorCode != SocketError.WouldBlock && errorCode != SocketError.IOPending && errorCode != SocketError.NoBufferSpaceAvailable))) {
  6121.                 //
  6122.                 //
  6123.                 // the socket is no longer a valid socket
  6124.                 //
  6125.                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::UpdateStatusAfterSocketError(socketException) Invalidating socket.");
  6126.                 SetToDisconnected();
  6127.             }
  6128.         }
  6129.        
  6130.        
  6131.         //
  6132.         // Does internal initalization before async winsock
  6133.         // call to BeginConnect() or BeginAccept().
  6134.         //
  6135.         private void UnsetAsyncEventSelect()
  6136.         {
  6137.             GlobalLog.Enter("Socket#" + ValidationHelper.HashString(this) + "::UnsetAsyncEventSelect", "m_BlockEventBits:" + m_BlockEventBits.ToString() + " willBlockInternal:" + willBlockInternal.ToString());
  6138.            
  6139.             RegisteredWaitHandle registeredWait = m_RegisteredWait;
  6140.             if (registeredWait != null) {
  6141.                 m_RegisteredWait = null;
  6142.                 registeredWait.Unregister(null);
  6143.             }
  6144.            
  6145.             SocketError errorCode = SocketError.NotSocket;
  6146.             try {
  6147.                 errorCode = UnsafeNclNativeMethods.OSSOCK.WSAEventSelect(m_Handle, IntPtr.Zero, AsyncEventBits.FdNone);
  6148.             }
  6149.             catch (Exception e) {
  6150.                 if (NclUtilities.IsFatal(e))
  6151.                     throw;
  6152.                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::UnsetAsyncEventSelect() !!! (ignoring) Exception: " + e.ToString());
  6153.                 GlobalLog.Assert(CleanedUp, "Socket#{0}::UnsetAsyncEventSelect|Got exception and CleanedUp not set.", ValidationHelper.HashString(this));
  6154.             }
  6155.             catch {
  6156.                 GlobalLog.Assert("Socket#" + ValidationHelper.HashString(this) + "::UnsetAsyncEventSelect", "Non-Exception object thrown by WSAEventSelect.");
  6157.             }
  6158.            
  6159.             //
  6160.             // May be re-used in future, reset if the event got signalled after registeredWait.Unregister call
  6161.             //
  6162.             if (m_AsyncEvent != null) {
  6163.                 try {
  6164.                     m_AsyncEvent.Reset();
  6165.                 }
  6166.                 catch (ObjectDisposedException) {
  6167.                 }
  6168.             }
  6169.            
  6170.             if (errorCode == SocketError.SocketError) {
  6171.                 //
  6172.                 // update our internal state after this socket error
  6173.                 // we won't throw since this is an internal method
  6174.                 //
  6175.                 UpdateStatusAfterSocketError(errorCode);
  6176.             }
  6177.            
  6178.             GlobalLog.Leave("Socket#" + ValidationHelper.HashString(this) + "::UnsetAsyncEventSelect", "m_BlockEventBits:" + m_BlockEventBits.ToString() + " willBlockInternal:" + willBlockInternal.ToString());
  6179.         }
  6180.        
  6181.         private bool SetAsyncEventSelect(AsyncEventBits blockEventBits)
  6182.         {
  6183.             GlobalLog.Enter("Socket#" + ValidationHelper.HashString(this) + "::SetAsyncEventSelect", "blockEventBits:" + blockEventBits.ToString() + " m_BlockEventBits:" + m_BlockEventBits.ToString() + " willBlockInternal:" + willBlockInternal.ToString());
  6184.             GlobalLog.Assert(blockEventBits != AsyncEventBits.FdNone, "Socket#{0}::SetAsyncEventSelect|Use UnsetAsyncEventSelect for FdNone.", ValidationHelper.HashString(this));
  6185.             GlobalLog.Assert(m_BlockEventBits == AsyncEventBits.FdNone || m_BlockEventBits == blockEventBits, "Socket#{0}::SetAsyncEventSelect|Can't change from one active wait to another.", ValidationHelper.HashString(this));
  6186.             GlobalLog.Assert(m_RegisteredWait == null, "Socket#{0}::SetAsyncEventSelect|Already actively waiting on an op.", ValidationHelper.HashString(this));
  6187.            
  6188.             // This check is bogus, too late diggin into a historical reason for it.
  6189.             // Make sure the upper level will fail with ObjectDisposedException
  6190.             if (m_RegisteredWait != null)
  6191.                 return false;
  6192.            
  6193.             //
  6194.             // This will put us into non-blocking mode. Create the event if it isn't, and register a wait.
  6195.             //
  6196.             if (m_AsyncEvent == null) {
  6197.                 Interlocked.CompareExchange<ManualResetEvent>(ref m_AsyncEvent, new ManualResetEvent(false), null);
  6198.                 if (s_RegisteredWaitCallback == null)
  6199.                     s_RegisteredWaitCallback = new WaitOrTimerCallback(RegisteredWaitCallback);
  6200.             }
  6201.            
  6202.             //
  6203.             // Try to win over Dispose is there is a race
  6204.             //
  6205.             if (Interlocked.CompareExchange(ref m_IntCleanedUp, 2, 0) != 0) {
  6206.                 GlobalLog.Leave("Socket#" + ValidationHelper.HashString(this) + "::SetAsyncEventSelect() Already Cleaned up, returning ... ", string.Empty);
  6207.                 return false;
  6208.             }
  6209.            
  6210.             m_BlockEventBits = blockEventBits;
  6211.             m_RegisteredWait = ThreadPool.UnsafeRegisterWaitForSingleObject(m_AsyncEvent, s_RegisteredWaitCallback, this, Timeout.Infinite, true);
  6212.            
  6213.             //
  6214.             // Release dispose if any is waiting
  6215.             //
  6216.             Interlocked.Exchange(ref m_IntCleanedUp, 0);
  6217.            
  6218.             SocketError errorCode = SocketError.NotSocket;
  6219.             //
  6220.             // issue the native call
  6221.             //
  6222.             try {
  6223.                 errorCode = UnsafeNclNativeMethods.OSSOCK.WSAEventSelect(m_Handle, m_AsyncEvent.SafeWaitHandle, blockEventBits);
  6224.             }
  6225.             catch (Exception e) {
  6226.                 if (NclUtilities.IsFatal(e))
  6227.                     throw;
  6228.                 GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::SetAsyncEventSelect() !!! (converting to ObjectDisposed) Exception :" + e.ToString());
  6229.                 GlobalLog.Assert(CleanedUp, "Socket#{0}::SetAsyncEventSelect|WSAEventSelect got exception and CleanedUp not set.", ValidationHelper.HashString(this));
  6230.             }
  6231.             catch {
  6232.                 GlobalLog.Assert("Socket#" + ValidationHelper.HashString(this) + "::SetAsyncEventSelect", "WSAEventSelect caught non-Exception object.");
  6233.             }
  6234.            
  6235.             if (errorCode == SocketError.SocketError) {
  6236.                 //
  6237.                 // update our internal state after this socket error
  6238.                 // we won't throw since this is an internal method
  6239.                 //
  6240.                 UpdateStatusAfterSocketError(errorCode);
  6241.             }
  6242.            
  6243.             //
  6244.             // the call to WSAEventSelect might have caused us to change
  6245.             // blocking mode, hence we need update internal status
  6246.             //
  6247.             willBlockInternal = false;
  6248.            
  6249.             GlobalLog.Leave("Socket#" + ValidationHelper.HashString(this) + "::SetAsyncEventSelect", "m_BlockEventBits:" + m_BlockEventBits.ToString() + " willBlockInternal:" + willBlockInternal.ToString());
  6250.             return errorCode == SocketError.Success;
  6251.         }
  6252.        
  6253.         private static void RegisteredWaitCallback(object state, bool timedOut)
  6254.         {
  6255.             GlobalLog.Enter("Socket#" + ValidationHelper.HashString(state) + "::RegisteredWaitCallback", "m_BlockEventBits:" + ((Socket)state).m_BlockEventBits.ToString());
  6256.             #if DEBUG
  6257.             // GlobalLog.SetThreadSource(ThreadKinds.Worker); Because of change 1077887, need logic to determine thread type here.
  6258.             using (GlobalLog.SetThreadKind(ThreadKinds.System)) {
  6259.                 #endif
  6260.                 Socket me = (Socket)state;
  6261.                
  6262.                 // Interlocked to avoid a race condition with DoBeginConnect
  6263.                 if (Interlocked.Exchange(ref me.m_RegisteredWait, null) != null) {
  6264.                     switch (me.m_BlockEventBits) {
  6265.                         case AsyncEventBits.FdConnect:
  6266.                             me.ConnectCallback();
  6267.                             break;
  6268.                         case AsyncEventBits.FdAccept:
  6269.                            
  6270.                             me.AcceptCallback(null);
  6271.                             break;
  6272.                     }
  6273.                 }
  6274.                 #if DEBUG
  6275.             }
  6276.             #endif
  6277.             GlobalLog.Leave("Socket#" + ValidationHelper.HashString(state) + "::RegisteredWaitCallback", "m_BlockEventBits:" + ((Socket)state).m_BlockEventBits.ToString());
  6278.         }
  6279.        
  6280.         //
  6281.         // ValidateBlockingMode - called before synchronous calls to validate
  6282.         // the fact that we are in blocking mode (not in non-blocking mode) so the
  6283.         // call will actually be synchronous
  6284.         //
  6285.         private void ValidateBlockingMode()
  6286.         {
  6287.             if (willBlock && !willBlockInternal) {
  6288.                 throw new InvalidOperationException(SR.GetString(SR.net_invasync));
  6289.             }
  6290.         }
  6291.        
  6292.        
  6293.         //
  6294.         // This Method binds the Socket Win32 Handle to the ThreadPool's CompletionPort
  6295.         // (make sure we only bind once per socket)
  6296.         //
  6297.         [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.UnmanagedCode)]
  6298.         internal void BindToCompletionPort()
  6299.         {
  6300.             //
  6301.             // Check to see if the socket native m_Handle is already
  6302.             // bound to the ThreadPool's completion port.
  6303.             //
  6304.             if (!m_BoundToThreadPool && !UseOverlappedIO) {
  6305.                 lock (this) {
  6306.                     if (!m_BoundToThreadPool) {
  6307.                         //
  6308.                         // bind the socket native m_Handle to the ThreadPool
  6309.                         //
  6310.                         GlobalLog.Print("Socket#" + ValidationHelper.HashString(this) + "::BindToCompletionPort() calling ThreadPool.BindHandle()");
  6311.                        
  6312.                         try {
  6313.                             ThreadPool.BindHandle(m_Handle);
  6314.                             m_BoundToThreadPool = true;
  6315.                         }
  6316.                         catch (Exception exception) {
  6317.                             if (NclUtilities.IsFatal(exception))
  6318.                                 throw;
  6319.                             Close(0);
  6320.                             throw;
  6321.                         }
  6322.                     }
  6323.                 }
  6324.             }
  6325.         }
  6326.        
  6327.        
  6328.     }
  6329.    
  6330.    
  6331.     internal class ConnectAsyncResult : ContextAwareResult
  6332.     {
  6333.         internal ConnectAsyncResult(object myObject, object myState, AsyncCallback myCallBack) : base(myObject, myState, myCallBack)
  6334.         {
  6335.         }
  6336.     }
  6337.    
  6338.     internal class AcceptAsyncResult : ContextAwareResult
  6339.     {
  6340.         internal AcceptAsyncResult(object myObject, object myState, AsyncCallback myCallBack) : base(myObject, myState, myCallBack)
  6341.         {
  6342.         }
  6343.     }
  6344.    
  6345.    
  6346. }

Developer Fusion