// 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); } }
private static PingReply CreatePingReplyFromIcmp6EchoReply(Interop.IpHlpApi.Icmp6EchoReply reply, IntPtr dataPtr, int sendSize) { IPAddress address = new IPAddress(reply.Address.Address, reply.Address.ScopeID); IPStatus ipStatus = (IPStatus)reply.Status; // The icmpsendecho IP status codes. long rtt; byte[] buffer; rtt = reply.RoundTripTime; if (ipStatus == IPStatus.Success) { // Only copy the data if we succeed w/ the ping operation. buffer = new byte[sendSize]; Marshal.Copy(IntPtrHelper.Add(dataPtr, 36), buffer, 0, sendSize); } else { buffer = Array.Empty <byte>(); } return(new PingReply(address, default(PingOptions), ipStatus, rtt, buffer)); }