using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; using System.Management; using System.Management.Automation; using System.Net; using System.Net.NetworkInformation; using System.Text; using System.Threading; using System.Threading.Tasks; using Vinno.FIS.Sonopost.Features.Network; using Vinno.FIS.Sonopost.Features.Oled; using Vinno.FIS.Sonopost.Helpers; using Vinno.FIS.Sonopost.Managers.Interfaces; using Vinno.FIS.Sonopost.Settings; using Vinno.IUS.Common.Log; using Vinno.IUS.Common.Utilities; namespace Vinno.FIS.Sonopost.Managers { internal enum DefaultNetworkMode { Ethernet, Wireless } internal class NetworkManager : SonopostManager, INetworkManager { private NetworkInterfaceInfo _currentNetwork; private int _currentWifiLevel; private int _timingRefreshInterval;//unit:second. private readonly object _networkInterfaceInfolocker = new object(); private readonly object _networkAddresslocker = new object(); private DefaultNetworkMode _defaultNetworkMode; private readonly IDeviceManager _deviceManager; private readonly IConfigManager _configManager; private readonly ManualResetEvent _timingRefreshManualResetEvent = new ManualResetEvent(false); private readonly List _networkInterfaceInfos; public event EventHandler CurrentNetworkChanged; public event EventHandler CurrentWifiLevelChanged; public List _currentNetworkInterfaces; public NetworkInterfaceInfo CurrentNetwork { get => _currentNetwork; private set { if (_currentNetwork != value) { _currentNetwork = value; CurrentNetworkChanged?.Invoke(this, _currentNetwork); CurrentWifiLevelChanged?.Invoke(this, _currentWifiLevel); } } } public int CurrentWifiLevel { get => _currentWifiLevel; private set { if (_currentWifiLevel != value) { _currentWifiLevel = value; CurrentWifiLevelChanged?.Invoke(this, _currentWifiLevel); } } } public NetworkManager() { _networkInterfaceInfos = new List(); _defaultNetworkMode = DefaultNetworkMode.Ethernet; _configManager = AppManager.Instance.GetManager(); _deviceManager = AppManager.Instance.GetManager(); _deviceManager.WifiModuleInserted += OnWifiModuleInserted; _deviceManager.NetworkAddressChanged += OnNetworkAddressChanged; RefreshAllNetworks(true); _timingRefreshInterval = 15; StartTimerRefreshTask(); AutoReconnectWifi(false); } private void OnWifiModuleInserted(object sender, EventArrivedEventArgs e) { lock (_networkAddresslocker) { AutoReconnectWifi(true); } } private void AutoReconnectWifi(bool needRefresh) { if (needRefresh) { RefreshAllNetworks(true); } var isAutoConnect = SonopostUserDefinedSettings.Instance.NetworkSetting.IsAutoConnect; var wifiName = SonopostUserDefinedSettings.Instance.NetworkSetting.WifiName; var wifiPassword = DesBuilder.Decrypt(SonopostUserDefinedSettings.Instance.NetworkSetting.WifiPassword); var wifiMacAddress = SonopostUserDefinedSettings.Instance.NetworkSetting.WifiMacAddress; Logger.WriteLineInfo($"Network Manager Auto Conncect Wifi :{isAutoConnect},MacAddress:{wifiMacAddress}"); if (!string.IsNullOrWhiteSpace(wifiMacAddress) && isAutoConnect) { var wifiInfo = GetAllNetworkInterfaceInfos().FirstOrDefault(x => x.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 && x.MacAddress == wifiMacAddress); if (wifiInfo == null) { Logger.WriteLineError($"Network Manager Auto Conncect Wifi Fail,Because the Wifi MacAdress : {wifiMacAddress} is not exist"); } else if (wifiInfo.OperationalStatus == OperationStatus.Connected) { Logger.WriteLineError($"Network Manager Auto Conncect Wifi Fail,Because the Wifi MacAdress : {wifiMacAddress} already connected"); } else { var point = ((WirelessNetworkInterfaceInfo)wifiInfo).GetAccessPoints()?.FirstOrDefault(x => x.Name.Equals(wifiName)); if (point == null) { Logger.WriteLineError($"Network Manager Auto Conncect Wifi Fail,Because the Wifi {wifiName} is not exist"); } else { var result = ((WirelessNetworkInterfaceInfo)wifiInfo).Connect(point, wifiName, wifiPassword); if (result) { Logger.WriteLineInfo($"Network Manager Auto Conncect Wifi Success"); } else { Logger.WriteLineError($"Network Manager Auto Conncect Wifi Fail,Because Connect Failed"); } } } } } public void OnNetworkAddressChanged(object sender, EventArgs e) { lock (_networkAddresslocker) { RefreshAllNetworks(false); } } public void RefreshAllNetworks(bool wlanReScan) { try { foreach (var existNetwork in _networkInterfaceInfos) { existNetwork.Dispose(); } _networkInterfaceInfos.Clear(); var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces(); var interfaces = networkInterfaces.Where(c => !c.Description.ToUpper().Contains("VIRTUAL") && !c.Description.ToUpper().Contains("BLUETOOTH") && !c.Description.ToUpper().Contains("LOOPBACK")).OrderBy(x => x.Description).ToList(); var allInterfaces = new List(); var i219List = interfaces.Where(x => x.Description.ToLower().Contains("i219")).OrderBy(x => x.Description).ToList(); allInterfaces.AddRange(i219List);//219为主网卡 var i211List = interfaces.Where(x => x.Description.ToLower().Contains("i211")).OrderBy(x => x.Description).ToList(); allInterfaces.AddRange(i211List);//211已停产 var i210List = interfaces.Where(x => x.Description.ToLower().Contains("i210")).OrderBy(x => x.Description).ToList(); allInterfaces.AddRange(i210List);//210为副网卡 foreach (var restInterface in interfaces) { if (!i211List.Contains(restInterface) && !i219List.Contains(restInterface) && !i210List.Contains(restInterface)) { allInterfaces.Add(restInterface); } } foreach (var network in allInterfaces) { if (network.NetworkInterfaceType == NetworkInterfaceType.Ethernet) { var networkInterfaceInfo = new NetworkInterfaceInfo(network); _networkInterfaceInfos.Add(networkInterfaceInfo); } else if (network.NetworkInterfaceType == NetworkInterfaceType.Wireless80211) { var wirelessInterfaceInfo = new WirelessNetworkInterfaceInfo(network, wlanReScan); _networkInterfaceInfos.Add(wirelessInterfaceInfo); } } lock (_networkInterfaceInfolocker) { _currentNetworkInterfaces = _networkInterfaceInfos.ToList(); } if (wlanReScan) { Thread.Sleep(3000);//扫描网络会卡顿3秒左右 } SetCurrentNetwork(); } catch (Exception ex) { Logger.WriteLineError($"Refresh all network error:{ex}"); } } public IList GetAllNetworkInterfaceInfos() { lock (_networkInterfaceInfolocker) { return _currentNetworkInterfaces.ToList(); } } private void SetCurrentNetwork() { var outsideAddress = SonopostUserDefinedSettings.Instance.NetworkSetting.OutsideNetworkMacAddress; NetworkInterfaceInfo networkInterfaceInfo = null; NetworkInterfaceInfo outsideNetworkInfo = null; var networkInterfaceInfos = GetAllNetworkInterfaceInfos(); var connectedList = networkInterfaceInfos.Where(x => x.OperationalStatus == OperationStatus.Connected); if (connectedList.Count() == 0) { _defaultNetworkMode = DefaultNetworkMode.Ethernet; } else if (connectedList.Count() == 1) { _defaultNetworkMode = connectedList.FirstOrDefault().NetworkInterfaceType == NetworkInterfaceType.Ethernet ? DefaultNetworkMode.Ethernet : DefaultNetworkMode.Wireless; } else if (!connectedList.Any(x => x.NetworkInterfaceType == NetworkInterfaceType.Ethernet) && _defaultNetworkMode == DefaultNetworkMode.Ethernet) { _defaultNetworkMode = DefaultNetworkMode.Wireless; } else if (!connectedList.Any(x => x.NetworkInterfaceType == NetworkInterfaceType.Wireless80211) && _defaultNetworkMode == DefaultNetworkMode.Wireless) { _defaultNetworkMode = DefaultNetworkMode.Ethernet; } if (!string.IsNullOrEmpty(outsideAddress)) { outsideNetworkInfo = networkInterfaceInfos.FirstOrDefault(c => string.Equals(c.MacAddress, outsideAddress)); if (outsideNetworkInfo != null && outsideNetworkInfo.OperationalStatus != OperationStatus.Connected) { outsideNetworkInfo = null; } } if (outsideNetworkInfo == null) { if (connectedList.Count() <= 1) { networkInterfaceInfo = connectedList.FirstOrDefault(); } else { var currentNetworkMacAddress = CurrentNetwork?.MacAddress; if (!string.IsNullOrWhiteSpace(currentNetworkMacAddress)) { if (_defaultNetworkMode == DefaultNetworkMode.Ethernet) { networkInterfaceInfo = connectedList.FirstOrDefault(x => x.NetworkInterfaceType == NetworkInterfaceType.Ethernet && x.MacAddress == currentNetworkMacAddress); } else if (_defaultNetworkMode == DefaultNetworkMode.Wireless) { networkInterfaceInfo = connectedList.FirstOrDefault(x => x.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 && x.MacAddress == currentNetworkMacAddress); } } if (networkInterfaceInfo == null) { if (_defaultNetworkMode == DefaultNetworkMode.Ethernet) { networkInterfaceInfo = connectedList.FirstOrDefault(x => x.NetworkInterfaceType == NetworkInterfaceType.Ethernet); } else if (_defaultNetworkMode == DefaultNetworkMode.Wireless) { networkInterfaceInfo = connectedList.FirstOrDefault(x => x.NetworkInterfaceType == NetworkInterfaceType.Wireless80211); } } } } if (outsideNetworkInfo != null) { CurrentNetwork = outsideNetworkInfo; } else { if (networkInterfaceInfo == null) { CurrentNetwork = networkInterfaceInfos.FirstOrDefault(c => c.NetworkInterfaceType == NetworkInterfaceType.Ethernet); } else { CurrentNetwork = networkInterfaceInfo; } } } private int GetWifiLevel(WirelessNetworkInterfaceInfo network) { var currentWifi = network.GetAccessPoints().FirstOrDefault(c => c.IsConnected == true); if (currentWifi == null) { return 1; } int level; if (currentWifi.SignalStrength > 85) { level = 4; } else if (currentWifi.SignalStrength > 55) { level = 3; } else { level = 2; } return level; } public bool SetNetworkInfo(string macAddress, bool enableDhcp, string ip = "", string subnetMask = "", string gateway = "", string preferredDns = "", string standbyDns = "") { lock (_networkAddresslocker) { try { var networkInterfaceInfos = GetAllNetworkInterfaceInfos(); var network = networkInterfaceInfos.FirstOrDefault(c => c.MacAddress == macAddress); if (network == null) { Logger.WriteLineError($"Can not find network {macAddress}"); return false; } if (enableDhcp == false) { if (IsAddressValid(ip) == false) return false; if (IsAddressValid(subnetMask) == false) return false; if (IsAddressValid(gateway) == false) return false; if (IsAddressValid(preferredDns) == false) return false; if (!string.IsNullOrEmpty(standbyDns)) { if (IsAddressValid(standbyDns) == false) return false; } network.IpAddress.Value = ip; network.SubnetMask.Value = subnetMask; network.GateWay.Value = gateway; network.PreferredDNSServer.Value = preferredDns; network.StandbyDNSServer.Value = standbyDns; } network.SaveChanges(enableDhcp); Logger.WriteLineInfo($"Set Network Info Success:MacAddress:{macAddress},EnableDHCP:{enableDhcp},IP:{ip},SubnetMask:{subnetMask},GateWay:{gateway},PreferredDNS:{preferredDns},StandbyDNS:{standbyDns}"); return true; } catch (Exception ex) { Logger.WriteLineError($"Set Network Info Error:{ex}"); } return false; } } public bool FlushDns() { var flushdns = "ipconfig /flushdns"; var cmdOutPut = DoCmd(flushdns); return !string.IsNullOrWhiteSpace(cmdOutPut); } public bool ResetWinSock() { var resetWinsock = "netsh winsock reset"; var cmdOutPut = DoCmd(resetWinsock); return !string.IsNullOrWhiteSpace(cmdOutPut); } public IPStatus Ping(string address, int timeOut = 5000) { try { Ping myPing = new Ping(); PingReply reply = myPing.Send(address, timeOut); if (reply == null) { return IPStatus.Unknown; } return reply.Status; } catch (Exception ex) { Logger.WriteLineError($"NetworkManager Ping Error,IpAddress:{address}, Ex:{ex}"); return IPStatus.Unknown; } } public bool SetDualNetwork(string outsideMacAddress) { lock (_networkAddresslocker) { try { if (string.IsNullOrEmpty(outsideMacAddress)) { Logger.WriteLineError("mac address is empty"); return false; } var networkInterfaceInfos = GetAllNetworkInterfaceInfos(); var availableNetworks = networkInterfaceInfos.Where(c => c.OperationalStatus == OperationStatus.Connected && !string.IsNullOrEmpty(c.IpAddress.Value)).ToList(); var outsideNetwork = availableNetworks.FirstOrDefault(c => c.MacAddress == outsideMacAddress); if (outsideNetwork == null) { Logger.WriteLineError($"Can not find network:{outsideMacAddress}"); return false; } var insideNetworks = availableNetworks.Where(c => c.MacAddress != outsideMacAddress); if (!insideNetworks.Any()) { Logger.WriteLineError("Can not find other networks,no need set dual network!"); return false; } var deleteRoute = "route -p delete 0.0.0.0"; var outsideRoute = $"route -p add 0.0.0.0 mask 0.0.0.0 {GetGateWay(outsideNetwork.IpAddress.Value)}"; var insideRoute = "route -p add {0} mask 255.255.255.0 {1}"; DoCmd(deleteRoute); DoCmd(outsideRoute); foreach (var network in insideNetworks) { var index = network.GateWay.Value.LastIndexOf('.'); var insideTarget = network.GateWay.Value.Substring(0, index + 1) + "0"; var routeCmd = string.Format(insideRoute, insideTarget, GetGateWay(network.IpAddress.Value)); DoCmd(routeCmd); } SetNetworkPriority(outsideNetwork.MacAddress); return true; } catch (Exception e) { Logger.WriteLineError($"SetDualNetworkEnable Error:{e}"); } return false; } } public SetDualNetworkResult SetDualNetworkEnable(string outsideMacAddress) { lock (_networkAddresslocker) { try { if (string.IsNullOrEmpty(outsideMacAddress)) { Logger.WriteLineError("mac address is empty"); return new SetDualNetworkResult { IsSuccess = false, NeedReboot = false, }; } var networkInterfaceInfos = GetAllNetworkInterfaceInfos(); var availableNetworks = networkInterfaceInfos.Where(c => c.OperationalStatus == OperationStatus.Connected && !string.IsNullOrEmpty(c.IpAddress.Value)).ToList(); var outsideNetwork = availableNetworks.FirstOrDefault(c => c.MacAddress == outsideMacAddress); if (outsideNetwork == null) { Logger.WriteLineError($"Can not find network:{outsideMacAddress}"); return new SetDualNetworkResult { IsSuccess = false, NeedReboot = false, }; } var insideNetworks = availableNetworks.Where(c => c.MacAddress != outsideMacAddress); if (!insideNetworks.Any()) { Logger.WriteLineError("Can not find other networks,no need set dual network!"); return new SetDualNetworkResult { IsSuccess = false, NeedReboot = false, }; } if (SonopostUserDefinedSettings.Instance.NetworkSetting.NeedDoubleNetwork && string.Equals(SonopostUserDefinedSettings.Instance.NetworkSetting.OutsideNetworkMacAddress, outsideMacAddress)) { return new SetDualNetworkResult { IsSuccess = true, NeedReboot = false, }; } SonopostUserDefinedSettings.Instance.NetworkSetting.NeedDoubleNetwork = true; SonopostUserDefinedSettings.Instance.NetworkSetting.OutsideNetworkMacAddress = outsideNetwork.MacAddress; _configManager.Save(); StartRebootTask(); return new SetDualNetworkResult { IsSuccess = true, NeedReboot = true, }; } catch (Exception e) { Logger.WriteLineError($"SetDualNetworkEnable Error:{e}"); } return new SetDualNetworkResult { IsSuccess = false, NeedReboot = false, }; } } public SetDualNetworkResult SetDualNetworkDisable() { try { if (!SonopostUserDefinedSettings.Instance.NetworkSetting.NeedDoubleNetwork) { return new SetDualNetworkResult { IsSuccess = true, NeedReboot = false, }; } SonopostUserDefinedSettings.Instance.NetworkSetting.NeedDoubleNetwork = false; SonopostUserDefinedSettings.Instance.NetworkSetting.OutsideNetworkMacAddress = string.Empty; _configManager.Save(); var deleteaAll = $"route delete *"; DoCmd(deleteaAll); var routeCmd = "route -p add 0.0.0.0 mask 0.0.0.0 {0}"; var networkInterfaceInfos = GetAllNetworkInterfaceInfos(); var staticNetworks = networkInterfaceInfos.Where(c => c.EnableDhcp.Value == true); foreach (var item in staticNetworks) { var cmd = string.Format(routeCmd, GetGateWay(item.IpAddress.Value)); DoCmd(cmd); } StartRebootTask(); return new SetDualNetworkResult { IsSuccess = true, NeedReboot = true, }; } catch (Exception e) { Logger.WriteLineError($"SetDualNetworkDisEnable Error:{e}"); } return new SetDualNetworkResult { IsSuccess = false, NeedReboot = false, }; } private void StartRebootTask() { Task.Run(() => { Thread.Sleep(1000); AppManager.Instance.GetManager().ShowStatus(OledMessage.Reboot); SystemHelper.RebootSystem(); }); } private void StartTimerRefreshTask() { Logger.WriteLineInfo("NetworkManager Start Timer Refresh Task"); Task.Run(() => { _timingRefreshManualResetEvent.Reset(); try { while (!_timingRefreshManualResetEvent.WaitOne(_timingRefreshInterval * 1000)) { try { if (CurrentNetwork == null || string.IsNullOrEmpty(CurrentNetwork?.IpAddress?.Value)) { lock (_networkAddresslocker) { RefreshAllNetworks(false); } } if (CurrentNetwork is WirelessNetworkInterfaceInfo wireless) { CurrentWifiLevel = GetWifiLevel(wireless); } } catch (Exception ex) { Logger.WriteLineError($"NetworkManager Timer Refresh Task Error, ex:{ex}"); } } } catch (Exception ex) { Logger.WriteLineError($"NetworkManager Timer Refresh Task Error, ex:{ex}"); } finally { Logger.WriteLineInfo($"NetworkManager Timer Refresh Task Finshed"); } }); } /// /// 网关可能为空 /// /// /// private string GetGateWay(string ip) { var index = ip.LastIndexOf('.'); return ip.Substring(0, index + 1) + "1"; } private Dictionary GetNetworkAdapterIndexs() { Dictionary networkAdapters = new Dictionary(); var result = DoPowerShell("Get-NetAdapter", null); foreach (var item in result) { var index = item.Members["InterfaceIndex"]?.Value.ToString(); var address = item.Members["PermanentAddress"]?.Value.ToString(); var macAddress = ConvertMacAddress(address); networkAdapters.Add(macAddress, index); } return networkAdapters; } private void SetNetworkPriority(string mainMacAddress) { var networkAdapters = GetNetworkAdapterIndexs(); if (!networkAdapters.TryGetValue(mainMacAddress, out var ifindex)) { return; } int mainMetric = 10; var paramters = new Dictionary { { "InterfaceIndex", ifindex }, { "InterfaceMetric", mainMetric } }; DoPowerShell("Set-NetIPInterface", paramters); var othernetworks = networkAdapters.Where(c => c.Key != mainMacAddress); foreach (var item in othernetworks) { paramters["InterfaceIndex"] = item.Value; paramters["InterfaceMetric"] = ++mainMetric; DoPowerShell("Set-NetIPInterface", paramters); } } private void DisableAutoMetric() { var networkAdapters = GetNetworkAdapterIndexs(); var paramters = new Dictionary { { "InterfaceIndex", "0" }, { "AutomaticMetric ", "enabled" } }; foreach (var item in networkAdapters) { paramters["InterfaceIndex"] = item.Value; DoPowerShell("Set-NetIPInterface", paramters); } } public string ConvertMacAddress(string address) { StringBuilder sb = new StringBuilder(); var len = address.Length; for (int i = 0; i < len; i++) { sb.Append(address[i]); if (i % 2 != 0 && i != len - 1) { sb.Append('-'); } } return sb.ToString(); } private bool IsAddressValid(string address) { if (string.IsNullOrEmpty(address)) { return false; } return IPAddress.TryParse(address, out _); } public string DoCmd(string shell) { try { Process p = new Process(); p.StartInfo.CreateNoWindow = true; p.StartInfo.UseShellExecute = false; p.StartInfo.FileName = "cmd"; p.StartInfo.Verb = "runas"; var flushDnsArguments = "/C " + shell; p.StartInfo.Arguments = flushDnsArguments; p.StartInfo.RedirectStandardInput = true; p.StartInfo.RedirectStandardOutput = true; if (p.Start()) { string str = p.StandardOutput.ReadToEnd(); p.Close(); p.Dispose(); Logger.WriteLineInfo($"DoCmd Arguments:{shell}, Output:{str}"); return str; } } catch (Exception ex) { Logger.WriteLineError($"DoCmd Arguments:{shell} failed: {ex}"); } return string.Empty; } public Collection DoPowerShell(string shell, Dictionary parameters) { using (PowerShell powerShell = PowerShell.Create()) { powerShell.AddCommand(shell); if (parameters?.Count > 0) { foreach (var item in parameters) { powerShell.AddParameter(item.Key, item.Value); } } return powerShell.Invoke(); } } public override void DoDispose() { try { _deviceManager.WifiModuleInserted -= OnWifiModuleInserted; _deviceManager.NetworkAddressChanged -= OnNetworkAddressChanged; _timingRefreshManualResetEvent.Set(); lock (_networkInterfaceInfolocker) { _currentNetworkInterfaces.Clear(); } foreach (var existNetwork in _networkInterfaceInfos) { existNetwork.Dispose(); } _networkInterfaceInfos.Clear(); } catch (Exception ex) { Logger.WriteLineError($"NetworkManager DoDispose Error:{ex}"); } base.DoDispose(); } } }