Author Topic: [C#] TraceRoute Implementation  (Read 768 times)

0 Members and 1 Guest are viewing this topic.

Offline xor

  • Peasant
  • *
  • Posts: 59
  • Cookies: 32
    • View Profile
[C#] TraceRoute Implementation
« on: May 06, 2015, 08:04:26 am »

TODO: Summary explanation to come later. Code comments work for now.




Code: [Select]
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;


namespace com.network_junkies.networking
{
    public class TraceRouteEntry
    {
        /// <summary>
        /// The hop id. Represents the number of the hop.
        /// </summary>
        public int HopID { get; set; }


        /// <summary>
        /// The IP address.
        /// </summary>
        public string Address { get; set; }


        /// <summary>
        /// The hostname
        /// </summary>
        public string Hostname { get; set; }


        /// <summary>
        /// The reply time it took for the host to receive and reply to the request in milliseconds.
        /// </summary>
        public long ReplyTime { get; set; }


        /// <summary>
        /// The reply status of the request.
        /// </summary>
        public IPStatus ReplyStatus { get; set; }


        public override string ToString()
        {
            return string.Format("{0} | {1} | {2}",
                HopID,
                string.IsNullOrEmpty(Hostname) ? Address : Hostname + "[" + Address + "]",
                ReplyStatus == IPStatus.TimedOut ? "Request Timed Out." : ReplyTime.ToString() + " ms"
                );
        }


    }


    public static class TraceRoute
    {
        public static IEnumerable<TraceRouteEntry> Tracert(IPAddress address, int maxHops, int timeout, bool resolveHost = false)
        {
            // Max hops should be at least one or else there won't be any data to return.
            if (maxHops < 1)
                throw new ArgumentException("Max hops can't be lower than 1.");


            // Ensure that the timeout is not set to 0 or a negative number.
            if (timeout < 1)
                throw new ArgumentException("Timeout value must be higher than 0.");




            var ping = new Ping();
            var pingOptions = new PingOptions(1, true);
            var pingReplyTime = new Stopwatch();
            PingReply reply;


            do
            {
                pingReplyTime.Start();
                reply = ping.Send(address, timeout, new byte[] {0}, pingOptions);
                pingReplyTime.Stop();


                var hostname = String.Empty;


                if (reply != null)
                {
                    if (reply.Address != null && resolveHost)
                    {
                        try
                        {
                            hostname = Dns.GetHostEntry(reply.Address).HostName;
                        }
                        catch (SocketException)
                        {
                        }
                    }
                }


                yield return new TraceRouteEntry()
                {
                    HopID = pingOptions.Ttl,
                    Address = reply.Address == null ? "Timeout" : reply.Address.ToString(),
                    Hostname = String.IsNullOrEmpty(hostname) ? "" : hostname,
                    ReplyTime = pingReplyTime.ElapsedMilliseconds,
                    ReplyStatus = reply.Status
                };


                pingOptions.Ttl++;
                pingReplyTime.Reset();
            } while (reply.Status != IPStatus.Success && pingOptions.Ttl <= maxHops);
        }
    }


}