Code:
/ 4.0 / 4.0 / untmp / 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;i
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ErrorProvider.cs
- UInt32Storage.cs
- TextSegment.cs
- WebBrowsableAttribute.cs
- XmlILIndex.cs
- MultiPropertyDescriptorGridEntry.cs
- XmlILConstructAnalyzer.cs
- SqlUdtInfo.cs
- ObjectStateManagerMetadata.cs
- ValueUtilsSmi.cs
- XamlTemplateSerializer.cs
- OdbcConnectionHandle.cs
- CodeSnippetTypeMember.cs
- Columns.cs
- EntitySqlQueryBuilder.cs
- Assert.cs
- MachineSettingsSection.cs
- PersianCalendar.cs
- ellipse.cs
- DockAndAnchorLayout.cs
- InputLanguageProfileNotifySink.cs
- IncrementalReadDecoders.cs
- Part.cs
- PropertyChangedEventArgs.cs
- HttpListenerTimeoutManager.cs
- FacetChecker.cs
- CubicEase.cs
- HwndTarget.cs
- GuidelineCollection.cs
- HashCodeCombiner.cs
- DependencyPropertyChangedEventArgs.cs
- CompoundFileStreamReference.cs
- EntitySetRetriever.cs
- CodeGeneratorOptions.cs
- SrgsElement.cs
- Column.cs
- ComplusEndpointConfigContainer.cs
- ObjectQuery_EntitySqlExtensions.cs
- ButtonField.cs
- DefaultAssemblyResolver.cs
- DataViewSettingCollection.cs
- EntityContainerAssociationSetEnd.cs
- LinearGradientBrush.cs
- BufferedReceiveElement.cs
- RenderDataDrawingContext.cs
- OutputCacheModule.cs
- ComponentEditorForm.cs
- TreeNodeClickEventArgs.cs
- GeometryHitTestParameters.cs
- ListViewCancelEventArgs.cs
- DuplicateWaitObjectException.cs
- XmlILConstructAnalyzer.cs
- ActivityBindForm.Designer.cs
- PrintSystemException.cs
- ResourceAssociationSet.cs
- FormViewModeEventArgs.cs
- DetailsViewUpdatedEventArgs.cs
- InternalResources.cs
- TabControl.cs
- RTLAwareMessageBox.cs
- FunctionUpdateCommand.cs
- Rotation3D.cs
- HwndHost.cs
- ResourceAttributes.cs
- IfAction.cs
- DeploymentSectionCache.cs
- SetIndexBinder.cs
- DataGridViewBindingCompleteEventArgs.cs
- SelectionEditingBehavior.cs
- Attributes.cs
- StylusPointProperty.cs
- ColorTranslator.cs
- Evidence.cs
- InstanceLockedException.cs
- IntegerValidator.cs
- Operand.cs
- UInt64Converter.cs
- DataRecordInfo.cs
- TaskHelper.cs
- TextParentUndoUnit.cs
- MimeMultiPart.cs
- BrowserDefinition.cs
- HotSpotCollection.cs
- UriPrefixTable.cs
- SoapHttpTransportImporter.cs
- ScopedMessagePartSpecification.cs
- DotAtomReader.cs
- LogReserveAndAppendState.cs
- CustomAttribute.cs
- TargetException.cs
- TypeListConverter.cs
- Geometry3D.cs
- XmlSchemaAttributeGroup.cs
- HtmlImage.cs
- ScriptResourceAttribute.cs
- ToolStripTextBox.cs
- RelationHandler.cs
- XPathSelfQuery.cs
- ToolStripSplitStackLayout.cs
- TargetParameterCountException.cs