using System.Net.NetworkInformation; using Microsoft.Win32; using SpdUp.Core; namespace SpdUp.Services; /// /// Network tweaks for gaming: DNS, TCP settings, latency checks. /// All changes are reversible via Restore methods. /// public sealed class NetworkService { private readonly Dictionary _previousRegValues = new(); /// /// Measure round-trip ping to a host. /// public static async Task PingAsync(string host = "8.8.8.8", int timeoutMs = 2000) { try { using var ping = new Ping(); var reply = await ping.SendPingAsync(host, timeoutMs); return reply.Status == IPStatus.Success ? reply.RoundtripTime : -1; } catch { return -1; } } /// /// Apply TCP gaming optimisations via the registry (Nagle, TCP ack frequency, etc.). /// public void ApplyTcpOptimizations() { try { const string tcpKey = @"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters"; using var key = Registry.LocalMachine.OpenSubKey(tcpKey, writable: true); if (key is null) return; SetRegistryValueWithBackup(key, tcpKey, "TcpAckFrequency", 1, RegistryValueKind.DWord); SetRegistryValueWithBackup(key, tcpKey, "TCPNoDelay", 1, RegistryValueKind.DWord); SetRegistryValueWithBackup(key, tcpKey, "TcpDelAckTicks", 0, RegistryValueKind.DWord); // Also per-interface const string ifacesKey = @"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces"; using var ifacesRoot = Registry.LocalMachine.OpenSubKey(ifacesKey); if (ifacesRoot is not null) { foreach (var subKeyName in ifacesRoot.GetSubKeyNames()) { using var ifaceKey = ifacesRoot.OpenSubKey(subKeyName, writable: true); if (ifaceKey is null) continue; var fullPath = $"{ifacesKey}\\{subKeyName}"; SetRegistryValueWithBackup(ifaceKey, fullPath, "TcpAckFrequency", 1, RegistryValueKind.DWord); SetRegistryValueWithBackup(ifaceKey, fullPath, "TCPNoDelay", 1, RegistryValueKind.DWord); } } Logger.Info("TCP gaming optimizations applied."); } catch (Exception ex) { Logger.Error("Failed to apply TCP optimizations", ex); } } /// /// Restore all TCP settings to their previous values. /// public void RestoreTcpSettings() { try { foreach (var kvp in _previousRegValues) { var parts = kvp.Key.Split('|'); if (parts.Length != 2) continue; using var key = Registry.LocalMachine.OpenSubKey(parts[0], writable: true); if (key is null) continue; if (kvp.Value is null) key.DeleteValue(parts[1], throwOnMissingValue: false); else key.SetValue(parts[1], kvp.Value); } _previousRegValues.Clear(); Logger.Info("TCP settings restored."); } catch (Exception ex) { Logger.Error("Failed to restore TCP settings", ex); } } private void SetRegistryValueWithBackup(RegistryKey key, string keyPath, string valueName, object newValue, RegistryValueKind kind) { var backupKey = $"{keyPath}|{valueName}"; if (!_previousRegValues.ContainsKey(backupKey)) _previousRegValues[backupKey] = key.GetValue(valueName); // null if not present key.SetValue(valueName, newValue, kind); } }