Created
July 1, 2020 12:14
-
-
Save nathan130200/21bae68b6353468755aaf3f7d5669a72 to your computer and use it in GitHub Desktop.
.NET Async tracert with events.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Net.Http; | |
namespace System.NetworkInformation | |
{ | |
public class TraceRouteEventArgs | |
{ | |
public TraceRoute Tracer { get; internal set; } | |
} | |
public class TraceRoutedEventArgs : TraceRouteEventArgs | |
{ | |
public int Ttl { get; internal set; } | |
public string Address { get; internal set; } | |
public long Rtt { get; internal set; } | |
public bool TimedOutOrExpired { get; internal set; } | |
} | |
public class TraceRouteErrorEventArgs : TraceRouteEventArgs | |
{ | |
public Exception Exception { get; internal set; } | |
} | |
public delegate Task TraceRouteCallback(TraceRouteEventArgs e); | |
public delegate Task TraceRoutedCallback(TraceRoutedEventArgs e); | |
public delegate Task TraceRouteErrorCallback(TraceRouteErrorEventArgs e); | |
public class TraceRoute : IDisposable | |
{ | |
public event TraceRoutedCallback OnTrace; | |
public event TraceRouteCallback OnCompleted; | |
public event TraceRouteErrorCallback OnError; | |
static readonly int Timeout = 10_000; | |
protected Ping _ping; | |
protected string _host; | |
TraceRoute(string hostname) | |
{ | |
this._host = hostname; | |
this._ping = new Ping(); | |
} | |
public static TraceRoute CreateNew(string hostNameOrAddress) | |
=> new TraceRoute(hostNameOrAddress); | |
public async Task StartAsync() | |
{ | |
var buffer = new byte[32]; | |
using (var rng = RandomNumberGenerator.Create()) | |
rng.GetBytes(buffer); | |
var errored = false; | |
for (int i = 1; i <= 32; i++) | |
{ | |
try | |
{ | |
var options = new PingOptions(i, true); | |
var reply = await this._ping.SendPingAsync(this._host, Timeout, buffer, options); | |
if (reply.Status == IPStatus.Success || reply.Status == IPStatus.TtlExpired) | |
{ | |
if (this.OnTrace != null) | |
await this.OnTrace(new TraceRoutedEventArgs { Tracer = this, Address = reply.Address.ToString(), Rtt = reply.RoundtripTime, Ttl = i }) | |
.ConfigureAwait(false); | |
} | |
else | |
{ | |
if (this.OnTrace != null) | |
await this.OnTrace(new TraceRoutedEventArgs { Tracer = this, Address = reply.Address.ToString(), Rtt = reply.RoundtripTime, Ttl = i, TimedOutOrExpired = true }) | |
.ConfigureAwait(false); | |
} | |
if (reply.Status != IPStatus.TtlExpired && reply.Status != IPStatus.TimedOut) | |
break; | |
} | |
catch (Exception ex) | |
{ | |
errored = true; | |
if (this.OnError != null) | |
await this.OnError(new TraceRouteErrorEventArgs { Exception = ex, Tracer = this }).ConfigureAwait(false); | |
} | |
} | |
if (!errored) | |
{ | |
if (this.OnCompleted != null) | |
await this.OnCompleted(new TraceRouteEventArgs { Tracer = this }) | |
.ConfigureAwait(false); | |
} | |
} | |
public void Dispose() | |
{ | |
if (this._ping != null) | |
{ | |
this._ping.Dispose(); | |
this._ping = null; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment