diff --git a/Shared/Services/WolService.cs b/Shared/Services/WolService.cs index 9666176..2457086 100644 --- a/Shared/Services/WolService.cs +++ b/Shared/Services/WolService.cs @@ -1,5 +1,6 @@ using ColorControl.Shared.Common; using NLog; +using NStandard; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; @@ -14,7 +15,7 @@ public class WolService private const string ArgumentExceptionInvalidMacAddressLength = "Invalid MAC address length."; private const string ArgumentExceptionInvalidPasswordLength = "Invalid password length."; - private const int DefaultWolPort = 9; + private const int DefaultWolPort = 0; private readonly WinApiService _winApiService; private readonly RpcClientService _rpcService; @@ -35,12 +36,19 @@ public bool SendWol(string macAddress, string ipAddress = null) return true; } - // If RPC faield, execute local WOL anyway + // If RPC failed, execute local WOL anyway } return WakeFunctionToAllNics(macAddress, ipAddress); } + private bool IsViableWOLInterface(NetworkInterface ni) { + return ni.NetworkInterfaceType != NetworkInterfaceType.Loopback + && !ni.Description.Contains("Hyper-V") + && ni.SupportsMulticast + && ni.GetIPProperties().GetIPv4Properties != null; + } + private bool WakeFunctionToAllNics(string macAddress, string ipAddressString) { var result = false; @@ -55,51 +63,34 @@ private bool WakeFunctionToAllNics(string macAddress, string ipAddressString) var interfaces = NetworkInterface.GetAllNetworkInterfaces(); - foreach (var ni in interfaces) - { - if (ni.NetworkInterfaceType == NetworkInterfaceType.Loopback/* || ni.Name.Contains("VirtualBox") || ni.Name.Contains("vEthernet") || ni.Description.Contains("Virtual")*/) - { - continue; - } - Logger.Debug($"Found network: {ni.Name} ({ni.Description}), type: {ni.NetworkInterfaceType}"); - try + interfaces + .Where(IsViableWOLInterface) + .Each(ni => { - if (ni.SupportsMulticast && ni.GetIPProperties().GetIPv4Properties() == null) - { - continue; - } - foreach (var uip in ni.GetIPProperties().UnicastAddresses) { if (uip.Address.ToString().StartsWith("169.254") || uip.Address.AddressFamily != AddressFamily.InterNetwork) { continue; } + try + { + Logger.Debug($"Broadcast WOL in network: {ni.Name} ({ni.Description}), local address: {uip.Address}, destination IP-address: {ipAddressString ?? "broadcast"}"); + BroadcastWol(uip.Address, IPAddress.Broadcast, data); - Logger.Debug($"Broadcast WOL in network: {ni.Name} ({ni.Description}), local address: {uip.Address}, destination IP-address: {ipAddressString ?? "broadcast"}"); + var parts = uip.Address.ToString().Split(".").ToList(); + parts[3] = "0"; + var broadcastAddress = IPAddress.Parse(string.Join(".", parts)); + BroadcastWol(uip.Address, broadcastAddress, data); - if (ipAddress != null && _winApiService.IsAdministrator()) + result = true; + } + catch (Exception ex) { - var localEP = new IPEndPoint(uip.Address, 0); - - SendWolToIpAddress(uip.Address, ipAddress, data, physicalAddress); + Logger.Error($"WakeFunctionToAllNics: while sending to specific network: {ni.Name} ({ni.Description}): {ex.ToLogString()}"); } - - BroadcastWol(uip.Address, IPAddress.Broadcast, data); - - var parts = uip.Address.ToString().Split(".").ToList(); - parts[3] = "0"; - var broadcastAddress = IPAddress.Parse(string.Join(".", parts)); - BroadcastWol(uip.Address, broadcastAddress, data); - - result = true; } - } - catch (Exception ex) - { - Logger.Error($"WakeFunctionToAllNics: while sending to specific network: {ni.Name} ({ni.Description}): {ex.ToLogString()}"); - } - } + }); } catch (Exception ex) { @@ -112,61 +103,43 @@ private bool WakeFunctionToAllNics(string macAddress, string ipAddressString) /// is null. /// The length of the array is not 6. /// The length of the array is not 0 or 6. - private static byte[] GetWolPacket(byte[] macAddress, byte[] password = null) + private static byte[] GetWolPacket(byte[] macAddress) { if (macAddress == null) throw new ArgumentNullException(nameof(macAddress)); if (macAddress.Length != 6) throw new ArgumentException(ArgumentExceptionInvalidMacAddressLength); - password = password ?? new byte[0]; - if (password.Length != 0 && password.Length != 6) - throw new ArgumentException(ArgumentExceptionInvalidPasswordLength); - - var packet = new byte[17 * 6 + password.Length]; + byte[] packet = new byte[102]; - int offset, i; - for (offset = 0; offset < 6; ++offset) - packet[offset] = 0xFF; - - for (offset = 6; offset < 17 * 6; offset += 6) - for (i = 0; i < 6; ++i) - packet[i + offset] = macAddress[i]; + foreach (var i in Enumerable.Range(0, 6)) { + packet[i] = 0xFF; + } - if (password.Length > 0) - { - for (offset = 16 * 6 + 6; offset < 17 * 6 + password.Length; offset += 6) - for (i = 0; i < 6; ++i) - packet[i + offset] = password[i]; + foreach (var i in Enumerable.Range(0, 16)) { + macAddress.CopyTo(packet, 6 + i * 6); } + return packet; } private static void BroadcastWol(IPAddress localAddress, IPAddress broadCastAddress, byte[] data) { - //var localEP = new IPEndPoint(localAddress, 0); - var udpc = new UdpClient(); - + using var udpc = new UdpClient(new IPEndPoint(localAddress, 0)); udpc.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1); - //udpc.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontRoute, 1); var target = new IPEndPoint(broadCastAddress, DefaultWolPort); - udpc.Send(data, data.Length, target); } private static void SendWolToIpAddress(IPAddress localAddress, IPAddress remoteAddress, byte[] data, PhysicalAddress physicalAddress) { - //var localEP = new IPEndPoint(localAddress, 0); - var netLuid = CreateTransientLocalNetEntry(remoteAddress, physicalAddress); try { - var udpc = new UdpClient(); + using var udpc = new UdpClient(new IPEndPoint(localAddress, 0)); udpc.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1); - var target = new IPEndPoint(remoteAddress, DefaultWolPort); - udpc.Send(data, data.Length, target); } finally