Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Net / System / Net / NetworkInformation / ping.cs / 1305376 / ping.cs
namespace System.Net.NetworkInformation { using System.Net; using System.Net.Sockets; using System; using System.Runtime.InteropServices; using System.Threading; using System.ComponentModel; using System.Diagnostics; using System.Security.Permissions; public delegate void PingCompletedEventHandler (object sender, PingCompletedEventArgs e); public class PingCompletedEventArgs: System.ComponentModel.AsyncCompletedEventArgs { PingReply reply; internal PingCompletedEventArgs (PingReply reply, Exception error, bool cancelled, object userToken):base(error,cancelled,userToken) { this.reply = reply; } public PingReply Reply{get {return reply;}} } public class Ping:Component { const int MaxUdpPacket = 0xFFFF + 256; // Marshal.SizeOf(typeof(Icmp6EchoReply)) * 2 + ip header info; const int MaxBufferSize = 65500; //artificial constraint due to win32 api limitations. const int DefaultTimeout = 5000; //5 seconds same as ping.exe const int DefaultSendBufferSize = 32; //same as ping.exe byte[] defaultSendBuffer = null; bool ipv6 = false; bool cancelled = false; bool disposed = false; object lockObject = new object(); //used for icmpsendecho apis internal ManualResetEvent pingEvent = null; private RegisteredWaitHandle registeredWait = null; SafeLocalFree requestBuffer = null; SafeLocalFree replyBuffer = null; int sendSize = 0; //needed to determine what reply size is for ipv6 in callback SafeCloseIcmpHandle handlePingV4 = null; SafeCloseIcmpHandle handlePingV6 = null; //new async event support AsyncOperation asyncOp = null; SendOrPostCallback onPingCompletedDelegate; public event PingCompletedEventHandler PingCompleted; // For blocking in SendAsyncCancel() ManualResetEvent asyncFinished = null; bool InAsyncCall { get { if (asyncFinished == null) return false; // Never blocks, just checks if a thread would block. return !asyncFinished.WaitOne(0); } set { if (asyncFinished == null) asyncFinished = new ManualResetEvent(!value); else if (value) asyncFinished.Reset(); // Block else asyncFinished.Set(); // Clear } } protected void OnPingCompleted(PingCompletedEventArgs e) { if (PingCompleted != null) { PingCompleted (this,e); } } void PingCompletedWaitCallback (object operationState) { OnPingCompleted((PingCompletedEventArgs)operationState); } public Ping () { onPingCompletedDelegate = new SendOrPostCallback (PingCompletedWaitCallback); } //cancel pending async requests, close the handles private void InternalDispose () { if (disposed) { return; } disposed = true; if (InAsyncCall) { SendAsyncCancel (); } if (handlePingV4 != null) { handlePingV4.Close (); handlePingV4 = null; } if (handlePingV6 != null) { handlePingV6.Close (); handlePingV6 = null; } UnregisterWaitHandle(); if (pingEvent != null) { pingEvent.Close(); pingEvent = null; } if (replyBuffer != null) { replyBuffer.Close(); replyBuffer = null; } if (asyncFinished != null) { asyncFinished.Close(); asyncFinished = null; } } private void UnregisterWaitHandle() { lock (lockObject) { if (registeredWait != null) { registeredWait.Unregister(null); // If Unregister returns false, it is sufficient to nullify registeredWait // and let its own finilizer clean up later. registeredWait = null; } } } protected override void Dispose(Boolean disposing) { if (disposing) { // Only on explicit dispose. Otherwise, the GC can cleanup everything else. InternalDispose(); } base.Dispose(disposing); } //cancels pending async calls public void SendAsyncCancel() { lock (lockObject) { if (!InAsyncCall) { return; } cancelled = true; } // Because there is no actual native cancel, // we just have to block until the current operation is completed. asyncFinished.WaitOne(); } //private callback invoked when icmpsendecho apis succeed private static void PingCallback (object state, bool signaled) { Ping ping = (Ping)state; PingCompletedEventArgs eventArgs = null; bool cancelled = false; AsyncOperation asyncOp = null; SendOrPostCallback onPingCompletedDelegate = null; try { lock (ping.lockObject) { cancelled = ping.cancelled; asyncOp = ping.asyncOp; onPingCompletedDelegate = ping.onPingCompletedDelegate; if (!cancelled) { //parse reply buffer SafeLocalFree buffer = ping.replyBuffer; Debug.Assert(ComNetOS.IsPostWin2K,"Requires XP or higher, Win2k IcmpParseReply code removed"); // IcmpParseReplies in XP does -required- post prosseing for IPv4 ping replies; // No Icmp6ParseReplies calls are needed for post processing // because they would only set the Icmp6EchoReply.Status value into lastWin32Error, // which we will retrieve from marshalling anyways. if (!ping.ipv6 && !ComNetOS.IsVista) { // XP IPv4 UnsafeNetInfoNativeMethods.IcmpParseReplies(buffer.DangerousGetHandle(), (uint)MaxUdpPacket); } //marshals and constructs new reply PingReply reply; if (ping.ipv6) { Icmp6EchoReply icmp6Reply = (Icmp6EchoReply)Marshal.PtrToStructure (buffer.DangerousGetHandle (), typeof(Icmp6EchoReply)); reply = new PingReply (icmp6Reply,buffer.DangerousGetHandle(),ping.sendSize); } else { IcmpEchoReply icmpReply = (IcmpEchoReply)Marshal.PtrToStructure (buffer.DangerousGetHandle (), typeof(IcmpEchoReply)); reply = new PingReply (icmpReply); } eventArgs = new PingCompletedEventArgs (reply, null, false, asyncOp.UserSuppliedState); } else { //cancelled eventArgs = new PingCompletedEventArgs (null, null, true, asyncOp.UserSuppliedState); } } } // in case of failure, create a failed event arg catch (Exception e) { PingException pe = new PingException(SR.GetString(SR.net_ping), e); eventArgs = new PingCompletedEventArgs (null,pe, false, asyncOp.UserSuppliedState); } finally { ping.FreeUnmanagedStructures (); ping.UnregisterWaitHandle(); ping.InAsyncCall = false; } asyncOp.PostOperationCompleted (onPingCompletedDelegate, eventArgs); } public PingReply Send (string hostNameOrAddress) { return Send (hostNameOrAddress, DefaultTimeout, DefaultSendBuffer, null); } public PingReply Send (string hostNameOrAddress, int timeout) { return Send (hostNameOrAddress, timeout, DefaultSendBuffer, null); } public PingReply Send (IPAddress address) { return Send (address, DefaultTimeout, DefaultSendBuffer, null); } public PingReply Send (IPAddress address, int timeout) { return Send (address, timeout, DefaultSendBuffer, null); } public PingReply Send (string hostNameOrAddress, int timeout, byte[] buffer) { return Send (hostNameOrAddress, timeout, buffer, null); } public PingReply Send (IPAddress address, int timeout, byte[] buffer) { return Send (address, timeout, buffer, null); } public PingReply Send (string hostNameOrAddress, int timeout, byte[] buffer, PingOptions options) { if (ValidationHelper.IsBlankString(hostNameOrAddress)) { throw new ArgumentNullException ("hostNameOrAddress"); } IPAddress address; if (!IPAddress.TryParse(hostNameOrAddress, out address)) { try { address = Dns.GetHostAddresses(hostNameOrAddress)[0]; } catch (ArgumentException) { throw; } catch (Exception ex) { throw new PingException(SR.GetString(SR.net_ping), ex); } } return Send(address, timeout, buffer, options); } public PingReply Send (IPAddress address, int timeout, byte[] buffer, PingOptions options) { if (buffer == null) { throw new ArgumentNullException ("buffer"); } if (buffer.Length > MaxBufferSize ) { throw new ArgumentException(SR.GetString(SR.net_invalidPingBufferSize), "buffer"); } if (timeout < 0) { throw new ArgumentOutOfRangeException ("timeout"); } if (address == null) { throw new ArgumentNullException ("address"); } TestIsIpSupported(address); // Address family is installed? if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any)) { throw new ArgumentException(SR.GetString(SR.net_invalid_ip_addr), "address"); } if (InAsyncCall) { throw new InvalidOperationException(SR.GetString(SR.net_inasync)); } if (disposed) { throw new ObjectDisposedException (this.GetType ().FullName); } // // FxCop: need to snapshot the address here, so we're sure that it's not changed between the permission // and the operation, and to be sure that IPAddress.ToString() is called and not some override that // always returns "localhost" or something. // IPAddress addressSnapshot; if (address.AddressFamily == AddressFamily.InterNetwork) { addressSnapshot = new IPAddress(address.GetAddressBytes()); } else { addressSnapshot = new IPAddress(address.GetAddressBytes(), address.ScopeId); } (new NetworkInformationPermission(NetworkInformationAccess.Ping)).Demand(); try { return InternalSend (addressSnapshot, buffer, timeout, options, false); } catch (Exception e) { throw new PingException(SR.GetString(SR.net_ping), e); } } [HostProtection(ExternalThreading=true)] public void SendAsync (string hostNameOrAddress, object userToken) { SendAsync (hostNameOrAddress, DefaultTimeout, DefaultSendBuffer, userToken); } [HostProtection(ExternalThreading=true)] public void SendAsync (string hostNameOrAddress, int timeout, object userToken) { SendAsync (hostNameOrAddress, timeout, DefaultSendBuffer, userToken); } [HostProtection(ExternalThreading=true)] public void SendAsync (IPAddress address, object userToken) { SendAsync (address, DefaultTimeout, DefaultSendBuffer, userToken); } [HostProtection(ExternalThreading=true)] public void SendAsync (IPAddress address, int timeout, object userToken) { SendAsync (address, timeout, DefaultSendBuffer, userToken); } [HostProtection(ExternalThreading=true)] public void SendAsync (string hostNameOrAddress, int timeout, byte[] buffer, object userToken) { SendAsync (hostNameOrAddress, timeout, buffer, null, userToken); } [HostProtection(ExternalThreading=true)] public void SendAsync (IPAddress address, int timeout, byte[] buffer, object userToken) { SendAsync (address, timeout, buffer, null, userToken); } [HostProtection(ExternalThreading=true)] public void SendAsync (string hostNameOrAddress, int timeout, byte[] buffer, PingOptions options, object userToken) { if (ValidationHelper.IsBlankString(hostNameOrAddress)) { throw new ArgumentNullException ("hostNameOrAddress"); } if (buffer == null) { throw new ArgumentNullException ("buffer"); } if (buffer.Length > MaxBufferSize ) { throw new ArgumentException(SR.GetString(SR.net_invalidPingBufferSize), "buffer"); } if (timeout < 0) { throw new ArgumentOutOfRangeException ("timeout"); } if (InAsyncCall) { throw new InvalidOperationException(SR.GetString(SR.net_inasync)); } if (disposed) { throw new ObjectDisposedException (this.GetType ().FullName); } IPAddress address; if (IPAddress.TryParse(hostNameOrAddress, out address)) { SendAsync(address, timeout, buffer, options, userToken); return; } try { InAsyncCall = true; cancelled = false; asyncOp = AsyncOperationManager.CreateOperation (userToken); AsyncStateObject state = new AsyncStateObject(hostNameOrAddress,buffer,timeout,options,userToken); ThreadPool.QueueUserWorkItem(new WaitCallback(ContinueAsyncSend), state); } catch (Exception e) { InAsyncCall = false; throw new PingException(SR.GetString(SR.net_ping), e); } } [HostProtection(ExternalThreading=true)] public void SendAsync (IPAddress address, int timeout, byte[] buffer, PingOptions options, object userToken) { if (buffer == null) { throw new ArgumentNullException ("buffer"); } if (buffer.Length > MaxBufferSize ) { throw new ArgumentException(SR.GetString(SR.net_invalidPingBufferSize), "buffer"); } if (timeout < 0) { throw new ArgumentOutOfRangeException ("timeout"); } if (address == null) { throw new ArgumentNullException ("address"); } TestIsIpSupported(address); // Address family is installed? if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any)) { throw new ArgumentException(SR.GetString(SR.net_invalid_ip_addr), "address"); } if (InAsyncCall) { throw new InvalidOperationException(SR.GetString(SR.net_inasync)); } if (disposed) { throw new ObjectDisposedException (this.GetType ().FullName); } // // FxCop: need to snapshot the address here, so we're sure that it's not changed between the permission // and the operation, and to be sure that IPAddress.ToString() is called and not some override that // always returns "localhost" or something. // IPAddress addressSnapshot; if (address.AddressFamily == AddressFamily.InterNetwork) { addressSnapshot = new IPAddress(address.GetAddressBytes()); } else { addressSnapshot = new IPAddress(address.GetAddressBytes(), address.ScopeId); } (new NetworkInformationPermission(NetworkInformationAccess.Ping)).Demand(); try{ InAsyncCall = true; cancelled = false; asyncOp = AsyncOperationManager.CreateOperation (userToken); InternalSend (addressSnapshot, buffer, timeout, options, true); } catch(Exception e){ InAsyncCall = false; throw new PingException(SR.GetString(SR.net_ping), e); } } internal class AsyncStateObject{ internal AsyncStateObject(string hostName, byte[] buffer, int timeout, PingOptions options, object userToken) { this.hostName = hostName; this.buffer = buffer; this.timeout = timeout; this.options = options; this.userToken = userToken; } internal byte[] buffer; internal string hostName; internal int timeout; internal PingOptions options; internal object userToken; } private void ContinueAsyncSend(object state) { // // FxCop: need to snapshot the address here, so we're sure that it's not changed between the permission // and the operation, and to be sure that IPAddress.ToString() is called and not some override that // always returns "localhost" or something. // Debug.Assert(asyncOp != null, "Null AsyncOp?"); AsyncStateObject stateObject = (AsyncStateObject) state; try { IPAddress addressSnapshot = Dns.GetHostAddresses(stateObject.hostName)[0]; (new NetworkInformationPermission(NetworkInformationAccess.Ping)).Demand(); InternalSend (addressSnapshot, stateObject.buffer, stateObject.timeout, stateObject.options, true); } catch(Exception e){ PingException pe = new PingException(SR.GetString(SR.net_ping), e); PingCompletedEventArgs eventArgs = new PingCompletedEventArgs (null, pe, false, asyncOp.UserSuppliedState); InAsyncCall = false; asyncOp.PostOperationCompleted(onPingCompletedDelegate, eventArgs); } } // internal method responsible for sending echo request on win2k and higher private PingReply InternalSend (IPAddress address, byte[] buffer, int timeout, PingOptions options, bool async) { Debug.Assert(ComNetOS.IsPostWin2K, "Requires XP or higher"); ipv6 = (address.AddressFamily == AddressFamily.InterNetworkV6)?true:false; sendSize = buffer.Length; //get and cache correct handle if (!ipv6 && handlePingV4 == null) { handlePingV4 = UnsafeNetInfoNativeMethods.IcmpCreateFile (); if (handlePingV4.IsInvalid) { handlePingV4 = null; throw new Win32Exception(); // Gets last error } } else if (ipv6 && handlePingV6 == null) { handlePingV6 = UnsafeNetInfoNativeMethods.Icmp6CreateFile(); if (handlePingV6.IsInvalid) { handlePingV6 = null; throw new Win32Exception(); // Gets last error } } //setup the options IPOptions ipOptions = new IPOptions (options); //setup the reply buffer if (replyBuffer == null) { replyBuffer = SafeLocalFree.LocalAlloc (MaxUdpPacket); } //queue the event int error; try { if (async) { if (pingEvent == null) pingEvent = new ManualResetEvent (false); else pingEvent.Reset(); registeredWait = ThreadPool.RegisterWaitForSingleObject (pingEvent, new WaitOrTimerCallback (PingCallback), this, -1, true); } //Copy user dfata into the native world SetUnmanagedStructures (buffer); if (!ipv6) { if (async) { error = (int)UnsafeNetInfoNativeMethods.IcmpSendEcho2 (handlePingV4, pingEvent.SafeWaitHandle, IntPtr.Zero, IntPtr.Zero, (uint)address.m_Address, requestBuffer, (ushort)buffer.Length, ref ipOptions, replyBuffer, MaxUdpPacket, (uint)timeout); } else{ error = (int)UnsafeNetInfoNativeMethods.IcmpSendEcho2 (handlePingV4, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, (uint)address.m_Address, requestBuffer, (ushort)buffer.Length, ref ipOptions, replyBuffer, MaxUdpPacket, (uint)timeout); } } else { IPEndPoint ep = new IPEndPoint (address, 0); SocketAddress remoteAddr = ep.Serialize (); byte[] sourceAddr = new byte[28]; if(async){ error = (int)UnsafeNetInfoNativeMethods.Icmp6SendEcho2 (handlePingV6, pingEvent.SafeWaitHandle, IntPtr.Zero, IntPtr.Zero, sourceAddr, remoteAddr.m_Buffer, requestBuffer, (ushort)buffer.Length, ref ipOptions, replyBuffer, MaxUdpPacket, (uint)timeout); } else{ error = (int)UnsafeNetInfoNativeMethods.Icmp6SendEcho2 (handlePingV6, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, sourceAddr, remoteAddr.m_Buffer, requestBuffer, (ushort)buffer.Length, ref ipOptions, replyBuffer, MaxUdpPacket, (uint)timeout); } } } catch { UnregisterWaitHandle(); throw; } //need this if something is bogus. if (error == 0) { error = (int)Marshal.GetLastWin32Error(); // Only skip Async IO Pending error value if (async && error == UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING) return null; // Expected async return value // Cleanup FreeUnmanagedStructures(); UnregisterWaitHandle(); if (async // No IPStatus async errors || error < (int)IPStatus.DestinationNetworkUnreachable // Min || error > (int)IPStatus.DestinationScopeMismatch) // Max // Out of IPStatus range throw new Win32Exception(error); return new PingReply((IPStatus)error); // Synchronous IPStatus errors } if (async) { return null; } FreeUnmanagedStructures (); //return the reply PingReply reply; if (ipv6) { Icmp6EchoReply icmp6Reply = (Icmp6EchoReply)Marshal.PtrToStructure(replyBuffer.DangerousGetHandle(), typeof(Icmp6EchoReply)); reply = new PingReply(icmp6Reply, replyBuffer.DangerousGetHandle(), sendSize); } else { IcmpEchoReply icmpReply = (IcmpEchoReply)Marshal.PtrToStructure(replyBuffer.DangerousGetHandle(), typeof(IcmpEchoReply)); reply = new PingReply(icmpReply); } // IcmpEchoReply still has an unsafe IntPtr reference into replybuffer // and replybuffer was being freed prematurely by the GC, causing AccessViolationExceptions. GC.KeepAlive(replyBuffer); return reply; } // Tests if the current machine supports the given ip protocol family private void TestIsIpSupported(IPAddress ip) { // Catches if IPv4 has been uninstalled on Vista+ if (ip.AddressFamily == AddressFamily.InterNetwork && !Socket.OSSupportsIPv4) throw new NotSupportedException(SR.GetString(SR.net_ipv4_not_installed)); // Catches if IPv6 is not installed on XP else if ((ip.AddressFamily == AddressFamily.InterNetworkV6 && !Socket.OSSupportsIPv6)) throw new NotSupportedException(SR.GetString(SR.net_ipv6_not_installed)); } // copies sendbuffer into unmanaged memory for async icmpsendecho apis private unsafe void SetUnmanagedStructures (byte[] buffer) { requestBuffer = SafeLocalFree.LocalAlloc(buffer.Length); byte* dst = (byte*)requestBuffer.DangerousGetHandle(); for (int i = 0; i < buffer.Length; ++i) { dst[i] = buffer[i]; } } // release the unmanaged memory after ping completion void FreeUnmanagedStructures () { if (requestBuffer != null) { requestBuffer.Close(); requestBuffer = null; } } // creates a default send buffer if a buffer wasn't specified. This follows the // ping.exe model private byte[] DefaultSendBuffer { get { if (defaultSendBuffer == null) { defaultSendBuffer = new byte[DefaultSendBufferSize]; for (int i=0;iMaxBufferSize ) { throw new ArgumentException(SR.GetString(SR.net_invalidPingBufferSize), "buffer"); } if (timeout < 0) { throw new ArgumentOutOfRangeException ("timeout"); } if (address == null) { throw new ArgumentNullException ("address"); } TestIsIpSupported(address); // Address family is installed? if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any)) { throw new ArgumentException(SR.GetString(SR.net_invalid_ip_addr), "address"); } if (InAsyncCall) { throw new InvalidOperationException(SR.GetString(SR.net_inasync)); } if (disposed) { throw new ObjectDisposedException (this.GetType ().FullName); } // // FxCop: need to snapshot the address here, so we're sure that it's not changed between the permission // and the operation, and to be sure that IPAddress.ToString() is called and not some override that // always returns "localhost" or something. // IPAddress addressSnapshot; if (address.AddressFamily == AddressFamily.InterNetwork) { addressSnapshot = new IPAddress(address.GetAddressBytes()); } else { addressSnapshot = new IPAddress(address.GetAddressBytes(), address.ScopeId); } (new NetworkInformationPermission(NetworkInformationAccess.Ping)).Demand(); try { return InternalSend (addressSnapshot, buffer, timeout, options, false); } catch (Exception e) { throw new PingException(SR.GetString(SR.net_ping), e); } } [HostProtection(ExternalThreading=true)] public void SendAsync (string hostNameOrAddress, object userToken) { SendAsync (hostNameOrAddress, DefaultTimeout, DefaultSendBuffer, userToken); } [HostProtection(ExternalThreading=true)] public void SendAsync (string hostNameOrAddress, int timeout, object userToken) { SendAsync (hostNameOrAddress, timeout, DefaultSendBuffer, userToken); } [HostProtection(ExternalThreading=true)] public void SendAsync (IPAddress address, object userToken) { SendAsync (address, DefaultTimeout, DefaultSendBuffer, userToken); } [HostProtection(ExternalThreading=true)] public void SendAsync (IPAddress address, int timeout, object userToken) { SendAsync (address, timeout, DefaultSendBuffer, userToken); } [HostProtection(ExternalThreading=true)] public void SendAsync (string hostNameOrAddress, int timeout, byte[] buffer, object userToken) { SendAsync (hostNameOrAddress, timeout, buffer, null, userToken); } [HostProtection(ExternalThreading=true)] public void SendAsync (IPAddress address, int timeout, byte[] buffer, object userToken) { SendAsync (address, timeout, buffer, null, userToken); } [HostProtection(ExternalThreading=true)] public void SendAsync (string hostNameOrAddress, int timeout, byte[] buffer, PingOptions options, object userToken) { if (ValidationHelper.IsBlankString(hostNameOrAddress)) { throw new ArgumentNullException ("hostNameOrAddress"); } if (buffer == null) { throw new ArgumentNullException ("buffer"); } if (buffer.Length > MaxBufferSize ) { throw new ArgumentException(SR.GetString(SR.net_invalidPingBufferSize), "buffer"); } if (timeout < 0) { throw new ArgumentOutOfRangeException ("timeout"); } if (InAsyncCall) { throw new InvalidOperationException(SR.GetString(SR.net_inasync)); } if (disposed) { throw new ObjectDisposedException (this.GetType ().FullName); } IPAddress address; if (IPAddress.TryParse(hostNameOrAddress, out address)) { SendAsync(address, timeout, buffer, options, userToken); return; } try { InAsyncCall = true; cancelled = false; asyncOp = AsyncOperationManager.CreateOperation (userToken); AsyncStateObject state = new AsyncStateObject(hostNameOrAddress,buffer,timeout,options,userToken); ThreadPool.QueueUserWorkItem(new WaitCallback(ContinueAsyncSend), state); } catch (Exception e) { InAsyncCall = false; throw new PingException(SR.GetString(SR.net_ping), e); } } [HostProtection(ExternalThreading=true)] public void SendAsync (IPAddress address, int timeout, byte[] buffer, PingOptions options, object userToken) { if (buffer == null) { throw new ArgumentNullException ("buffer"); } if (buffer.Length > MaxBufferSize ) { throw new ArgumentException(SR.GetString(SR.net_invalidPingBufferSize), "buffer"); } if (timeout < 0) { throw new ArgumentOutOfRangeException ("timeout"); } if (address == null) { throw new ArgumentNullException ("address"); } TestIsIpSupported(address); // Address family is installed? if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any)) { throw new ArgumentException(SR.GetString(SR.net_invalid_ip_addr), "address"); } if (InAsyncCall) { throw new InvalidOperationException(SR.GetString(SR.net_inasync)); } if (disposed) { throw new ObjectDisposedException (this.GetType ().FullName); } // // FxCop: need to snapshot the address here, so we're sure that it's not changed between the permission // and the operation, and to be sure that IPAddress.ToString() is called and not some override that // always returns "localhost" or something. // IPAddress addressSnapshot; if (address.AddressFamily == AddressFamily.InterNetwork) { addressSnapshot = new IPAddress(address.GetAddressBytes()); } else { addressSnapshot = new IPAddress(address.GetAddressBytes(), address.ScopeId); } (new NetworkInformationPermission(NetworkInformationAccess.Ping)).Demand(); try{ InAsyncCall = true; cancelled = false; asyncOp = AsyncOperationManager.CreateOperation (userToken); InternalSend (addressSnapshot, buffer, timeout, options, true); } catch(Exception e){ InAsyncCall = false; throw new PingException(SR.GetString(SR.net_ping), e); } } internal class AsyncStateObject{ internal AsyncStateObject(string hostName, byte[] buffer, int timeout, PingOptions options, object userToken) { this.hostName = hostName; this.buffer = buffer; this.timeout = timeout; this.options = options; this.userToken = userToken; } internal byte[] buffer; internal string hostName; internal int timeout; internal PingOptions options; internal object userToken; } private void ContinueAsyncSend(object state) { // // FxCop: need to snapshot the address here, so we're sure that it's not changed between the permission // and the operation, and to be sure that IPAddress.ToString() is called and not some override that // always returns "localhost" or something. // Debug.Assert(asyncOp != null, "Null AsyncOp?"); AsyncStateObject stateObject = (AsyncStateObject) state; try { IPAddress addressSnapshot = Dns.GetHostAddresses(stateObject.hostName)[0]; (new NetworkInformationPermission(NetworkInformationAccess.Ping)).Demand(); InternalSend (addressSnapshot, stateObject.buffer, stateObject.timeout, stateObject.options, true); } catch(Exception e){ PingException pe = new PingException(SR.GetString(SR.net_ping), e); PingCompletedEventArgs eventArgs = new PingCompletedEventArgs (null, pe, false, asyncOp.UserSuppliedState); InAsyncCall = false; asyncOp.PostOperationCompleted(onPingCompletedDelegate, eventArgs); } } // internal method responsible for sending echo request on win2k and higher private PingReply InternalSend (IPAddress address, byte[] buffer, int timeout, PingOptions options, bool async) { Debug.Assert(ComNetOS.IsPostWin2K, "Requires XP or higher"); ipv6 = (address.AddressFamily == AddressFamily.InterNetworkV6)?true:false; sendSize = buffer.Length; //get and cache correct handle if (!ipv6 && handlePingV4 == null) { handlePingV4 = UnsafeNetInfoNativeMethods.IcmpCreateFile (); if (handlePingV4.IsInvalid) { handlePingV4 = null; throw new Win32Exception(); // Gets last error } } else if (ipv6 && handlePingV6 == null) { handlePingV6 = UnsafeNetInfoNativeMethods.Icmp6CreateFile(); if (handlePingV6.IsInvalid) { handlePingV6 = null; throw new Win32Exception(); // Gets last error } } //setup the options IPOptions ipOptions = new IPOptions (options); //setup the reply buffer if (replyBuffer == null) { replyBuffer = SafeLocalFree.LocalAlloc (MaxUdpPacket); } //queue the event int error; try { if (async) { if (pingEvent == null) pingEvent = new ManualResetEvent (false); else pingEvent.Reset(); registeredWait = ThreadPool.RegisterWaitForSingleObject (pingEvent, new WaitOrTimerCallback (PingCallback), this, -1, true); } //Copy user dfata into the native world SetUnmanagedStructures (buffer); if (!ipv6) { if (async) { error = (int)UnsafeNetInfoNativeMethods.IcmpSendEcho2 (handlePingV4, pingEvent.SafeWaitHandle, IntPtr.Zero, IntPtr.Zero, (uint)address.m_Address, requestBuffer, (ushort)buffer.Length, ref ipOptions, replyBuffer, MaxUdpPacket, (uint)timeout); } else{ error = (int)UnsafeNetInfoNativeMethods.IcmpSendEcho2 (handlePingV4, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, (uint)address.m_Address, requestBuffer, (ushort)buffer.Length, ref ipOptions, replyBuffer, MaxUdpPacket, (uint)timeout); } } else { IPEndPoint ep = new IPEndPoint (address, 0); SocketAddress remoteAddr = ep.Serialize (); byte[] sourceAddr = new byte[28]; if(async){ error = (int)UnsafeNetInfoNativeMethods.Icmp6SendEcho2 (handlePingV6, pingEvent.SafeWaitHandle, IntPtr.Zero, IntPtr.Zero, sourceAddr, remoteAddr.m_Buffer, requestBuffer, (ushort)buffer.Length, ref ipOptions, replyBuffer, MaxUdpPacket, (uint)timeout); } else{ error = (int)UnsafeNetInfoNativeMethods.Icmp6SendEcho2 (handlePingV6, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, sourceAddr, remoteAddr.m_Buffer, requestBuffer, (ushort)buffer.Length, ref ipOptions, replyBuffer, MaxUdpPacket, (uint)timeout); } } } catch { UnregisterWaitHandle(); throw; } //need this if something is bogus. if (error == 0) { error = (int)Marshal.GetLastWin32Error(); // Only skip Async IO Pending error value if (async && error == UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING) return null; // Expected async return value // Cleanup FreeUnmanagedStructures(); UnregisterWaitHandle(); if (async // No IPStatus async errors || error < (int)IPStatus.DestinationNetworkUnreachable // Min || error > (int)IPStatus.DestinationScopeMismatch) // Max // Out of IPStatus range throw new Win32Exception(error); return new PingReply((IPStatus)error); // Synchronous IPStatus errors } if (async) { return null; } FreeUnmanagedStructures (); //return the reply PingReply reply; if (ipv6) { Icmp6EchoReply icmp6Reply = (Icmp6EchoReply)Marshal.PtrToStructure(replyBuffer.DangerousGetHandle(), typeof(Icmp6EchoReply)); reply = new PingReply(icmp6Reply, replyBuffer.DangerousGetHandle(), sendSize); } else { IcmpEchoReply icmpReply = (IcmpEchoReply)Marshal.PtrToStructure(replyBuffer.DangerousGetHandle(), typeof(IcmpEchoReply)); reply = new PingReply(icmpReply); } // IcmpEchoReply still has an unsafe IntPtr reference into replybuffer // and replybuffer was being freed prematurely by the GC, causing AccessViolationExceptions. GC.KeepAlive(replyBuffer); return reply; } // Tests if the current machine supports the given ip protocol family private void TestIsIpSupported(IPAddress ip) { // Catches if IPv4 has been uninstalled on Vista+ if (ip.AddressFamily == AddressFamily.InterNetwork && !Socket.OSSupportsIPv4) throw new NotSupportedException(SR.GetString(SR.net_ipv4_not_installed)); // Catches if IPv6 is not installed on XP else if ((ip.AddressFamily == AddressFamily.InterNetworkV6 && !Socket.OSSupportsIPv6)) throw new NotSupportedException(SR.GetString(SR.net_ipv6_not_installed)); } // copies sendbuffer into unmanaged memory for async icmpsendecho apis private unsafe void SetUnmanagedStructures (byte[] buffer) { requestBuffer = SafeLocalFree.LocalAlloc(buffer.Length); byte* dst = (byte*)requestBuffer.DangerousGetHandle(); for (int i = 0; i < buffer.Length; ++i) { dst[i] = buffer[i]; } } // release the unmanaged memory after ping completion void FreeUnmanagedStructures () { if (requestBuffer != null) { requestBuffer.Close(); requestBuffer = null; } } // creates a default send buffer if a buffer wasn't specified. This follows the // ping.exe model private byte[] DefaultSendBuffer { get { if (defaultSendBuffer == null) { defaultSendBuffer = new byte[DefaultSendBufferSize]; for (int i=0;i
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- WorkflowRuntime.cs
- Rect.cs
- SQLStringStorage.cs
- ipaddressinformationcollection.cs
- FixedDocument.cs
- ObjectManager.cs
- PeerName.cs
- BindingMemberInfo.cs
- CodeBlockBuilder.cs
- AsymmetricKeyExchangeFormatter.cs
- FolderLevelBuildProvider.cs
- HttpException.cs
- DockAndAnchorLayout.cs
- ping.cs
- AssemblyInfo.cs
- CmsInterop.cs
- ChannelServices.cs
- MethodAccessException.cs
- WSTrustDec2005.cs
- ResourceDisplayNameAttribute.cs
- HScrollProperties.cs
- CompModSwitches.cs
- CriticalHandle.cs
- DrawingState.cs
- WriterOutput.cs
- ClientEventManager.cs
- MetadataArtifactLoaderFile.cs
- DelayedRegex.cs
- VisualProxy.cs
- RadioButtonAutomationPeer.cs
- ConvertEvent.cs
- DependencyPropertyAttribute.cs
- VSWCFServiceContractGenerator.cs
- HttpRuntimeSection.cs
- MultiBindingExpression.cs
- ParallelEnumerable.cs
- JsonXmlDataContract.cs
- NavigatorInput.cs
- CompilerCollection.cs
- Blend.cs
- DataGridViewCellEventArgs.cs
- Parser.cs
- NavigationPropertyEmitter.cs
- autovalidator.cs
- PageAsyncTaskManager.cs
- ExtentJoinTreeNode.cs
- HtmlInputFile.cs
- CodeCompiler.cs
- ModifyActivitiesPropertyDescriptor.cs
- ServiceProviders.cs
- SqlDataSourceSelectingEventArgs.cs
- CorrelationManager.cs
- HtmlFormAdapter.cs
- EntityCommandCompilationException.cs
- BatchServiceHost.cs
- ZipIOExtraFieldElement.cs
- SqlFacetAttribute.cs
- ComNativeDescriptor.cs
- SoapAttributes.cs
- DesignerDeviceConfig.cs
- PropertyBuilder.cs
- UnmanagedMemoryStream.cs
- LabelExpression.cs
- CompilerHelpers.cs
- WebPart.cs
- ContentFileHelper.cs
- CompilationUnit.cs
- SqlDataSourceDesigner.cs
- EastAsianLunisolarCalendar.cs
- Types.cs
- DrawToolTipEventArgs.cs
- ColorAnimationUsingKeyFrames.cs
- PropertyDescriptor.cs
- SessionStateContainer.cs
- BooleanToVisibilityConverter.cs
- TextEditorSpelling.cs
- WindowsListViewGroupHelper.cs
- XmlCharacterData.cs
- Subordinate.cs
- WorkflowTransactionOptions.cs
- SqlBooleanizer.cs
- DbResourceAllocator.cs
- DbConnectionPool.cs
- PeerNameRecordCollection.cs
- AdornerDecorator.cs
- RevocationPoint.cs
- WebPartVerb.cs
- WizardPanel.cs
- TemplateNameScope.cs
- COM2IVsPerPropertyBrowsingHandler.cs
- DataGridViewRowHeaderCell.cs
- ToolBarTray.cs
- JapaneseLunisolarCalendar.cs
- InvalidCommandTreeException.cs
- AtomServiceDocumentSerializer.cs
- TextEffect.cs
- ListViewGroupCollectionEditor.cs
- RuleProcessor.cs
- TrackingStringDictionary.cs
- CookieParameter.cs