Skip to content

Instantly share code, notes, and snippets.

@nathan130200
Created July 1, 2020 12:14
Show Gist options
  • Save nathan130200/21bae68b6353468755aaf3f7d5669a72 to your computer and use it in GitHub Desktop.
Save nathan130200/21bae68b6353468755aaf3f7d5669a72 to your computer and use it in GitHub Desktop.
.NET Async tracert with events.
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