From 0bc725d1fce2c2b93ce1823ea213c41ddb9dfc2a Mon Sep 17 00:00:00 2001 From: karashiiro <49822414+karashiiro@users.noreply.github.com> Date: Tue, 1 Feb 2022 12:33:58 -0800 Subject: [PATCH] Add IpHlpApi tracker, modify base PingTracker (#41) --- .../PingTrackers/AggregatePingTracker.cs | 20 ++++-- .../PingTrackers/ComponentModelPingTracker.cs | 3 +- .../PingTrackers/IpHlpApiPingTracker.cs | 70 +++++++++++++++++++ PingPlugin/PingTrackers/PingTracker.cs | 3 +- 4 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 PingPlugin/PingTrackers/IpHlpApiPingTracker.cs diff --git a/PingPlugin/PingTrackers/AggregatePingTracker.cs b/PingPlugin/PingTrackers/AggregatePingTracker.cs index 799cdc5..62cc0e5 100644 --- a/PingPlugin/PingTrackers/AggregatePingTracker.cs +++ b/PingPlugin/PingTrackers/AggregatePingTracker.cs @@ -7,6 +7,9 @@ namespace PingPlugin.PingTrackers { public class AggregatePingTracker : PingTracker { + private const string COMTrackerKey = "COM"; + private const string IpHlpApiTrackerKey = "IpHlpApi"; + private readonly IDictionary trackerInfos; private readonly DecisionTree decisionTree; @@ -14,13 +17,21 @@ public AggregatePingTracker(PingConfiguration config, ClientState clientState) : { // Define trackers this.trackerInfos = new Dictionary(); - - var comPing = new ComponentModelPingTracker(config, clientState) { Verbose = false }; - RegisterTracker("COM", comPing); + + RegisterTracker(COMTrackerKey, new ComponentModelPingTracker(config, clientState) { Verbose = false }); + RegisterTracker(IpHlpApiTrackerKey, new IpHlpApiPingTracker(config, clientState) { Verbose = false }); // Create decision tree to solve tracker selection problem this.decisionTree = new DecisionTree( - () => TreeResult.FromObject(this.trackerInfos["COM"])); + () => + { + if (this.trackerInfos[COMTrackerKey].LastRTT < this.trackerInfos[IpHlpApiTrackerKey].LastRTT) + { + return TreeResult.FromObject(this.trackerInfos[COMTrackerKey]); + } + + return TreeResult.FromObject(this.trackerInfos[IpHlpApiTrackerKey]); + }); } protected override async Task PingLoop(CancellationToken token) @@ -35,7 +46,6 @@ protected override async Task PingLoop(CancellationToken token) { // Process result NextRTTCalculation(bestTracker.LastRTT); - SendMessage(); } } diff --git a/PingPlugin/PingTrackers/ComponentModelPingTracker.cs b/PingPlugin/PingTrackers/ComponentModelPingTracker.cs index b02ea5d..f96ad45 100644 --- a/PingPlugin/PingTrackers/ComponentModelPingTracker.cs +++ b/PingPlugin/PingTrackers/ComponentModelPingTracker.cs @@ -22,8 +22,9 @@ protected override async Task PingLoop(CancellationToken token) { var pingReply = await this.ping.SendPingAsync(SeAddress); if (pingReply.Status == IPStatus.Success && pingReply.RoundtripTime > 0) + { NextRTTCalculation((ulong)pingReply.RoundtripTime); - SendMessage(); + } } await Task.Delay(3000, token); diff --git a/PingPlugin/PingTrackers/IpHlpApiPingTracker.cs b/PingPlugin/PingTrackers/IpHlpApiPingTracker.cs new file mode 100644 index 0000000..3af95e8 --- /dev/null +++ b/PingPlugin/PingTrackers/IpHlpApiPingTracker.cs @@ -0,0 +1,70 @@ +using System; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using Dalamud.Game.ClientState; + +namespace PingPlugin.PingTrackers +{ + public class IpHlpApiPingTracker : PingTracker + { + public IpHlpApiPingTracker(PingConfiguration config, ClientState clientState) : base(config, clientState) + { + } + + protected override async Task PingLoop(CancellationToken token) + { + while (!token.IsCancellationRequested) + { + if (SeAddress != null) + { + var addressRaw = BitConverter.ToUInt64(SeAddress.GetAddressBytes()); + var rtt = GetAddressLastRTT(addressRaw); + var error = (WinError)Marshal.GetLastWin32Error(); + if (error == WinError.NO_ERROR) + { + NextRTTCalculation(rtt); + } + } + + await Task.Delay(3000, token); + } + } + + private static ulong GetAddressLastRTT(ulong address) + { + var hopCount = 0UL; + var rtt = 0UL; + GetRTTAndHopCount(address, ref hopCount, 51, ref rtt); + return rtt; + } + + [DllImport("Iphlpapi.dll", EntryPoint = "GetRTTAndHopCount", SetLastError = true)] + private static extern ulong GetRTTAndHopCount(ulong address, ref ulong hopCount, ulong maxHops, ref ulong rtt); + + private enum WinError + { + UNKNOWN = -1, + NO_ERROR = 0, + ACCESS_DENIED = 5, + NOT_ENOUGH_MEMORY = 8, + OUTOFMEMORY = 14, + NOT_SUPPORTED = 50, + INVALID_PARAMETER = 87, + ERROR_INVALID_NETNAME = 1214, + WSAEINTR = 10004, + WSAEACCES = 10013, + WSAEFAULT = 10014, + WSAEINVAL = 10022, + WSAEWOULDBLOCK = 10035, + WSAEINPROGRESS = 10036, + WSAEALREADY = 10037, + WSAENOTSOCK = 10038, + WSAENETUNREACH = 10051, + WSAENETRESET = 10052, + WSAECONNABORTED = 10053, + WSAECONNRESET = 10054, + IP_REQ_TIMED_OUT = 11010, + } + } +} \ No newline at end of file diff --git a/PingPlugin/PingTrackers/PingTracker.cs b/PingPlugin/PingTrackers/PingTracker.cs index 5ef5cde..5adf074 100644 --- a/PingPlugin/PingTrackers/PingTracker.cs +++ b/PingPlugin/PingTrackers/PingTracker.cs @@ -53,6 +53,7 @@ protected void NextRTTCalculation(ulong nextRTT) CalcAverage(); LastRTT = nextRTT; + SendMessage(); } protected void CalcAverage() => AverageRTT = RTTTimes.Average(); @@ -80,7 +81,7 @@ private async Task AddressUpdateLoop(CancellationToken token) } } - protected void SendMessage() + private void SendMessage() { var del = OnPingUpdated; del?.Invoke(new PingStatsPayload