private int SendEcho(IPAddress address, byte[] buffer, int timeout, PingOptions options, bool isAsync) { Interop.IpHlpApi.IPOptions ipOptions = new Interop.IpHlpApi.IPOptions(options); if (!_ipv6) { return((int)Interop.IpHlpApi.IcmpSendEcho2( _handlePingV4, GetWaitHandle(isAsync), IntPtr.Zero, IntPtr.Zero, #pragma warning disable CS0618 // Address is marked obsolete (uint)address.Address, #pragma warning restore CS0618 _requestBuffer, (ushort)buffer.Length, ref ipOptions, _replyBuffer, MaxUdpPacket, (uint)timeout)); } IPEndPoint ep = new IPEndPoint(address, 0); Internals.SocketAddress remoteAddr = IPEndPointExtensions.Serialize(ep); byte[] sourceAddr = new byte[28]; return((int)Interop.IpHlpApi.Icmp6SendEcho2( _handlePingV6, GetWaitHandle(isAsync), IntPtr.Zero, IntPtr.Zero, sourceAddr, remoteAddr.Buffer, _requestBuffer, (ushort)buffer.Length, ref ipOptions, _replyBuffer, MaxUdpPacket, (uint)timeout)); }
// Any exceptions that escape synchronously will be caught by the caller and wrapped in a PingException. // We do not need to or want to capture such exceptions into the returned task. private Task<PingReply> SendPingAsyncCore(IPAddress address, byte[] buffer, int timeout, PingOptions options) { var tcs = new TaskCompletionSource<PingReply>(); _taskCompletionSource = tcs; _ipv6 = (address.AddressFamily == AddressFamily.InterNetworkV6); _sendSize = buffer.Length; // Get and cache correct handle. if (!_ipv6 && _handlePingV4 == null) { _handlePingV4 = Interop.IpHlpApi.IcmpCreateFile(); if (_handlePingV4.IsInvalid) { _handlePingV4 = null; throw new Win32Exception(); // Gets last error. } } else if (_ipv6 && _handlePingV6 == null) { _handlePingV6 = Interop.IpHlpApi.Icmp6CreateFile(); if (_handlePingV6.IsInvalid) { _handlePingV6 = null; throw new Win32Exception(); // Gets last error. } } var ipOptions = new Interop.IpHlpApi.IPOptions(options); if (_replyBuffer == null) { _replyBuffer = SafeLocalAllocHandle.LocalAlloc(MaxUdpPacket); } // Queue the event. int error; try { if (_pingEvent == null) { _pingEvent = new ManualResetEvent(false); } else { _pingEvent.Reset(); } _registeredWait = ThreadPool.RegisterWaitForSingleObject(_pingEvent, (state, _) => ((Ping)state).PingCallback(), this, -1, true); SetUnmanagedStructures(buffer); if (!_ipv6) { SafeWaitHandle pingEventSafeWaitHandle = _pingEvent.GetSafeWaitHandle(); error = (int)Interop.IpHlpApi.IcmpSendEcho2( _handlePingV4, pingEventSafeWaitHandle, IntPtr.Zero, IntPtr.Zero, (uint)address.GetAddress(), _requestBuffer, (ushort)buffer.Length, ref ipOptions, _replyBuffer, MaxUdpPacket, (uint)timeout); } else { IPEndPoint ep = new IPEndPoint(address, 0); Internals.SocketAddress remoteAddr = IPEndPointExtensions.Serialize(ep); byte[] sourceAddr = new byte[28]; SafeWaitHandle pingEventSafeWaitHandle = _pingEvent.GetSafeWaitHandle(); error = (int)Interop.IpHlpApi.Icmp6SendEcho2( _handlePingV6, pingEventSafeWaitHandle, IntPtr.Zero, IntPtr.Zero, sourceAddr, remoteAddr.Buffer, _requestBuffer, (ushort)buffer.Length, ref ipOptions, _replyBuffer, MaxUdpPacket, (uint)timeout); } } catch { UnregisterWaitHandle(); throw; } if (error == 0) { error = Marshal.GetLastWin32Error(); // Only skip Async IO Pending error value. if (error != Interop.IpHlpApi.ERROR_IO_PENDING) { // Cleanup. FreeUnmanagedStructures(); UnregisterWaitHandle(); throw new Win32Exception(error); } } return tcs.Task; }
// Any exceptions that escape synchronously will be caught by the caller and wrapped in a PingException. // We do not need to or want to capture such exceptions into the returned task. private Task <PingReply> SendPingAsyncCore(IPAddress address, byte[] buffer, int timeout, PingOptions options) { var tcs = new TaskCompletionSource <PingReply>(); _taskCompletionSource = tcs; _ipv6 = (address.AddressFamily == AddressFamily.InterNetworkV6); _sendSize = buffer.Length; // Get and cache correct handle. if (!_ipv6 && _handlePingV4 == null) { _handlePingV4 = Interop.IpHlpApi.IcmpCreateFile(); if (_handlePingV4.IsInvalid) { _handlePingV4 = null; throw new Win32Exception(); // Gets last error. } } else if (_ipv6 && _handlePingV6 == null) { _handlePingV6 = Interop.IpHlpApi.Icmp6CreateFile(); if (_handlePingV6.IsInvalid) { _handlePingV6 = null; throw new Win32Exception(); // Gets last error. } } var ipOptions = new Interop.IpHlpApi.IPOptions(options); if (_replyBuffer == null) { _replyBuffer = SafeLocalAllocHandle.LocalAlloc(MaxUdpPacket); } // Queue the event. int error; try { if (_pingEvent == null) { _pingEvent = new ManualResetEvent(false); } else { _pingEvent.Reset(); } _registeredWait = ThreadPool.RegisterWaitForSingleObject(_pingEvent, (state, _) => ((Ping)state).PingCallback(), this, -1, true); SetUnmanagedStructures(buffer); if (!_ipv6) { SafeWaitHandle pingEventSafeWaitHandle = _pingEvent.GetSafeWaitHandle(); error = (int)Interop.IpHlpApi.IcmpSendEcho2( _handlePingV4, pingEventSafeWaitHandle, IntPtr.Zero, IntPtr.Zero, (uint)address.GetAddress(), _requestBuffer, (ushort)buffer.Length, ref ipOptions, _replyBuffer, MaxUdpPacket, (uint)timeout); } else { IPEndPoint ep = new IPEndPoint(address, 0); Internals.SocketAddress remoteAddr = IPEndPointExtensions.Serialize(ep); byte[] sourceAddr = new byte[28]; SafeWaitHandle pingEventSafeWaitHandle = _pingEvent.GetSafeWaitHandle(); error = (int)Interop.IpHlpApi.Icmp6SendEcho2( _handlePingV6, pingEventSafeWaitHandle, IntPtr.Zero, IntPtr.Zero, sourceAddr, remoteAddr.Buffer, _requestBuffer, (ushort)buffer.Length, ref ipOptions, _replyBuffer, MaxUdpPacket, (uint)timeout); } } catch { UnregisterWaitHandle(); throw; } if (error == 0) { error = Marshal.GetLastWin32Error(); // Only skip Async IO Pending error value. if (error != Interop.IpHlpApi.ERROR_IO_PENDING) { // Cleanup. FreeUnmanagedStructures(); UnregisterWaitHandle(); throw new Win32Exception(error); } } return(tcs.Task); }
private PingReply InternalSend(IPAddress address, byte[] buffer, int timeout, PingOptions options, bool async) { _ipv6 = (address.AddressFamily == AddressFamily.InterNetworkV6) ? true : false; _sendSize = buffer.Length; // Get and cache correct handle. if (!_ipv6 && _handlePingV4 == null) { _handlePingV4 = Interop.IpHlpApi.IcmpCreateFile(); if (_handlePingV4.IsInvalid) { _handlePingV4 = null; throw new Win32Exception(); // Gets last error. } } else if (_ipv6 && _handlePingV6 == null) { _handlePingV6 = Interop.IpHlpApi.Icmp6CreateFile(); if (_handlePingV6.IsInvalid) { _handlePingV6 = null; throw new Win32Exception(); // Gets last error. } } var ipOptions = new Interop.IpHlpApi.IPOptions(options); if (_replyBuffer == null) { _replyBuffer = SafeLocalAllocHandle.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); } SetUnmanagedStructures(buffer); if (!_ipv6) { if (async) { SafeWaitHandle pingEventSafeWaitHandle = pingEvent.GetSafeWaitHandle(); error = (int)Interop.IpHlpApi.IcmpSendEcho2( _handlePingV4, pingEventSafeWaitHandle, IntPtr.Zero, IntPtr.Zero, (uint)address.GetAddress(), _requestBuffer, (ushort)buffer.Length, ref ipOptions, _replyBuffer, MaxUdpPacket, (uint)timeout); } else { error = (int)Interop.IpHlpApi.IcmpSendEcho2( _handlePingV4, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, (uint)address.GetAddress(), _requestBuffer, (ushort)buffer.Length, ref ipOptions, _replyBuffer, MaxUdpPacket, (uint)timeout); } } else { IPEndPoint ep = new IPEndPoint(address, 0); Internals.SocketAddress remoteAddr = IPEndPointExtensions.Serialize(ep); byte[] sourceAddr = new byte[28]; if (async) { SafeWaitHandle pingEventSafeWaitHandle = pingEvent.GetSafeWaitHandle(); error = (int)Interop.IpHlpApi.Icmp6SendEcho2( _handlePingV6, pingEventSafeWaitHandle, IntPtr.Zero, IntPtr.Zero, sourceAddr, remoteAddr.Buffer, _requestBuffer, (ushort)buffer.Length, ref ipOptions, _replyBuffer, MaxUdpPacket, (uint)timeout); } else { error = (int)Interop.IpHlpApi.Icmp6SendEcho2( _handlePingV6, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, sourceAddr, remoteAddr.Buffer, _requestBuffer, (ushort)buffer.Length, ref ipOptions, _replyBuffer, MaxUdpPacket, (uint)timeout); } } } catch { UnregisterWaitHandle(); throw; } if (error == 0) { error = Marshal.GetLastWin32Error(); // Only skip Async IO Pending error value. if (async && error == Interop.IpHlpApi.ERROR_IO_PENDING) { // Expected async return value. return(null); } // Cleanup. FreeUnmanagedStructures(); UnregisterWaitHandle(); if (async || // No IPStatus async errors. error < (int)IPStatus.DestinationNetworkUnreachable || // Min error > (int)IPStatus.DestinationScopeMismatch) // Max or Out of IPStatus range. { throw new Win32Exception(error); } return(new PingReply((IPStatus)error)); // Synchronous IPStatus errors. } if (async) { return(null); } FreeUnmanagedStructures(); PingReply reply; if (_ipv6) { Interop.IpHlpApi.Icmp6EchoReply icmp6Reply = Marshal.PtrToStructure <Interop.IpHlpApi.Icmp6EchoReply>(_replyBuffer.DangerousGetHandle()); reply = new PingReply(icmp6Reply, _replyBuffer.DangerousGetHandle(), _sendSize); } else { Interop.IpHlpApi.IcmpEchoReply icmpReply = Marshal.PtrToStructure <Interop.IpHlpApi.IcmpEchoReply>(_replyBuffer.DangerousGetHandle()); 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); }
private PingReply InternalSend(IPAddress address, byte[] buffer, int timeout, PingOptions options, bool async) { _ipv6 = (address.AddressFamily == AddressFamily.InterNetworkV6) ? true : false; _sendSize = buffer.Length; // Get and cache correct handle. if (!_ipv6 && _handlePingV4 == null) { _handlePingV4 = Interop.IpHlpApi.IcmpCreateFile(); if (_handlePingV4.IsInvalid) { _handlePingV4 = null; throw new Win32Exception(); // Gets last error. } } else if (_ipv6 && _handlePingV6 == null) { _handlePingV6 = Interop.IpHlpApi.Icmp6CreateFile(); if (_handlePingV6.IsInvalid) { _handlePingV6 = null; throw new Win32Exception(); // Gets last error. } } var ipOptions = new Interop.IpHlpApi.IPOptions(options); if (_replyBuffer == null) { _replyBuffer = SafeLocalAllocHandle.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); } SetUnmanagedStructures(buffer); if (!_ipv6) { if (async) { SafeWaitHandle pingEventSafeWaitHandle = pingEvent.GetSafeWaitHandle(); error = (int)Interop.IpHlpApi.IcmpSendEcho2( _handlePingV4, pingEventSafeWaitHandle, IntPtr.Zero, IntPtr.Zero, (uint)address.GetAddress(), _requestBuffer, (ushort)buffer.Length, ref ipOptions, _replyBuffer, MaxUdpPacket, (uint)timeout); } else { error = (int)Interop.IpHlpApi.IcmpSendEcho2( _handlePingV4, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, (uint)address.GetAddress(), _requestBuffer, (ushort)buffer.Length, ref ipOptions, _replyBuffer, MaxUdpPacket, (uint)timeout); } } else { IPEndPoint ep = new IPEndPoint(address, 0); Internals.SocketAddress remoteAddr = IPEndPointExtensions.Serialize(ep); byte[] sourceAddr = new byte[28]; if (async) { SafeWaitHandle pingEventSafeWaitHandle = pingEvent.GetSafeWaitHandle(); error = (int)Interop.IpHlpApi.Icmp6SendEcho2( _handlePingV6, pingEventSafeWaitHandle, IntPtr.Zero, IntPtr.Zero, sourceAddr, remoteAddr.Buffer, _requestBuffer, (ushort)buffer.Length, ref ipOptions, _replyBuffer, MaxUdpPacket, (uint)timeout); } else { error = (int)Interop.IpHlpApi.Icmp6SendEcho2( _handlePingV6, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, sourceAddr, remoteAddr.Buffer, _requestBuffer, (ushort)buffer.Length, ref ipOptions, _replyBuffer, MaxUdpPacket, (uint)timeout); } } } catch { UnregisterWaitHandle(); throw; } if (error == 0) { error = Marshal.GetLastWin32Error(); // Only skip Async IO Pending error value. if (async && error == Interop.IpHlpApi.ERROR_IO_PENDING) { // Expected async return value. return null; } // Cleanup. FreeUnmanagedStructures(); UnregisterWaitHandle(); if (async // No IPStatus async errors. || error < (int)IPStatus.DestinationNetworkUnreachable // Min || error > (int)IPStatus.DestinationScopeMismatch) // Max or Out of IPStatus range. { throw new Win32Exception(error); } return new PingReply((IPStatus)error); // Synchronous IPStatus errors. } if (async) { return null; } FreeUnmanagedStructures(); PingReply reply; if (_ipv6) { Interop.IpHlpApi.Icmp6EchoReply icmp6Reply = Marshal.PtrToStructure<Interop.IpHlpApi.Icmp6EchoReply>(_replyBuffer.DangerousGetHandle()); reply = new PingReply(icmp6Reply, _replyBuffer.DangerousGetHandle(), _sendSize); } else { Interop.IpHlpApi.IcmpEchoReply icmpReply = Marshal.PtrToStructure<Interop.IpHlpApi.IcmpEchoReply>(_replyBuffer.DangerousGetHandle()); 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; }
internal PingOptions(Interop.IpHlpApi.IPOptions options) { _ttl = options.ttl; _dontFragment = ((options.flags & DontFragmentFlag) > 0 ? true : false); }