private static PingReply CreatePingReplyFromIcmpEchoReply(Interop.IpHlpApi.IcmpEchoReply reply) { const int DontFragmentFlag = 2; IPAddress address = new IPAddress(reply.address); IPStatus ipStatus = (IPStatus)reply.status; // The icmpsendecho IP status codes. long rtt; PingOptions options; byte[] buffer; rtt = reply.roundTripTime; if (ipStatus == IPStatus.Success) { // Only copy the data if we succeed w/ the ping operation. options = new PingOptions(reply.options.ttl, (reply.options.flags & DontFragmentFlag) > 0); buffer = new byte[reply.dataSize]; Marshal.Copy(reply.data, buffer, 0, reply.dataSize); } else { options = default(PingOptions); buffer = Array.Empty <byte>(); } return(new PingReply(address, options, ipStatus, rtt, buffer)); }
// Private callback invoked when icmpsendecho APIs succeed. private void PingCallback() { TaskCompletionSource <PingReply> tcs = _taskCompletionSource; _taskCompletionSource = null; PingReply reply = null; Exception error = null; bool canceled = false; try { lock (_lockObject) { canceled = _canceled; // Parse reply buffer. SafeLocalAllocHandle buffer = _replyBuffer; // Marshals and constructs new reply. if (_ipv6) { Interop.IpHlpApi.Icmp6EchoReply icmp6Reply = Marshal.PtrToStructure <Interop.IpHlpApi.Icmp6EchoReply>(buffer.DangerousGetHandle()); reply = CreatePingReplyFromIcmp6EchoReply(icmp6Reply, buffer.DangerousGetHandle(), _sendSize); } else { Interop.IpHlpApi.IcmpEchoReply icmpReply = Marshal.PtrToStructure <Interop.IpHlpApi.IcmpEchoReply>(buffer.DangerousGetHandle()); reply = CreatePingReplyFromIcmpEchoReply(icmpReply); } } } catch (Exception e) { // In case of failure, create a failed event arg. error = new PingException(SR.net_ping, e); } finally { FreeUnmanagedStructures(); UnregisterWaitHandle(); Finish(); } // Once we've called Finish, complete the task if (canceled) { tcs.SetCanceled(); } else if (reply != null) { tcs.SetResult(reply); } else { Debug.Assert(error != null); tcs.SetException(error); } }