private PingReply ParsePingUtilityOutput(IPAddress address, string output) { long rtt = UnixCommandLinePing.ParseRoundTripTime(output); return(new PingReply( address, null, // Ping utility cannot accommodate these, return null to indicate they were ignored. IPStatus.Success, rtt, Array.Empty <byte>())); // Ping utility doesn't deliver this info. }
private static PingReply ParsePingUtilityOutput(IPAddress address, int exitCode, string stdout) { // Throw timeout for known failure return codes from ping functions. if (exitCode == 1 || exitCode == 2) { // TTL exceeded may have occured if (TryParseTtlExceeded(stdout, out PingReply? reply)) { return(reply !); } // otherwise assume timeout return(CreatePingReply(IPStatus.TimedOut)); } // On success, report RTT long rtt = UnixCommandLinePing.ParseRoundTripTime(stdout); return(CreatePingReply(IPStatus.Success, address, rtt)); }
private async Task <PingReply> SendWithPingUtility(IPAddress address, byte[] buffer, int timeout, PingOptions options) { bool isIpv4 = address.AddressFamily == AddressFamily.InterNetwork; string pingExecutable = isIpv4 ? UnixCommandLinePing.Ping4UtilityPath : UnixCommandLinePing.Ping6UtilityPath; if (pingExecutable == null) { throw new PlatformNotSupportedException(SR.net_ping_utility_not_found); } string processArgs = UnixCommandLinePing.ConstructCommandLine(buffer.Length, address.ToString(), isIpv4); ProcessStartInfo psi = new ProcessStartInfo(pingExecutable, processArgs); psi.RedirectStandardOutput = true; psi.RedirectStandardError = true; Process p = new Process() { StartInfo = psi }; var processCompletion = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously); p.EnableRaisingEvents = true; p.Exited += (s, e) => processCompletion.SetResult(true); p.Start(); var cts = new CancellationTokenSource(); Task timeoutTask = Task.Delay(timeout, cts.Token); Task finished = await Task.WhenAny(processCompletion.Task, timeoutTask).ConfigureAwait(false); if (finished == timeoutTask && !p.HasExited) { // Try to kill the ping process if it didn't return. If it is already in the process of exiting, a Win32Exception will be thrown. try { p.Kill(); } catch (Win32Exception) { } return(CreateTimedOutPingReply()); } else { cts.Cancel(); if (p.ExitCode != 0) { // This means no reply was received, although transmission may have been successful. return(CreateTimedOutPingReply()); } try { string output = await p.StandardOutput.ReadToEndAsync().ConfigureAwait(false); long rtt = UnixCommandLinePing.ParseRoundTripTime(output); return(new PingReply( address, null, // Ping utility cannot accomodate these, return null to indicate they were ignored. IPStatus.Success, rtt, Array.Empty <byte>())); // Ping utility doesn't deliver this info. } catch (Exception) { // If the standard output cannot be successfully parsed, throw a generic PingException. throw new PingException(SR.net_ping); } } }