Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / fx / src / Net / System / Net / NetworkInformation / ping.cs / 5 / 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,IDisposable { 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 inAsyncCall = false; bool cancelled = false; bool disposed = false; //used for icmpsendecho apis internal ManualResetEvent pingEvent = null; private RegisteredWaitHandle registeredWait = null; SafeLocalFree requestBuffer = null; SafeLocalFree replyBuffer = null; int sendSize = 0; //----s, but needed to determine what reply size is for ipv6 in callback //used for downlevel calls const int TimeoutErrorCode = 0x274c; const int PacketTooBigErrorCode = 0x2738; Socket pingSocket = null; byte[] downlevelReplyBuffer = null; SafeCloseIcmpHandle handlePingV4 = null; SafeCloseIcmpHandle handlePingV6 = null; int startTime = 0; IcmpPacket packet = null; int llTimeout = 0; //new async event support AsyncOperation asyncOp = null; SendOrPostCallback onPingCompletedDelegate; public event PingCompletedEventHandler PingCompleted; 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 (pingSocket != null) { pingSocket.Close (); pingSocket = null; } if (handlePingV4 != null) { handlePingV4.Close (); handlePingV4 = null; } if (handlePingV6 != null) { handlePingV6.Close (); handlePingV6 = null; } if (registeredWait != null) { registeredWait.Unregister(null); } if (pingEvent != null) { pingEvent.Close(); } if (replyBuffer != null) { replyBuffer.Close(); } } ///void IDisposable.Dispose () { InternalDispose (); } //cancels pending async calls public void SendAsyncCancel() { lock (this) { if (!inAsyncCall) { return; } cancelled = true; if (handlePingV4 != null) { handlePingV4.Close (); handlePingV4 = null; } if (handlePingV6 != null) { handlePingV6.Close (); handlePingV6 = null; } if (pingSocket != null) { pingSocket.Close (); pingSocket = null; } } if (pingEvent != null) { pingEvent.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) { cancelled = ping.cancelled; asyncOp = ping.asyncOp; onPingCompletedDelegate = ping.onPingCompletedDelegate; if (!cancelled) { //parse reply buffer SafeLocalFree buffer = ping.replyBuffer; int error = 0; if (ping.ipv6) { error = (int)UnsafeNetInfoNativeMethods.Icmp6ParseReplies (buffer.DangerousGetHandle (), (uint)MaxUdpPacket); } else { if (ComNetOS.IsPostWin2K) { error = (int)UnsafeNetInfoNativeMethods.IcmpParseReplies (buffer.DangerousGetHandle (), (uint)MaxUdpPacket); } else{ error = (int)UnsafeIcmpNativeMethods.IcmpParseReplies (buffer.DangerousGetHandle (), (uint)MaxUdpPacket); } } //looks like we get a lot of false failures here //if (error == 0){ // error = Marshal.GetLastWin32Error(); //if (error != 0) { // throw new PingException(error); looks like we get false failures here // if the status code isn't success. //seems to be timing related // } //} //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); } } } // 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); } catch { PingException pe = new PingException(SR.GetString(SR.net_ping), new Exception(SR.GetString(SR.net_nonClsCompliantException))); eventArgs = new PingCompletedEventArgs (null,pe, false, asyncOp.UserSuppliedState); } finally { ping.FreeUnmanagedStructures (); ping.inAsyncCall = false; } if (cancelled) { eventArgs = new PingCompletedEventArgs (null, null, true, asyncOp.UserSuppliedState); } asyncOp.PostOperationCompleted (onPingCompletedDelegate, eventArgs); } //private callback invoked when downlevel send succeeds private static void PingSendCallback (IAsyncResult result) { Ping ping = (Ping)(result.AsyncState); PingCompletedEventArgs eventArgs = null; try { ping.pingSocket.EndSendTo (result); PingReply reply = null; if (!ping.cancelled) { // call blocking receive so we timeout normally. EndPoint endPoint = new IPEndPoint (0, 0); int bytesReceived = 0; while (true) { bytesReceived = ping.pingSocket.ReceiveFrom (ping.downlevelReplyBuffer, ref endPoint); if (CorrectPacket(ping.downlevelReplyBuffer,ping.packet)) { break; } if ((System.Environment.TickCount - ping.startTime) > ping.llTimeout) { reply = new PingReply(IPStatus.TimedOut); break; } } int rttTime = System.Environment.TickCount - ping.startTime; // stop timing if (reply == null) { reply = new PingReply (ping.downlevelReplyBuffer, bytesReceived, ((IPEndPoint)endPoint).Address, rttTime); } //construct the reply eventArgs = new PingCompletedEventArgs (reply, null, false, ping.asyncOp.UserSuppliedState); } } // in case of failure, create a failed event arg catch (Exception e) { PingReply reply = null; PingException pe = null; SocketException e2 = e as SocketException; if (e2 != null) { //timed out if (e2.ErrorCode == TimeoutErrorCode) { reply = new PingReply(IPStatus.TimedOut); } //buffer is too big else if (e2.ErrorCode == PacketTooBigErrorCode) { reply = new PingReply(IPStatus.PacketTooBig); } } if (reply == null) { pe = new PingException(SR.GetString(SR.net_ping), e); } eventArgs = new PingCompletedEventArgs (reply, pe, false, ping.asyncOp.UserSuppliedState); } catch { PingException pe = new PingException(SR.GetString(SR.net_ping), new Exception(SR.GetString(SR.net_nonClsCompliantException))); eventArgs = new PingCompletedEventArgs (null, pe, false, ping.asyncOp.UserSuppliedState); } //otherwise, create real one try { if (ping.cancelled) { eventArgs = new PingCompletedEventArgs (null, null, true, ping.asyncOp.UserSuppliedState); } ping.asyncOp.PostOperationCompleted (ping.onPingCompletedDelegate, eventArgs); } finally { ping.inAsyncCall = false; } } /* private static void PingRecvCallback (IAsyncResult result) { Ping ping = (Ping)result.AsyncState; EndPoint endPoint = new IPEndPoint (0, 0); int bytesReceived = ping.pingSocket.EndReceiveFrom (result, ref endPoint); PingReply reply = new PingReply (ping.downlevelReplyBuffer, bytesReceived, ((IPEndPoint)endPoint).Address, 0); ping.inAsyncCall = false; } */ 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; 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"); } if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any)) { throw new ArgumentException(SR.GetString(SR.net_invalid_ip_addr), "address"); } if (inAsyncCall == true) { 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); } catch { throw new PingException(SR.GetString(SR.net_ping), new Exception(SR.GetString(SR.net_nonClsCompliantException))); } } [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 == true) { 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; 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"); } if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any)) { throw new ArgumentException(SR.GetString(SR.net_invalid_ip_addr), "address"); } if (inAsyncCall == true) { 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; asyncOp = AsyncOperationManager.CreateOperation (userToken); InternalSend (addressSnapshot, buffer, timeout, options, true); } catch(Exception e){ inAsyncCall = false; throw new PingException(SR.GetString(SR.net_ping), e); } catch { inAsyncCall = false; throw new PingException(SR.GetString(SR.net_ping), new Exception(SR.GetString(SR.net_nonClsCompliantException))); } } 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); } catch { PingException pe = new PingException(SR.GetString(SR.net_ping), new Exception(SR.GetString(SR.net_nonClsCompliantException))); 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) { inAsyncCall = async; cancelled = false; //for llTimeout) { return new PingReply(IPStatus.TimedOut); } } //construct and return the reply rttTime = System.Environment.TickCount - startTime; // stop timing return new PingReply (downlevelReplyBuffer, bytesReceived, ((IPEndPoint)endPoint).Address, rttTime); } catch (SocketException e) { //timed out, [....] is implied if (e.ErrorCode == TimeoutErrorCode) { return new PingReply(IPStatus.TimedOut); } //buffer too big else if (e.ErrorCode == PacketTooBigErrorCode) { PingReply reply = new PingReply(IPStatus.PacketTooBig); if (!async) { return reply; } PingCompletedEventArgs eventArgs = new PingCompletedEventArgs(reply,null, false, asyncOp.UserSuppliedState); asyncOp.PostOperationCompleted (onPingCompletedDelegate, eventArgs); return null; } else throw e; } } // 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 > 16) + (total & 0xffff); total += (total >> 16); return(~total); } //converts the structure into a byte array internal byte[] GetBytes() { byte[] bytes = new byte[buffer.Length + 8]; byte[] b_cksum = BitConverter.GetBytes (checkSum); byte[] b_id = BitConverter.GetBytes (Identifier); byte[] b_seq = BitConverter.GetBytes (sequenceNumber); bytes[0] = type ; bytes[1] = subCode ; Array.Copy ( b_cksum , 0 , bytes , 2 , 2 ) ; Array.Copy ( b_id , 0 , bytes , 4 , 2 ) ; Array.Copy (b_seq, 0, bytes, 6, 2); Array.Copy ( buffer , 0 , bytes , 8 , buffer . Length ) ; return bytes; } } // class IcmpPacket } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. 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,IDisposable { 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 inAsyncCall = false; bool cancelled = false; bool disposed = false; //used for icmpsendecho apis internal ManualResetEvent pingEvent = null; private RegisteredWaitHandle registeredWait = null; SafeLocalFree requestBuffer = null; SafeLocalFree replyBuffer = null; int sendSize = 0; //----s, but needed to determine what reply size is for ipv6 in callback //used for downlevel calls const int TimeoutErrorCode = 0x274c; const int PacketTooBigErrorCode = 0x2738; Socket pingSocket = null; byte[] downlevelReplyBuffer = null; SafeCloseIcmpHandle handlePingV4 = null; SafeCloseIcmpHandle handlePingV6 = null; int startTime = 0; IcmpPacket packet = null; int llTimeout = 0; //new async event support AsyncOperation asyncOp = null; SendOrPostCallback onPingCompletedDelegate; public event PingCompletedEventHandler PingCompleted; 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 (pingSocket != null) { pingSocket.Close (); pingSocket = null; } if (handlePingV4 != null) { handlePingV4.Close (); handlePingV4 = null; } if (handlePingV6 != null) { handlePingV6.Close (); handlePingV6 = null; } if (registeredWait != null) { registeredWait.Unregister(null); } if (pingEvent != null) { pingEvent.Close(); } if (replyBuffer != null) { replyBuffer.Close(); } } /// void IDisposable.Dispose () { InternalDispose (); } //cancels pending async calls public void SendAsyncCancel() { lock (this) { if (!inAsyncCall) { return; } cancelled = true; if (handlePingV4 != null) { handlePingV4.Close (); handlePingV4 = null; } if (handlePingV6 != null) { handlePingV6.Close (); handlePingV6 = null; } if (pingSocket != null) { pingSocket.Close (); pingSocket = null; } } if (pingEvent != null) { pingEvent.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) { cancelled = ping.cancelled; asyncOp = ping.asyncOp; onPingCompletedDelegate = ping.onPingCompletedDelegate; if (!cancelled) { //parse reply buffer SafeLocalFree buffer = ping.replyBuffer; int error = 0; if (ping.ipv6) { error = (int)UnsafeNetInfoNativeMethods.Icmp6ParseReplies (buffer.DangerousGetHandle (), (uint)MaxUdpPacket); } else { if (ComNetOS.IsPostWin2K) { error = (int)UnsafeNetInfoNativeMethods.IcmpParseReplies (buffer.DangerousGetHandle (), (uint)MaxUdpPacket); } else{ error = (int)UnsafeIcmpNativeMethods.IcmpParseReplies (buffer.DangerousGetHandle (), (uint)MaxUdpPacket); } } //looks like we get a lot of false failures here //if (error == 0){ // error = Marshal.GetLastWin32Error(); //if (error != 0) { // throw new PingException(error); looks like we get false failures here // if the status code isn't success. //seems to be timing related // } //} //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); } } } // 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); } catch { PingException pe = new PingException(SR.GetString(SR.net_ping), new Exception(SR.GetString(SR.net_nonClsCompliantException))); eventArgs = new PingCompletedEventArgs (null,pe, false, asyncOp.UserSuppliedState); } finally { ping.FreeUnmanagedStructures (); ping.inAsyncCall = false; } if (cancelled) { eventArgs = new PingCompletedEventArgs (null, null, true, asyncOp.UserSuppliedState); } asyncOp.PostOperationCompleted (onPingCompletedDelegate, eventArgs); } //private callback invoked when downlevel send succeeds private static void PingSendCallback (IAsyncResult result) { Ping ping = (Ping)(result.AsyncState); PingCompletedEventArgs eventArgs = null; try { ping.pingSocket.EndSendTo (result); PingReply reply = null; if (!ping.cancelled) { // call blocking receive so we timeout normally. EndPoint endPoint = new IPEndPoint (0, 0); int bytesReceived = 0; while (true) { bytesReceived = ping.pingSocket.ReceiveFrom (ping.downlevelReplyBuffer, ref endPoint); if (CorrectPacket(ping.downlevelReplyBuffer,ping.packet)) { break; } if ((System.Environment.TickCount - ping.startTime) > ping.llTimeout) { reply = new PingReply(IPStatus.TimedOut); break; } } int rttTime = System.Environment.TickCount - ping.startTime; // stop timing if (reply == null) { reply = new PingReply (ping.downlevelReplyBuffer, bytesReceived, ((IPEndPoint)endPoint).Address, rttTime); } //construct the reply eventArgs = new PingCompletedEventArgs (reply, null, false, ping.asyncOp.UserSuppliedState); } } // in case of failure, create a failed event arg catch (Exception e) { PingReply reply = null; PingException pe = null; SocketException e2 = e as SocketException; if (e2 != null) { //timed out if (e2.ErrorCode == TimeoutErrorCode) { reply = new PingReply(IPStatus.TimedOut); } //buffer is too big else if (e2.ErrorCode == PacketTooBigErrorCode) { reply = new PingReply(IPStatus.PacketTooBig); } } if (reply == null) { pe = new PingException(SR.GetString(SR.net_ping), e); } eventArgs = new PingCompletedEventArgs (reply, pe, false, ping.asyncOp.UserSuppliedState); } catch { PingException pe = new PingException(SR.GetString(SR.net_ping), new Exception(SR.GetString(SR.net_nonClsCompliantException))); eventArgs = new PingCompletedEventArgs (null, pe, false, ping.asyncOp.UserSuppliedState); } //otherwise, create real one try { if (ping.cancelled) { eventArgs = new PingCompletedEventArgs (null, null, true, ping.asyncOp.UserSuppliedState); } ping.asyncOp.PostOperationCompleted (ping.onPingCompletedDelegate, eventArgs); } finally { ping.inAsyncCall = false; } } /* private static void PingRecvCallback (IAsyncResult result) { Ping ping = (Ping)result.AsyncState; EndPoint endPoint = new IPEndPoint (0, 0); int bytesReceived = ping.pingSocket.EndReceiveFrom (result, ref endPoint); PingReply reply = new PingReply (ping.downlevelReplyBuffer, bytesReceived, ((IPEndPoint)endPoint).Address, 0); ping.inAsyncCall = false; } */ 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; 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"); } if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any)) { throw new ArgumentException(SR.GetString(SR.net_invalid_ip_addr), "address"); } if (inAsyncCall == true) { 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); } catch { throw new PingException(SR.GetString(SR.net_ping), new Exception(SR.GetString(SR.net_nonClsCompliantException))); } } [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 == true) { 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; 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"); } if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any)) { throw new ArgumentException(SR.GetString(SR.net_invalid_ip_addr), "address"); } if (inAsyncCall == true) { 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; asyncOp = AsyncOperationManager.CreateOperation (userToken); InternalSend (addressSnapshot, buffer, timeout, options, true); } catch(Exception e){ inAsyncCall = false; throw new PingException(SR.GetString(SR.net_ping), e); } catch { inAsyncCall = false; throw new PingException(SR.GetString(SR.net_ping), new Exception(SR.GetString(SR.net_nonClsCompliantException))); } } 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); } catch { PingException pe = new PingException(SR.GetString(SR.net_ping), new Exception(SR.GetString(SR.net_nonClsCompliantException))); 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) { inAsyncCall = async; cancelled = false; //for llTimeout) { return new PingReply(IPStatus.TimedOut); } } //construct and return the reply rttTime = System.Environment.TickCount - startTime; // stop timing return new PingReply (downlevelReplyBuffer, bytesReceived, ((IPEndPoint)endPoint).Address, rttTime); } catch (SocketException e) { //timed out, [....] is implied if (e.ErrorCode == TimeoutErrorCode) { return new PingReply(IPStatus.TimedOut); } //buffer too big else if (e.ErrorCode == PacketTooBigErrorCode) { PingReply reply = new PingReply(IPStatus.PacketTooBig); if (!async) { return reply; } PingCompletedEventArgs eventArgs = new PingCompletedEventArgs(reply,null, false, asyncOp.UserSuppliedState); asyncOp.PostOperationCompleted (onPingCompletedDelegate, eventArgs); return null; } else throw e; } } // 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 > 16) + (total & 0xffff); total += (total >> 16); return(~total); } //converts the structure into a byte array internal byte[] GetBytes() { byte[] bytes = new byte[buffer.Length + 8]; byte[] b_cksum = BitConverter.GetBytes (checkSum); byte[] b_id = BitConverter.GetBytes (Identifier); byte[] b_seq = BitConverter.GetBytes (sequenceNumber); bytes[0] = type ; bytes[1] = subCode ; Array.Copy ( b_cksum , 0 , bytes , 2 , 2 ) ; Array.Copy ( b_id , 0 , bytes , 4 , 2 ) ; Array.Copy (b_seq, 0, bytes, 6, 2); Array.Copy ( buffer , 0 , bytes , 8 , buffer . Length ) ; return bytes; } } // class IcmpPacket } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- FindCriteriaApril2005.cs
- RefExpr.cs
- XmlSiteMapProvider.cs
- WebContext.cs
- ConstNode.cs
- SynchronizedDispatch.cs
- AdPostCacheSubstitution.cs
- ReadOnlyCollectionBase.cs
- MenuBindingsEditor.cs
- CreateUserErrorEventArgs.cs
- InputLanguage.cs
- ZipIOEndOfCentralDirectoryBlock.cs
- TreeNodeBindingCollection.cs
- MemberAccessException.cs
- PeerCollaborationPermission.cs
- SQLByteStorage.cs
- HtmlControl.cs
- InvocationExpression.cs
- IImplicitResourceProvider.cs
- OpenFileDialog.cs
- SystemIPInterfaceProperties.cs
- CapabilitiesRule.cs
- GenericIdentity.cs
- TreeNodeBindingCollection.cs
- MeshGeometry3D.cs
- CodeStatementCollection.cs
- RepeaterCommandEventArgs.cs
- NavigationPropertyEmitter.cs
- RegisterInfo.cs
- HttpPostProtocolReflector.cs
- Int32RectValueSerializer.cs
- HtmlInputRadioButton.cs
- PipelineModuleStepContainer.cs
- DataFormats.cs
- _SpnDictionary.cs
- _Win32.cs
- LinkedList.cs
- QilSortKey.cs
- XmlQueryStaticData.cs
- ModuleBuilder.cs
- RoleGroup.cs
- CodeTypeDelegate.cs
- LongValidatorAttribute.cs
- ActivatedMessageQueue.cs
- FontCacheUtil.cs
- URIFormatException.cs
- SpnEndpointIdentity.cs
- StructuredCompositeActivityDesigner.cs
- ProcessModuleCollection.cs
- SourceFileBuildProvider.cs
- LowerCaseStringConverter.cs
- EncoderBestFitFallback.cs
- ControlBindingsCollection.cs
- AsyncPostBackTrigger.cs
- ApplicationServiceHelper.cs
- Container.cs
- SharedConnectionInfo.cs
- ToolStripLabel.cs
- ComplexType.cs
- FloatUtil.cs
- SynchronizedDispatch.cs
- ResourceContainer.cs
- ValidationException.cs
- SliderAutomationPeer.cs
- PersonalizationProviderCollection.cs
- ClientApiGenerator.cs
- GlobalDataBindingHandler.cs
- DocumentSequence.cs
- ControlValuePropertyAttribute.cs
- WebPartExportVerb.cs
- HwndProxyElementProvider.cs
- FacetChecker.cs
- MetadataWorkspace.cs
- CompositeControl.cs
- ProviderMetadata.cs
- SoapReflectionImporter.cs
- PartitionResolver.cs
- EditingCoordinator.cs
- PositiveTimeSpanValidator.cs
- SafeEventLogReadHandle.cs
- StatusBar.cs
- HtmlPhoneCallAdapter.cs
- DiagnosticStrings.cs
- DataTableTypeConverter.cs
- DataGridViewSortCompareEventArgs.cs
- BinaryFormatterSinks.cs
- AuthenticationConfig.cs
- MruCache.cs
- RegexParser.cs
- Verify.cs
- RSAPKCS1KeyExchangeFormatter.cs
- Calendar.cs
- FormsAuthenticationUserCollection.cs
- ProcessThread.cs
- ItemsChangedEventArgs.cs
- MenuRenderer.cs
- ValueConversionAttribute.cs
- ScalarRestriction.cs
- WebPartConnectionCollection.cs
- TextProperties.cs