add better logging of network devices when sending WOL

This commit is contained in:
Vincent Maas committed 2021-02-05 19:56:19 +01:00
1 parent 91fd44d698
commit 5268e6679e
25 files changed
+1915 -8

No files matched your search

+1 -1
View File
@@ -27,7 +27,7 @@
<ProductName>ColorControl</ProductName>
<PublisherName>Maassoft</PublisherName>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.5.3.0</ApplicationVersion>
<ApplicationVersion>1.5.4.0</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<PublishWizardCompleted>true</PublishWizardCompleted>
<BootstrapperEnabled>true</BootstrapperEnabled>
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.5.3.0")]
[assembly: AssemblyFileVersion("1.5.3.0")]
[assembly: AssemblyVersion("1.5.4.0")]
[assembly: AssemblyFileVersion("1.5.4.0")]
+14 -5
View File
@@ -1,12 +1,10 @@
using NLog;
using System;
using System.Globalization;
using PacketDotNet;
using System.Net.NetworkInformation;
using SharpPcap;
using System.Diagnostics;
using SharpPcap.Npcap;
using System.Linq;
using System.Net;
namespace ColorControl
{
@@ -14,8 +12,12 @@ namespace ColorControl
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
//You need SharpPcap for this to work
public static void WakeFunction2(string macAddress)
{
//PhysicalAddress.Parse(macAddress).SendWol();
}
//You need SharpPcap for this to work
public static void WakeFunction(string macAddress)
{
/* Retrieve the device list */
@@ -40,7 +42,14 @@ namespace ColorControl
// }
//}
Logger.Debug("Opening network device: " + device.Name);
if (device is NpcapDevice npcapDevice)
{
Logger.Debug($"Opening network device (NpcapDevice): FriendlyName: {npcapDevice.Interface.FriendlyName}, Description: {npcapDevice.Interface.Description}");
}
else
{
Logger.Debug($"Opening network device (NOT A NpcapDevice!): {device.Name}, Description: {device.Description}");
}
//Open the device
device.Open();
+39
View File
@@ -0,0 +1,39 @@
using System.ComponentModel;
using System.Net.NetworkInformation;
using System.Threading.Tasks;
namespace System.Net
{
/// <summary>Stellt Methoden für das Senden von Anfragen über das ARP-Protokoll bereit.</summary>
public static class ArpRequest
{
/// <summary>
/// Sendet eine Anfrage über das ARP-Protokoll, um eine IP-Adresse in die Physikalische Adresse aufzulösen. Falls sich die physikalische Adresse bereits im Cache des Hosts befindet, wird diese zurückgegeben.
/// </summary>
/// <param name="destination">Destination <see cref="IPAddress"/>.</param>
/// <returns>Eine <see cref="T:System.Net.ArpRequestResult">ArpRequestResult</see>-Instanz, welche die Ergebnisse der Anfrage enthält.</returns>
public static ArpRequestResult Send(IPAddress destination)
{
if (destination == null)
throw new ArgumentNullException(nameof(destination));
int destIp = BitConverter.ToInt32(destination.GetAddressBytes(), 0);
var addr = new byte[6];
var len = addr.Length;
var res = NativeMethods.SendARP(destIp, 0, addr, ref len);
if (res == 0)
return new ArpRequestResult(new PhysicalAddress(addr));
return new ArpRequestResult(new Win32Exception(res));
}
/// <summary>
/// Sendet eine Anfrage über das ARP-Protokoll, um eine IP-Adresse in die Physikalische Adresse aufzulösen. Falls sich die physikalische Adresse bereits im Cache des Hosts befindet, wird diese zurückgegeben.
/// </summary>
/// <param name="destination">Destination <see cref="IPAddress"/>.</param>
/// <returns>Ein asynchroner Task, welcher einen ARP-Request sendet.</returns>
public static Task<ArpRequestResult> SendAsync(IPAddress destination) => Task.Run(() => Send(destination));
}
}
+57
View File
@@ -0,0 +1,57 @@
using System.Net.NetworkInformation;
using System.Text;
namespace System.Net
{
// TODO: rethink the whole exception thing
/// <summary>
/// Enthält die Rückgabewerte der ArpRequest.Send-Funktion.
/// </summary>
public class ArpRequestResult
{
/// <summary>Falls Fehler bei der Protokollanfrage auftreten, werden diese in dieser Eigenschaft abgelegt. Andernfalls null.</summary>
public Exception Exception { get; }
/// <summary>Die aufgelöste physikalische Adresse.</summary>
public PhysicalAddress Address { get; }
/// <summary>Erstellt eine neue ArpRequestResult-Instanz</summary>
/// <param name="address">Die physikalische Adresse</param>
public ArpRequestResult(PhysicalAddress address)
{
this.Exception = null;
Address = address;
}
/// <summary>Erstellt eine neue ArpRequestResult-Instanz</summary>
/// <param name="exception">Der aufgetretene Fehler</param>
public ArpRequestResult(Exception exception)
{
this.Exception = exception;
Address = null;
}
/// <summary>Konvertiert ARP-Rückgabewerte in eine Zeichenfolge.</summary>
public override string ToString()
{
var sb = new StringBuilder();
if (Address == null)
sb.Append("no address");
else
{
sb.Append("address: ");
sb.Append(Address);
}
sb.Append(", ");
if (Exception == null)
sb.Append("no exception");
else
{
sb.Append("exception: ");
sb.Append(Exception.Message);
}
return sb.ToString();
}
}
}
+62
View File
@@ -0,0 +1,62 @@
// This file is used by Code Analysis to maintain SuppressMessage
// attributes that are applied to this project.
// Project-level suppressions either have no target or are given
// a specific target and scoped to a namespace, type, member, etc.
//
// To add a suppression to this file, right-click the message in the
// Code Analysis results, point to "Suppress Message", and click
// "In Suppression File".
// You do not need to add suppressions to this file manually.
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWol(System.Net.IPAddress,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Int32)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWol(System.Net.IPAddress,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWol(System.Net.IPAddress,System.Byte[],System.Int32)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWol(System.Net.IPAddress,System.Byte[],System.Int32,System.Net.SecureOnPassword)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWol(System.Net.IPAddress,System.Byte[])")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWol(System.Net.IPAddress,System.Byte[],System.Net.SecureOnPassword)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWol(System.Net.IPAddress,System.Net.NetworkInformation.PhysicalAddress)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWol(System.Net.IPAddress,System.Net.NetworkInformation.PhysicalAddress,System.Net.SecureOnPassword)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWolAsync(System.Net.IPAddress,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Int32)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWolAsync(System.Net.IPAddress,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWolAsync(System.Net.IPAddress,System.Byte[],System.Int32)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWolAsync(System.Net.IPAddress,System.Byte[],System.Int32,System.Net.SecureOnPassword)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWolAsync(System.Net.IPAddress,System.Byte[])")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWolAsync(System.Net.IPAddress,System.Byte[],System.Net.SecureOnPassword)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWolAsync(System.Net.IPAddress,System.Net.NetworkInformation.PhysicalAddress)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWolAsync(System.Net.IPAddress,System.Net.NetworkInformation.PhysicalAddress,System.Net.SecureOnPassword)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPEndPointExtensions.#SendWol(System.Net.IPEndPoint,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPEndPointExtensions.#SendWol(System.Net.IPEndPoint,System.Byte[])")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPEndPointExtensions.#SendWol(System.Net.IPEndPoint,System.Net.NetworkInformation.PhysicalAddress)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPEndPointExtensions.#SendWol(System.Net.IPEndPoint,System.Byte[],System.Net.SecureOnPassword)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPEndPointExtensions.#SendWol(System.Net.IPEndPoint,System.Net.NetworkInformation.PhysicalAddress,System.Net.SecureOnPassword)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPEndPointExtensions.#SendWolAsync(System.Net.IPEndPoint,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPEndPointExtensions.#SendWolAsync(System.Net.IPEndPoint,System.Byte[])")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPEndPointExtensions.#SendWolAsync(System.Net.IPEndPoint,System.Net.NetworkInformation.PhysicalAddress)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPEndPointExtensions.#SendWolAsync(System.Net.IPEndPoint,System.Byte[],System.Net.SecureOnPassword)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPEndPointExtensions.#SendWolAsync(System.Net.IPEndPoint,System.Net.NetworkInformation.PhysicalAddress,System.Net.SecureOnPassword)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Lan")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Scope = "member", Target = "System.Net.Topology.INetMask.#GetMaskBytes()")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "n", Scope = "member", Target = "System.Net.Topology.NetMask.#op_Equality(System.Net.Topology.NetMask,System.Net.Topology.NetMask)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "n", Scope = "member", Target = "System.Net.Topology.NetMask.#op_Inequality(System.Net.Topology.NetMask,System.Net.Topology.NetMask)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "n", Scope = "member", Target = "System.Net.Topology.NetMask.#op_BitwiseAnd(System.Net.Topology.NetMask,System.Net.Topology.NetMask)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1008:EnumsShouldHaveZeroValue", Scope = "type", Target = "System.Net.Topology.SiblingOptions")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "type", Target = "System.Net.SendWol")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.PhysicalAddressExtensions.#SendWolAsync(System.Net.NetworkInformation.PhysicalAddress,System.Net.IPEndPoint)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.PhysicalAddressExtensions.#SendWolAsync(System.Net.NetworkInformation.PhysicalAddress,System.Net.SecureOnPassword)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.PhysicalAddressExtensions.#SendWolAsync(System.Net.NetworkInformation.PhysicalAddress)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.PhysicalAddressExtensions.#SendWol(System.Net.NetworkInformation.PhysicalAddress,System.Net.IPEndPoint,System.Net.SecureOnPassword)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.PhysicalAddressExtensions.#SendWol(System.Net.NetworkInformation.PhysicalAddress,System.Net.IPEndPoint)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.PhysicalAddressExtensions.#SendWol(System.Net.NetworkInformation.PhysicalAddress,System.Net.IPAddress,System.Net.SecureOnPassword)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.PhysicalAddressExtensions.#SendWol(System.Net.NetworkInformation.PhysicalAddress,System.Net.IPAddress)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.PhysicalAddressExtensions.#SendWol(System.Net.NetworkInformation.PhysicalAddress,System.Net.SecureOnPassword)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.PhysicalAddressExtensions.#SendWol(System.Net.NetworkInformation.PhysicalAddress)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "n", Scope = "member", Target = "System.Net.Topology.NetMask.#op_BitwiseOr(System.Net.Topology.NetMask,System.Net.Topology.NetMask)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "n", Scope = "member", Target = "System.Net.Topology.NetMask.#BitwiseOr(System.Net.Topology.NetMask,System.Net.Topology.NetMask)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.PhysicalAddressExtensions.#SendWolAsync(System.Net.NetworkInformation.PhysicalAddress,System.Net.IPAddress)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.PhysicalAddressExtensions.#SendWolAsync(System.Net.NetworkInformation.PhysicalAddress,System.Net.IPAddress,System.Net.SecureOnPassword)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.PhysicalAddressExtensions.#SendWolAsync(System.Net.NetworkInformation.PhysicalAddress,System.Net.IPEndPoint,System.Net.SecureOnPassword)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Cidr", Scope = "member", Target = "System.Net.Topology.INetMask.#Cidr")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "m", Scope = "member", Target = "System.Net.Topology.NetMask.#.ctor(System.Byte,System.Byte,System.Byte,System.Byte)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "n", Scope = "member", Target = "System.Net.Topology.NetMask.#BitwiseAnd(System.Net.Topology.NetMask,System.Net.Topology.NetMask)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "cidr", Scope = "member", Target = "System.Net.Topology.NetMask.#.ctor(System.Int32)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "cidr", Scope = "member", Target = "System.Net.Topology.NetMask.#.ctor(System.Byte)")]
+166
View File
@@ -0,0 +1,166 @@
using System.Threading.Tasks;
using System.Net.NetworkInformation;
using System.Net.Sockets;
namespace System.Net
{
/// <summary>Provides extension methods for sending Wake On LAN signals (magic packets) to a specific <see cref="IPAddress"/>.</summary>
public static class IPAddressExtensions
{
private const int DefaultWolPort = 7;
#region Wol
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
/// <param name="macAddress">The MAC address of the client.</param>
/// <param name="port">The port to send the packet to.</param>
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array <paramref name="macAddress"/> is not 6.</exception>
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
/// <exception cref="SocketException">An error occurred when accessing the socket. See Remarks section of <see cref="UdpClient.Send(byte[], int, IPEndPoint)"/> for more information.</exception>
public static void SendWol(this IPAddress target, byte[] macAddress, int port) => target.SendWol(macAddress, port, null);
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
/// <param name="macAddress">The MAC address of the client.</param>
/// <param name="port">The port to send the packet to.</param>
/// <param name="password">The SecureOn password of the client.</param>
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array <paramref name="macAddress"/> is not 6.</exception>
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
/// <exception cref="SocketException">An error occurred when accessing the socket. See Remarks section of <see cref="UdpClient.Send(byte[], int, IPEndPoint)"/> for more information.</exception>
public static void SendWol(this IPAddress target, byte[] macAddress, int port, SecureOnPassword password)
{
Net.MagicPacket.Send(new IPEndPoint(target, port), macAddress, password);
}
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
/// <param name="macAddress">The MAC address of the client.</param>
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array <paramref name="macAddress"/> is not 6.</exception>
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
/// <exception cref="SocketException">An error occurred when accessing the socket. See Remarks section of <see cref="UdpClient.Send(byte[], int, IPEndPoint)"/> for more information.</exception>
public static void SendWol(this IPAddress target, byte[] macAddress) => target.SendWol(macAddress, null);
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
/// <param name="macAddress">The MAC address of the client.</param>
/// <param name="password">The SecureOn password of the client.</param>
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array <paramref name="macAddress"/> is not 6.</exception>
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
/// <exception cref="SocketException">An error occurred when accessing the socket. See Remarks section of <see cref="UdpClient.Send(byte[], int, IPEndPoint)"/> for more information.</exception>
public static void SendWol(this IPAddress target, byte[] macAddress, SecureOnPassword password)
{
Net.MagicPacket.Send(new IPEndPoint(target, DefaultWolPort), macAddress, password);
}
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
/// <param name="macAddress">The MAC address of the client.</param>
/// <exception cref="ArgumentException">The length of the <see cref="PhysicalAddress" /> <paramref name="macAddress"/> is not 6.</exception>
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
/// <exception cref="SocketException">An error occurred when accessing the socket. See Remarks section of <see cref="UdpClient.Send(byte[], int, IPEndPoint)"/> for more information.</exception>
public static void SendWol(this IPAddress target, PhysicalAddress macAddress) => target.SendWol(macAddress, null);
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
/// <param name="macAddress">The MAC address of the client.</param>
/// <param name="password">The SecureOn password of the client.</param>
/// <exception cref="ArgumentException">The length of the <see cref="PhysicalAddress" /> <paramref name="macAddress"/> is not 6.</exception>
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
/// <exception cref="SocketException">An error occurred when accessing the socket. See Remarks section of <see cref="UdpClient.Send(byte[], int, IPEndPoint)"/> for more information.</exception>
public static void SendWol(this IPAddress target, PhysicalAddress macAddress, SecureOnPassword password)
{
Net.MagicPacket.Send(new IPEndPoint(target, DefaultWolPort), macAddress, password);
}
#endregion
#region ARP
/// <summary>
/// Sendet eine Anfrage über das ARP-Protokoll, um eine IP-Adresse in die Physikalische Adresse aufzulösen. Falls sich die physikalische Adresse bereits im Cache des Hosts befindet, wird diese zurückgegeben.
/// </summary>
/// <param name="destination">Destination <see cref="IPAddress"/>.</param>
/// <returns>Eine <see cref="T:System.Net.ArpRequestResult">ArpRequestResult</see>-Instanz, welche die Ergebnisse der Anfrage enthält.</returns>
public static ArpRequestResult SendArpRequest(this IPAddress destination) => ArpRequest.Send(destination);
#endregion
#region TAP
#region Wol
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
/// <param name="macAddress">The MAC address of the client.</param>
/// <param name="port">The port to send the packet to.</param>
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array <paramref name="macAddress"/> is not 6.</exception>
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
public static Task SendWolAsync(this IPAddress target, byte[] macAddress, int port) => target.SendWolAsync(macAddress, port, null);
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
/// <param name="macAddress">The MAC address of the client.</param>
/// <param name="port">The port to send the packet to.</param>
/// <param name="password">The SecureOn password of the client.</param>
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array <paramref name="macAddress"/> is not 6.</exception>
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
public static Task SendWolAsync(this IPAddress target, byte[] macAddress, int port, SecureOnPassword password)
{
return Net.MagicPacket.SendAsync(new IPEndPoint(target, port), macAddress, password);
}
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
/// <param name="macAddress">The MAC address of the client.</param>
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array <paramref name="macAddress"/> is not 6.</exception>
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
public static Task SendWolAsync(this IPAddress target, byte[] macAddress) => target.SendWolAsync(macAddress, null);
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
/// <param name="macAddress">The MAC address of the client.</param>
/// <param name="password">The SecureOn password of the client.</param>
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array <paramref name="macAddress"/> is not 6.</exception>
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
/// <exception cref="ArgumentNullException"><paramref name="password"/> is null.</exception>
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
public static Task SendWolAsync(this IPAddress target, byte[] macAddress, SecureOnPassword password)
{
return Net.MagicPacket.SendAsync(new IPEndPoint(target, DefaultWolPort), macAddress, password);
}
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
/// <param name="macAddress">The MAC address of the client.</param>
/// <exception cref="ArgumentException">The length of the <see cref="PhysicalAddress" /> <paramref name="macAddress"/> is not 6.</exception>
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
public static Task SendWolAsync(this IPAddress target, PhysicalAddress macAddress) => target.SendWolAsync(macAddress, null);
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
/// <param name="macAddress">The MAC address of the client.</param>
/// <param name="password">The SecureOn password of the client.</param>
/// <exception cref="ArgumentException">The length of the <see cref="PhysicalAddress" /> <paramref name="macAddress"/> is not 6.</exception>
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
/// <exception cref="ArgumentNullException"><paramref name="password"/> is null.</exception>
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
public static Task SendWolAsync(this IPAddress target, PhysicalAddress macAddress, SecureOnPassword password)
{
return Net.MagicPacket.SendAsync(new IPEndPoint(target, DefaultWolPort), macAddress, password);
}
#endregion
#region ARP
/// <summary>Sends a request via ARP to resolve an IP address to aphysical address. If the physical address is already cached, it's cached value is returned.</summary>
/// <param name="destination">Destination <see cref="IPAddress"/>.</param>
/// <returns>An asynchronous <see cref="Task"/> which sends an ARP request.</returns>
public static Task<ArpRequestResult> SendArpRequestAsync(this IPAddress destination) => ArpRequest.SendAsync(destination);
#endregion
#endregion
}
}
+101
View File
@@ -0,0 +1,101 @@
using System.Threading.Tasks;
using System.Net.NetworkInformation;
namespace System.Net
{
/// <summary>Provides extension methods for sending Wake On LAN signals (magic packets) to a specific <see cref="IPEndPoint"/>.</summary>
public static class IPEndPointExtensions
{
#region Wol
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
/// <param name="macAddress">The MAC address of the client.</param>
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array macAddress is not 6.</exception>
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
public static void SendWol(this IPEndPoint target, byte[] macAddress)
{
Net.MagicPacket.Send(target, macAddress);
}
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
/// <param name="macAddress">The MAC address of the client.</param>
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
public static void SendWol(this IPEndPoint target, PhysicalAddress macAddress)
{
Net.MagicPacket.Send(target, macAddress);
}
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
/// <param name="macAddress">The MAC address of the client.</param>
/// <param name="password">The SecureOn password of the client.</param>
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array macAddress is not 6.</exception>
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
public static void SendWol(this IPEndPoint target, byte[] macAddress, SecureOnPassword password)
{
Net.MagicPacket.Send(target, macAddress, password);
}
/// <summary>
/// Sendet ein Wake-On-LAN-Signal an einen Client.
/// </summary>
/// <param name="target">Der Ziel-IPEndPoint.</param>
/// <param name="macAddress">The MAC address of the client.</param>
/// <param name="password">The SecureOn password of the client.</param>
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
public static void SendWol(this IPEndPoint target, PhysicalAddress macAddress, SecureOnPassword password)
{
Net.MagicPacket.Send(target, macAddress, password);
}
#endregion
#region TAP
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
/// <param name="macAddress">The MAC address of the client.</param>
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array macAddress is not 6.</exception>
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
public static Task SendWolAsync(this IPEndPoint target, byte[] macAddress)
{
return Net.MagicPacket.SendAsync(target, macAddress);
}
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
/// <param name="macAddress">The MAC address of the client.</param>
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
public static Task SendWolAsync(this IPEndPoint target, PhysicalAddress macAddress)
{
return Net.MagicPacket.SendAsync(target, macAddress);
}
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
/// <param name="macAddress">The MAC address of the client.</param>
/// <param name="password">The SecureOn password of the client.</param>
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array macAddress is not 6.</exception>
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
public static Task SendWolAsync(this IPEndPoint target, byte[] macAddress, SecureOnPassword password)
{
return Net.MagicPacket.SendAsync(target, macAddress, password);
}
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
/// <param name="macAddress">The MAC address of the client.</param>
/// <param name="password">The SecureOn password of the client.</param>
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
public static Task SendWolAsync(this IPEndPoint target, PhysicalAddress macAddress, SecureOnPassword password)
{
return Net.MagicPacket.SendAsync(target, macAddress, password);
}
#endregion
}
}
+12
View File
@@ -0,0 +1,12 @@
#define GERMAN
namespace System.Net
{
internal static class Localization
{
public const string ArgumentExceptionInvalidMacAddressLength = "Invalid MAC address length.";
public const string ArgumentExceptionInvalidPasswordLength = "Invalid password length.";
public const string ArgumentExceptionIsNotAValidMadAddress = " is not a valid MAC address.";
}
}
+171
View File
@@ -0,0 +1,171 @@
using System.Threading.Tasks;
using System.Net.NetworkInformation;
using System.Net.Sockets;
namespace System.Net
{
/// <summary>Provides methods for sending Wake On LAN signals (magic packets).</summary>
public static class MagicPacket
{
#region Wol
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
/// <param name="macAddress">The MAC address of the designated client.</param>
/// <exception cref="ArgumentNullException">target is null.</exception>
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array macAddress is not 6.</exception>
/// <exception cref="SocketException">An error occurred when accessing the socket. See Remarks section of <see cref="UdpClient.Send(byte[], int, IPEndPoint)"/> for more information.</exception>
public static void Send(IPEndPoint target, byte[] macAddress) => Send(target, macAddress, null);
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
/// <param name="macAddress">The MAC address of the designated client.</param>
/// <param name="password">The SecureOn password of the client.</param>
/// <exception cref="ArgumentNullException"><paramref name="target"/> is null.</exception>
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array <paramref name="macAddress"/> is not 6.</exception>
/// <exception cref="SocketException">An error occurred when accessing the socket. See Remarks section of <see cref="UdpClient.Send(byte[], int, IPEndPoint)"/> for more information.</exception>
public static void Send(IPEndPoint target, byte[] macAddress, SecureOnPassword password)
{
if (macAddress == null)
throw new ArgumentNullException(nameof(macAddress));
byte[] passwordBuffer = password?.GetPasswordBytes();
byte[] packet = GetWolPacket(macAddress, passwordBuffer);
SendPacket(target, packet);
}
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
/// <param name="macAddress">The MAC address of the designated client.</param>
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
/// <exception cref="SocketException">An error occurred when accessing the socket. See Remarks section of <see cref="UdpClient.Send(byte[], int, IPEndPoint)"/> for more information.</exception>
public static void Send(IPEndPoint target, PhysicalAddress macAddress) => Send(target, macAddress, null);
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
/// <param name="macAddress">The MAC address of the designated client.</param>
/// <param name="password">The SecureOn password of the client.</param>
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
/// <exception cref="SocketException">An error occurred when accessing the socket. See Remarks section of <see cref="UdpClient.Send(byte[], int, IPEndPoint)"/> for more information.</exception>
public static void Send(IPEndPoint target, PhysicalAddress macAddress, SecureOnPassword password)
{
if (macAddress == null)
throw new ArgumentNullException(nameof(macAddress));
byte[] passwordBuffer = password?.GetPasswordBytes();
byte[] packet = GetWolPacket(macAddress.GetAddressBytes(), passwordBuffer);
SendPacket(target, packet);
}
private static void SendPacket(IPEndPoint target, byte[] packet)
{
using (var cl = new UdpClient())
cl.Send(packet, packet.Length, target);
}
#endregion
#region TAP
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
/// <param name="macAddress">The MAC address of the designated client.</param>
/// <exception cref="ArgumentNullException"><paramref name="target"/> is null.</exception>
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
/// <exception cref="ArgumentException">The length of the <see cref="Byte" /> array <paramref name="macAddress"/> is not 6.</exception>
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
public static Task SendAsync(IPEndPoint target, byte[] macAddress) => SendAsync(target, macAddress);
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
/// <param name="macAddress">The MAC address of the designated client.</param>
/// <param name="password">The SecureOn password of the client.</param>
/// <exception cref="ArgumentNullException"><paramref name="target"/> is null.</exception>
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
/// <exception cref="ArgumentNullException"><paramref name="password"/> is null.</exception>
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
public static Task SendAsync(IPEndPoint target, byte[] macAddress, SecureOnPassword password)
{
if (target == null)
throw new ArgumentNullException(nameof(target));
if (macAddress == null)
throw new ArgumentNullException(nameof(macAddress));
var passwordBuffer = password?.GetPasswordBytes();
var packet = GetWolPacket(macAddress, passwordBuffer);
return SendPacketAsync(target, packet);
}
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
/// <param name="macAddress">The MAC address of the designated client.</param>
/// <exception cref="ArgumentNullException"><paramref name="target"/> is null.</exception>
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
public static Task SendAsync(IPEndPoint target, PhysicalAddress macAddress) => SendAsync(target, macAddress, null);
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
/// <param name="macAddress">The MAC address of the designated client.</param>
/// <param name="password">The SecureOn password of the client.</param>
/// <exception cref="ArgumentNullException"><paramref name="target"/> is null.</exception>
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
public static Task SendAsync(IPEndPoint target, PhysicalAddress macAddress, SecureOnPassword password)
{
if (target == null)
throw new ArgumentNullException(nameof(target));
if (macAddress == null)
throw new ArgumentNullException(nameof(macAddress));
var passwordBuffer = password?.GetPasswordBytes();
var p = GetWolPacket(macAddress.GetAddressBytes(), passwordBuffer);
return SendPacketAsync(target, p);
}
private static Task SendPacketAsync(IPEndPoint target, byte[] packet)
{
var cl = new UdpClient();
return cl.SendAsync(packet, packet.Length, target).ContinueWith((Task t) => cl.Close());
}
#endregion
#region internal
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array <paramref name="macAddress"/> is not 6.</exception>
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array <paramref name="password"/> is not 0 or 6.</exception>
private static byte[] GetWolPacket(byte[] macAddress, byte[] password)
{
if (macAddress == null)
throw new ArgumentNullException(nameof(macAddress));
if (macAddress.Length != 6)
throw new ArgumentException(Localization.ArgumentExceptionInvalidMacAddressLength);
password = password ?? new byte[0];
if (password.Length != 0 && password.Length != 6)
throw new ArgumentException(Localization.ArgumentExceptionInvalidPasswordLength);
var packet = new byte[17 * 6 + password.Length];
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];
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];
}
return packet;
}
#endregion
}
}
+14
View File
@@ -0,0 +1,14 @@
using System.Runtime.InteropServices;
using System.Security;
namespace System.Net
{
internal static class NativeMethods
{
private const string IphlpApi = "iphlpapi.dll";
[DllImport(IphlpApi, ExactSpelling = true)]
[SecurityCritical]
internal static extern int SendARP(int destinationIp, int sourceIp, byte[] macAddress, ref int physicalAddrLength);
}
}
+148
View File
@@ -0,0 +1,148 @@
using System.Threading.Tasks;
using System.Net.NetworkInformation;
namespace System.Net
{
/// <summary>Provides extension methods for sending Wake On LAN signals (magic packets) using a specific <see cref="PhysicalAddress"/>.</summary>
public static class PhysicalAddressExtensions
{
#region Wol
/// <summary>Sends a Wake On LAN signal (magic packet) to the broadcast IP address with the physical address.</summary>
/// <param name="address">The instance of the physical address that should be used in the magic packet.</param>
/// <exception cref="ArgumentNullException"><paramref name="address"/> is null.</exception>
public static void SendWol(this PhysicalAddress address) => address.SendWol(IPAddress.Broadcast, null);
/// <summary>Sends a Wake On LAN signal (magic packet) to a specific IP address with the physical address.</summary>
/// <param name="address">The instance of the physical address that should be used in the magic packet.</param>
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
/// <exception cref="ArgumentNullException"><paramref name="address"/> is null.</exception>
public static void SendWol(this PhysicalAddress address, IPAddress target) => address.SendWol(target, null);
/// <summary>Sends a Wake On LAN signal (magic packet) to a specific IP address with the physical address.</summary>
/// <param name="address">The instance of the physical address that should be used in the magic packet.</param>
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
/// <param name="password">The SecureOn password of the client.</param>
/// <exception cref="ArgumentNullException"><paramref name="address"/> is null.</exception>
public static void SendWol(this PhysicalAddress address, IPAddress target, SecureOnPassword password)
{
if (address == null)
throw new ArgumentNullException(nameof(address));
target.SendWol(address.GetAddressBytes(), password);
}
/// <summary>Sends a Wake On LAN signal (magic packet) to a specific IP end point with the physical address.</summary>
/// <param name="address">The instance of the physical address that should be used in the magic packet.</param>
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
/// <exception cref="ArgumentNullException"><paramref name="address"/> is null.</exception>
public static void SendWol(this PhysicalAddress address, IPEndPoint target) => address.SendWol(target, null);
/// <summary>Sends a Wake On LAN signal (magic packet) to a specific IP end point with the physical address.</summary>
/// <param name="address">The instance of the physical address that should be used in the magic packet.</param>
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
/// <param name="password">The SecureOn password of the client.</param>
/// <exception cref="ArgumentNullException"><paramref name="address"/> is null.</exception>
public static void SendWol(this PhysicalAddress address, IPEndPoint target, SecureOnPassword password)
{
if (address == null)
throw new ArgumentNullException(nameof(address));
target.SendWol(address.GetAddressBytes(), password);
}
#endregion
#region TAP
/// <summary>Sends a Wake On LAN signal (magic packet) to the broadcast IP address with the physical address.</summary>
/// <param name="address">The instance of the physical address that should be used in the magic packet.</param>
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
/// <exception cref="ArgumentNullException"><paramref name="address"/> is null.</exception>
public static Task SendWolAsync(this PhysicalAddress address)
{
if (address == null)
throw new ArgumentNullException(nameof(address));
return IPAddress.Broadcast.SendWolAsync(address.GetAddressBytes());
}
/// <summary>Sends a Wake On LAN signal (magic packet) to a specific IP address with the physical address.</summary>
/// <param name="address">The instance of the physical address that should be used in the magic packet.</param>
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
/// <exception cref="ArgumentNullException"><paramref name="address"/> is null.</exception>
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
public static Task SendWolAsync(this PhysicalAddress address, IPAddress target) => address.SendWolAsync(target, null);
/// <summary>Sends a Wake On LAN signal (magic packet) to a specific IP address with the physical address.</summary>
/// <param name="address">The instance of the physical address that should be used in the magic packet.</param>
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
/// <param name="password">The SecureOn password of the client.</param>
/// <exception cref="ArgumentNullException"><paramref name="address"/> is null.</exception>
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
public static Task SendWolAsync(this PhysicalAddress address, IPAddress target, SecureOnPassword password)
{
if (address == null)
throw new ArgumentNullException(nameof(address));
return target.SendWolAsync(address.GetAddressBytes(), password);
}
/// <summary>Sends a Wake On LAN signal (magic packet) to a specific IP end point with the physical address.</summary>
/// <param name="address">The instance of the physical address that should be used in the magic packet.</param>
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
/// <exception cref="ArgumentNullException"><paramref name="address"/> is null.</exception>
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
public static Task SendWolAsync(this PhysicalAddress address, IPEndPoint target) => address.SendWolAsync(target, null);
/// <summary>Sends a Wake On LAN signal (magic packet) to a specific IP end point with the physical address.</summary>
/// <param name="address">The instance of the physical address that should be used in the magic packet.</param>
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
/// <param name="password">The SecureOn password of the client.</param>
/// <exception cref="ArgumentNullException"><paramref name="address"/> is null.</exception>
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
public static Task SendWolAsync(this PhysicalAddress address, IPEndPoint target, SecureOnPassword password)
{
if (address == null)
throw new ArgumentNullException(nameof(address));
return target.SendWolAsync(address.GetAddressBytes(), password);
}
#endregion
#region common
/// <summary>Gets the type (<see cref="PhysicalAddressAdministrator"/>) of the <see cref="PhysicalAddress" />.</summary>
/// <param name="address">The address.</param>
/// <exception cref="ArgumentNullException"><paramref name="address"/> is null.</exception>
/// <returns>The <see cref="PhysicalAddressType" /> of the physical addess (MAC address).</returns>
public static PhysicalAddressType GetAddressType(this PhysicalAddress address)
{
if (address == null)
throw new ArgumentNullException(nameof(address));
var bytes = address.GetAddressBytes();
if (bytes == null || bytes.Length < 1)
throw new ArgumentException($"Invalid {nameof(address)}.");
return (bytes[0] & 0x1) == 0 ? PhysicalAddressType.Unicast : PhysicalAddressType.Multicast;
}
/// <summary>Gets the administrator (<see cref="PhysicalAddressAdministrator"/>) of the <see cref="PhysicalAddress" />.</summary>
/// <param name="address">The address.</param>
/// <exception cref="ArgumentNullException"><paramref name="address"/> is null.</exception>
/// <returns>The <see cref="PhysicalAddressAdministrator" /> of the physical addess (MAC address).</returns>
public static PhysicalAddressAdministrator GetAddressAdministrator(this PhysicalAddress address)
{
if (address == null)
throw new ArgumentNullException(nameof(address));
var bytes = address.GetAddressBytes();
if (bytes == null || bytes.Length < 1)
throw new ArgumentException($"Invalid {nameof(address)}.");
return (bytes[0] & 0x2) == 0 ? PhysicalAddressAdministrator.Global : PhysicalAddressAdministrator.Local;
}
#endregion
}
}
+34
View File
@@ -0,0 +1,34 @@
namespace System.Net
{
/// <summary>
/// Der Administrator der physikalischen Adresse gibt an, ob die Adresse globally unique oder local administrated ist.
/// </summary>
public enum PhysicalAddressAdministrator
{
/// <summary>
/// Die Adresse ist global einzigartig (nach der OUI).
/// </summary>
Global,
/// <summary>
/// Die Adresse ist lokal administriert.
/// </summary>
Local
}
/// <summary>
/// Der Typ der physikalischen Adresse gibt an, ob es um eine UNicast oder Multicast-Adresse handelt.
/// </summary>
public enum PhysicalAddressType
{
/// <summary>
/// Bezeichnet eine Unicast-Adresse.
/// </summary>
Unicast,
/// <summary>
/// Bezeichnet eine Multicast-Adresse
/// </summary>
Multicast
}
}
+4
View File
@@ -0,0 +1,4 @@
using System.Runtime.CompilerServices;
using System;
[assembly: InternalsVisibleTo("WakeOnLan.Tests")]
+95
View File
@@ -0,0 +1,95 @@
namespace System.Net
{
/// <summary>Provides a SecureOn password.</summary>
[Serializable]
public sealed class SecureOnPassword
{
private readonly byte[] _password;
/// <summary>Initializes a new instance of <see cref="SecureOnPassword"/> with the given password.</summary>
/// <param name="password">The password as <see cref="Byte"/> array.</param>
/// <exception cref="ArgumentNullException"><paramref name="password"/> is null.</exception>
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array password is not 6.</exception>
public SecureOnPassword(byte[] password)
{
if (password == null)
throw new ArgumentNullException(nameof(password));
if (password.Length != 6)
throw new ArgumentException(Localization.ArgumentExceptionInvalidPasswordLength);
_password = password;
}
/// <summary>Gets the buffer of the password.</summary>
public byte[] GetPasswordBytes()
{
if (_password == null)
return null;
var buffer = new byte[_password.Length];
Array.Copy(_password, buffer, 0);
return buffer;
}
/// <summary>Initializes a new instance of <see cref="SecureOnPassword"/> with the given password.</summary>
/// <param name="password">The password as <see cref="String"/>.</param>
/// <exception cref="ArgumentNullException"><paramref name="password"/> is null.</exception>
/// <remarks>Uses <see cref="Text.Encoding.Default" /> as encoding.</remarks>
public SecureOnPassword(string password)
: this(password, Text.Encoding.Default)
{ }
/// <summary>Initializes a new instance of <see cref="SecureOnPassword"/> with the given password.</summary>
/// <param name="password">The password as <see cref="String"/>.</param>
/// <param name="encoding">The <see cref="Text.Encoding"/> instance to use for the password.</param>
/// <exception cref="ArgumentNullException"><paramref name="password"/> is null.</exception>
/// <exception cref="ArgumentNullException"><paramref name="encoding"/> is null.</exception>
/// <exception cref="ArgumentException">The <see cref="Byte"/> array wich is created using the password has more elements than 6.</exception>
public SecureOnPassword(string password, Text.Encoding encoding)
{
if (password == null)
throw new ArgumentNullException(nameof(password));
if (encoding == null)
throw new ArgumentNullException(nameof(encoding));
if (string.IsNullOrEmpty(password))
_password = new byte[6];
var bytes = encoding.GetBytes(password);
if (bytes.Length > 6)
throw new ArgumentException(Localization.ArgumentExceptionInvalidPasswordLength);
_password = new byte[6];
for (int i = 0; i < bytes.Length; i++)
_password[i] = bytes[i];
if (bytes.Length < 6)
{
for (int i = bytes.Length - 1; i < 6; i++)
_password[i] = 0x00;
}
}
/// <summary>Converts the <see cref="SecureOnPassword"/> to dash notation.</summary>
/// <returns>A <see cref="String"/> representing the <see cref="SecureOnPassword"/> as dash notation.</returns>
public override string ToString() => ToString("X2");
/// <summary>Converts the <see cref="SecureOnPassword"/> to dash notation.</summary>
/// <returns>A <see cref="String"/> representing the <see cref="SecureOnPassword"/> as dash notation.</returns>
private string ToString(string format)
{
var f = new string[6];
for (int i = 0; i < f.Length; i++)
f[i] = _password[i].ToString(format);
return string.Join("-", f);
}
/// <summary>Converts the <see cref="SecureOnPassword"/> to dash notation.</summary>
/// <returns>A <see cref="String"/> representing the <see cref="SecureOnPassword"/> as dash notation.</returns>
public string ToString(IFormatProvider format)
{
var f = new string[6];
for (int i = 0; i < f.Length; i++)
f[i] = _password[i].ToString(format);
return string.Join("-", f);
}
}
}
+287
View File
@@ -0,0 +1,287 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
namespace System.Net.Topology
{
internal static class ByteArrayExtensions
{
internal static IEnumerable<bool> ToBitStream(this byte[] bytes, bool fromLeft)
{
if (bytes == null)
throw new ArgumentNullException(nameof(bytes));
if (fromLeft)
{
for (int i = 0; i < bytes.Length; ++i)
{
byte tmp = bytes[i].ReverseBits();
for (int j = 0; j < 8; ++j)
{
yield return (tmp & 1) == 1;
tmp >>= 1;
}
}
}
else
{
for (int i = bytes.Length - 1; i >= 0; --i)
{
byte tmp = bytes[i];
for (int j = 0; j < 8; ++j)
{
yield return (tmp & 1) == 1;
tmp >>= 1;
}
}
}
}
private static int CountFromSide(byte[] bits, bool value, bool fromleft)
{
int counter = 0;
var str = bits.ToBitStream(fromleft);
foreach (var bit in str)
{
if (bit == value)
++counter;
else return counter;
}
return counter;
}
internal static int CountFromLeft(this byte[] bits, bool value)
{
if (bits == null)
throw new ArgumentNullException(nameof(bits));
return CountFromSide(bits, value, true);
}
internal static int CountFromRight(this byte[] bits, bool value)
{
if (bits == null)
throw new ArgumentNullException(nameof(bits));
return CountFromSide(bits, value, false);
}
internal static string ToBinaryString(this byte[] bits, char separator)
{
if (bits == null)
throw new ArgumentNullException(nameof(bits));
const int radix = 2;
const int padding = 8;
const char paddingChar = '0';
var sb = new StringBuilder();
sb.Append(Convert.ToString(bits[0], radix).PadLeft(padding, paddingChar)).Append(separator);
sb.Append(Convert.ToString(bits[1], radix).PadLeft(padding, paddingChar)).Append(separator);
sb.Append(Convert.ToString(bits[2], radix).PadLeft(padding, paddingChar)).Append(separator);
sb.Append(Convert.ToString(bits[3], radix).PadLeft(padding, paddingChar));
return sb.ToString();
}
internal static string ToBinaryString(this byte[] bits)
{
if (bits == null)
throw new ArgumentNullException(nameof(bits));
const int radix = 2;
const int padding = 8;
const char paddingChar = '0';
var sb = new StringBuilder();
sb.Append(Convert.ToString(bits[0], radix).PadLeft(padding, paddingChar));
sb.Append(Convert.ToString(bits[1], radix).PadLeft(padding, paddingChar));
sb.Append(Convert.ToString(bits[2], radix).PadLeft(padding, paddingChar));
sb.Append(Convert.ToString(bits[3], radix).PadLeft(padding, paddingChar));
return sb.ToString();
}
internal static bool RepresentsValidNetMask(this byte[] bits)
{
if (bits == null)
throw new ArgumentNullException(nameof(bits));
int fromLeft = bits.CountFromLeft(true);
int fromRight = bits.CountFromRight(false);
// Sum of all counted indexes schloud be equal the whole length
return (fromLeft + fromRight) == (8 * NetMask.MaskLength);
}
internal static byte[] And(this byte[] b1, byte[] b2)
{
if (b1 == null)
throw new ArgumentNullException(nameof(b1));
if (b2 == null)
throw new ArgumentNullException(nameof(b2));
if (b1.Length == 1 && b2.Length == 1)
{
int ib1 = b1[0];
int ib2 = b2[0];
return new[] { (byte)(ib1 & ib2) };
}
if (b1.Length == 2 && b2.Length == 2)
{
var sb1 = BitConverter.ToInt16(b1, 0);
var sb2 = BitConverter.ToInt16(b2, 0);
return BitConverter.GetBytes((short)(sb1 & sb2));
}
if (b1.Length == 4 && b2.Length == 4)
{
var ib1 = BitConverter.ToInt32(b1, 0);
var ib2 = BitConverter.ToInt32(b2, 0);
return BitConverter.GetBytes(ib1 & ib2);
}
if (b1.Length != b2.Length)
{
// Or maybe throw exception?
int maxIndex = Math.Max(b1.Length, b2.Length);
byte[] biggerArray = b1.Length > b2.Length ? b1 : b2;
byte[] smallerArray = b1.Length <= b2.Length ? b1 : b2;
var paddedArray = new byte[maxIndex];
Buffer.BlockCopy(smallerArray, 0, paddedArray, 0, smallerArray.Length);
Debug.Assert(biggerArray.Length == paddedArray.Length);
return And(biggerArray, paddedArray);
}
var targetIndex = b1.Length;
var andedArray = new byte[targetIndex];
Buffer.BlockCopy(b1, 0, andedArray, 0, andedArray.Length);
for (int i = 0; i < targetIndex; ++i)
andedArray[i] &= b2[i];
return andedArray;
}
internal static byte[] Or(this byte[] b1, byte[] b2)
{
if (b1 == null)
throw new ArgumentNullException(nameof(b1));
if (b2 == null)
throw new ArgumentNullException(nameof(b2));
if (b1.Length == 1 && b2.Length == 1)
{
int ib1 = b1[0];
int ib2 = b2[0];
return new[] { (byte)(ib1 | ib2) };
}
if (b1.Length == 2 && b2.Length == 2)
{
var sb1 = BitConverter.ToInt16(b1, 0);
var sb2 = BitConverter.ToInt16(b2, 0);
return BitConverter.GetBytes((short)(sb1 | sb2));
}
if (b1.Length == 4 && b2.Length == 4)
{
var ib1 = BitConverter.ToInt32(b1, 0);
var ib2 = BitConverter.ToInt32(b2, 0);
return BitConverter.GetBytes(ib1 | ib2);
}
if (b1.Length != b2.Length)
{
// Or maybe throw exception?
int maxIndex = Math.Max(b1.Length, b2.Length);
byte[] biggerArray = b1.Length > b2.Length ? b1 : b2;
byte[] smallerArray = b1.Length <= b2.Length ? b1 : b2;
var paddedArray = new byte[maxIndex];
Buffer.BlockCopy(smallerArray, 0, paddedArray, 0, smallerArray.Length);
Debug.Assert(biggerArray.Length == paddedArray.Length);
return Or(biggerArray, paddedArray);
}
var targetIndex = b1.Length;
var oredArray = new byte[targetIndex];
Buffer.BlockCopy(b1, 0, oredArray, 0, oredArray.Length);
for (int i = 0; i < targetIndex; ++i)
oredArray[i] |= b2[i];
return oredArray;
}
internal static byte[] Xor(this byte[] b1, byte[] b2)
{
if (b1 == null)
throw new ArgumentNullException(nameof(b1));
if (b2 == null)
throw new ArgumentNullException(nameof(b2));
// TODO: Testing
if (b1.Length == 1 && b2.Length == 1)
{
int ib1 = b1[0];
int ib2 = b2[0];
return new[] { (byte)(ib1 ^ ib2) };
}
if (b1.Length == 2 && b2.Length == 2)
{
var sb1 = BitConverter.ToInt16(b1, 0);
var sb2 = BitConverter.ToInt16(b2, 0);
return BitConverter.GetBytes((short)(sb1 ^ sb2));
}
if (b1.Length == 4 && b2.Length == 4)
{
var ib1 = BitConverter.ToInt32(b1, 0);
var ib2 = BitConverter.ToInt32(b2, 0);
return BitConverter.GetBytes(ib1 ^ ib2);
}
if (b1.Length != b2.Length)
{
// Or maybe throw exception?
int maxIndex = Math.Max(b1.Length, b2.Length);
byte[] biggerArray = b1.Length > b2.Length ? b1 : b2;
byte[] smallerArray = b1.Length <= b2.Length ? b1 : b2;
var paddedArray = new byte[maxIndex];
Buffer.BlockCopy(smallerArray, 0, paddedArray, 0, smallerArray.Length);
Debug.Assert(biggerArray.Length == paddedArray.Length);
return Xor(biggerArray, paddedArray);
}
var targetIndex = b1.Length;
var xoredArray = new byte[targetIndex];
Buffer.BlockCopy(b1, 0, xoredArray, 0, xoredArray.Length);
for (int i = 0; i < targetIndex; ++i)
xoredArray[i] ^= b2[i];
return xoredArray;
}
internal static byte[] Not(this byte[] bits)
{
if (bits == null)
throw new ArgumentNullException(nameof(bits));
if (bits.Length == 4)
{
var i = BitConverter.ToInt32(bits, 0);
return BitConverter.GetBytes(~i);
}
var newBytes = new byte[bits.Length];
for (int i = 0; i < newBytes.Length; ++i)
newBytes[i] = unchecked((byte)(~bits[i]));
return newBytes;
}
}
}
+43
View File
@@ -0,0 +1,43 @@
namespace System.Net.Topology
{
internal static class ByteExtensions
{
public static byte[] BitReverseTable = {
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
};
public static byte ReverseBits(this byte toReverse) => BitReverseTable[toReverse];
}
}
+17
View File
@@ -0,0 +1,17 @@
namespace System.Net.Topology
{
/// <summary>Provides an interface for IP net masks.</summary>
public interface INetMask
{
/// <summary>Gets the length of the net mask in bits.</summary>
int AddressLength { get; }
/// <summary>Gets the amount of set bits from the left side (used in CIDR-Notation of net masks).</summary>
int Cidr { get; }
/// <summary>Gets the bits of the net mask instance as an BitArray object instance.</summary>
/// <returns>The bits of the net mask instance as an BitArray object instance</returns>
byte[] GetMaskBytes();
}
}
+167
View File
@@ -0,0 +1,167 @@
using System.Collections.Generic;
using System.Diagnostics;
namespace System.Net.Topology
{
/// <summary>Provides extension methods for the <see cref="T:System.Net.IPAddress"/>.</summary>
public static class IPAddressExtensions
{
private const string OnlyIPv4Supported = "Only IPv4 is currently supported";
/// <summary>Enumerates through the siblings of an <see cref="T:System.Net.IPAddress"/> in a network. Compliant to RFC 950 (2^n-2).</summary>
/// <param name="address">The address</param>
/// <param name="mask">The net mask of the network</param>
public static IEnumerable<IPAddress> GetSiblings(this IPAddress address, NetMask mask)
{
return GetSiblings(address, mask, SiblingOptions.ExcludeUnusable);
}
/// <summary>Enumerates through the siblings of an <see cref="T:System.Net.IPAddress"/> in a network.</summary>
/// <param name="address">The address</param>
/// <param name="mask">The net mask of the network</param>
/// <param name="options">Options which addresses to include an which not</param>
public static IEnumerable<IPAddress> GetSiblings(this IPAddress address, NetMask mask, SiblingOptions options)
{
if (address == null)
throw new ArgumentNullException(nameof(address));
if (mask == null)
throw new ArgumentNullException(nameof(mask));
if (address.AddressFamily != Sockets.AddressFamily.InterNetwork)
throw new NotSupportedException(OnlyIPv4Supported);
bool includeSelf = BitHelper.IsOptionSet(options, SiblingOptions.IncludeSelf);
bool includeBroadcast = BitHelper.IsOptionSet(options, SiblingOptions.IncludeBroadcast);
bool includeNetworkIdentifier = BitHelper.IsOptionSet(options, SiblingOptions.IncludeNetworkIdentifier);
bool alreadyReturnedSelf = false;
var netPrefix = address.GetNetworkPrefix(mask);
if (includeNetworkIdentifier)
{
netPrefix = address.GetNetworkPrefix(mask);
if (netPrefix.Equals(address))
alreadyReturnedSelf = true;
yield return netPrefix;
}
var selfAddressBytes = address.GetAddressBytes();
var netPrefixBytes = netPrefix.GetAddressBytes();
int cidr = mask.Cidr;
uint maxHosts = 0xFFFFFFFF;
if (cidr > 0)
maxHosts = (uint)(1 << (8 * NetMask.MaskLength - cidr)) - 1;
var hostBytes = new byte[NetMask.MaskLength];
for (int hostPart = 1; hostPart < maxHosts; ++hostPart)
{
unchecked
{
hostBytes[0] = (byte)(hostPart >> 24);
hostBytes[1] = (byte)(hostPart >> 16);
hostBytes[2] = (byte)(hostPart >> 8);
hostBytes[3] = (byte)(hostPart >> 0);
}
Debug.WriteLine("HostPart: " + hostPart.ToString("X2").PadLeft(8, '0') + " (" + BitConverter.ToString(hostBytes) + ")");
var nextIpBytes = netPrefixBytes.Or(hostBytes);
var nextIp = new IPAddress(nextIpBytes);
if (!alreadyReturnedSelf)
{
if (includeSelf)
{
if (nextIpBytes[0] == selfAddressBytes[0]
&& nextIpBytes[1] == selfAddressBytes[1]
&& nextIpBytes[2] == selfAddressBytes[2]
&& nextIpBytes[3] == selfAddressBytes[3])
alreadyReturnedSelf = true;
yield return nextIp;
}
else if (nextIpBytes[0] != selfAddressBytes[0]
|| nextIpBytes[1] != selfAddressBytes[1]
|| nextIpBytes[2] != selfAddressBytes[2]
|| nextIpBytes[3] != selfAddressBytes[3])
yield return nextIp;
}
else
yield return nextIp;
}
if (includeBroadcast)
{
var broadcastAddress = address.GetBroadcastAddress(mask);
if (!address.Equals(broadcastAddress) || (address.Equals(broadcastAddress) && !alreadyReturnedSelf))
yield return broadcastAddress;
}
}
/// <summary>Gets the network prefix of an <see cref="T:System.Net.IPAddress"/>.</summary>
/// <param name="address">The address</param>
/// <param name="mask">The net mask of the network</param>
/// <returns>The network prefix of an <see cref="T:System.Net.IPAddress"/></returns>
public static IPAddress GetNetworkPrefix(this IPAddress address, NetMask mask)
{
if (address == null)
throw new ArgumentNullException(nameof(address));
if (mask == null)
throw new ArgumentNullException(nameof(mask));
if (address.AddressFamily != Sockets.AddressFamily.InterNetwork)
throw new NotSupportedException(OnlyIPv4Supported);
return mask & address;
}
/// <summary>Gets the broadcast address of an <see cref="T:System.Net.IPAddress"/>.</summary>
/// <param name="address">The address</param>
/// <param name="mask">The net mask of the network</param>
/// <returns>The broadcast address of an <see cref="T:System.Net.IPAddress"/></returns>
public static IPAddress GetBroadcastAddress(this IPAddress address, NetMask mask)
{
if (address == null)
throw new ArgumentNullException("address");
if (mask == null)
throw new ArgumentNullException("mask");
if (address.AddressFamily != Sockets.AddressFamily.InterNetwork)
throw new NotSupportedException(OnlyIPv4Supported);
// TODO: Test
var ipBytes = address.GetAddressBytes();
var notMaskBytes = mask.GetMaskBytes().Not();
var broadcastAddressBytes = notMaskBytes.Or(ipBytes);
return new IPAddress(broadcastAddressBytes);
}
/// <summary>Gets the host identifier (rest) an <see cref="T:System.Net.IPAddress"/>.</summary>
/// <param name="address">The address</param>
/// <param name="mask">The net mask of the network</param>
/// <returns>The host identifier (rest) an <see cref="T:System.Net.IPAddress"/></returns>
public static IPAddress GetHostIdentifier(this IPAddress address, NetMask mask)
{
if (address == null)
throw new ArgumentNullException(nameof(address));
if (mask == null)
throw new ArgumentNullException(nameof(mask));
if (address.AddressFamily != Sockets.AddressFamily.InterNetwork)
throw new NotSupportedException(OnlyIPv4Supported);
var maskBits = mask.GetMaskBytes();
var ipBits = address.GetAddressBytes();
// ~Mask & IP
var retVal = maskBits.Not().And(ipBits);
var bytes = new byte[NetMask.MaskLength];
Buffer.BlockCopy(retVal, 0, bytes, 0, bytes.Length);
return new IPAddress(bytes);
}
}
}
+312
View File
@@ -0,0 +1,312 @@
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
namespace System.Net.Topology
{
// TODO: Use Span<T> when available (instead of byte arrays)
/// <summary>Represents an IPv4 net mask.</summary>
[StructLayout(LayoutKind.Explicit)]
public struct NetMask : INetMask, IEquatable<NetMask>
{
[FieldOffset(0)]
private readonly uint _mask;
#region byte-wise fields
// We are assuming here, that the byte-ordering is like on a normal x86 system
[FieldOffset(3)]
private readonly byte _maskB0;
[FieldOffset(2)]
private readonly byte _maskB1;
[FieldOffset(1)]
private readonly byte _maskB2;
[FieldOffset(0)]
private readonly byte _maskB3;
#endregion
internal const int MaskLength = 4;
/// <summary>Represents an empty IPv4 NetMask (all bits set to 0).</summary>
public static NetMask Empty { get; } = new NetMask();
/// <summary>Gets the length of the net mask in bits.</summary>
public int AddressLength => MaskLength * 8;
/// <summary>Gets the amount of set bits from the left side (used in CIDR-Notation of net masks).</summary>
public int Cidr => GetCidr(_mask);
#region Ctors
/// <summary>Creates a new instance of <see cref="T:System.Net.Topology.NetMask"/> cloning an existing instance of <see cref="T:System.Net.Topology.NetMask"/>.</summary>
public NetMask(NetMask mask)
{
if (mask == null)
throw new ArgumentNullException(nameof(mask));
_maskB0 = _maskB1 = _maskB2 = _maskB3 = 0;
_mask = mask._mask;
}
/// <summary>Creates a new instance of <see cref="T:System.Net.Topology.NetMask"/> from an array of <see cref="System.Byte"/>.</summary>
public NetMask(byte[] value)
{
_maskB0 = _maskB1 = _maskB2 = _maskB3 = 0;
_mask = 0;
if (value == null || value.Length == 0) // maybe throw ArgumentNullException?
return;
if (value.Length != MaskLength)
throw new ArgumentException("Invalid mask length.");
CheckMaskBytes(value); // check if passed mask are a valid mask. if not, throw Exception
_maskB0 = value[0];
_maskB1 = value[1];
_maskB2 = value[2];
_maskB3 = value[3];
}
/// <summary>Creates a new instance of <see cref="T:System.Net.Topology.NetMask"/> from a given <see cref="T:System.Net.IPAddress"/>.</summary>
/// <param name="address">The IPv4 address.</param>
public NetMask(IPAddress address)
: this(address == null ? null : address.GetAddressBytes())
{ }
/// <summary>Creates a new instance of <see cref="T:System.Net.Topology.NetMask"/>.</summary>
/// <param name="m0">The first byte.</param>
/// <param name="m1">The second byte.</param>
/// <param name="m2">The third byte.</param>
/// <param name="m3">The fourth byte.</param>
public NetMask(byte m0, byte m1, byte m2, byte m3)
: this(new[] { m0, m1, m2, m3 })
{ }
/// <summary>Creates a new instance of <see cref="T:System.Net.Topology.NetMask"/>.</summary>
/// <param name="cidr">The mask represented by the CIDR notation integer.</param>
public NetMask(byte cidr)
{
// maybe change parameter type interpretation to CIDR?
if (cidr > MaskLength * 8)
throw new ArgumentException("Invalid CIDR length");
_maskB0 = _maskB1 = _maskB2 = _maskB3 = 0; // to keep init checks happy
_mask = GetUIntFromCidrValue(cidr);
}
private NetMask(uint ipv4Mask)
{
_maskB0 = _maskB1 = _maskB2 = _maskB3 = 0; // to keep init checks happy
_mask = ipv4Mask;
}
#endregion
private static void CheckMaskBytes(byte[] bytes)
{
if (!bytes.RepresentsValidNetMask())
throw new ArgumentException("The passed mask do not represent a valid net mask.");
}
/// <summary>Gets the bits of the net mask instance as an BitArray object instance.</summary>
/// <returns>The bits of the net mask instance as an BitArray object instance.</returns>
public byte[] GetMaskBytes() => new[] { _maskB0, _maskB1, _maskB2, _maskB3 };
private static int GetCidr(uint mask)
{
Debug.Assert(sizeof(uint) == MaskLength);
return mask.CountOnesFromLeft();
}
/// <summary>Extends the current <see cref="T:System.Net.Topology.NetMask"/> instance by a given value (CIDR-wise).</summary>
/// <param name="mask">The mask to use as a reference.</param>
/// <param name="value">The value.</param>
/// <remarks>Because <see cref="T:System.Net.Topology.NetMask"/> is a reference type, this method is static. If it were not like this, you could change the value of <see cref="T:System.Net.Topology.NetMask"/>.Empty, for example.</remarks>
public static NetMask Extend(NetMask mask, int value)
{
int currentCidr = mask.Cidr;
if (currentCidr >= MaskLength * 8)
return new NetMask(mask);
if (currentCidr <= 0)
currentCidr = 0;
int newLength = Math.Max(Math.Min(currentCidr + value, 32), 0);
var m = BytesFromCidrValue(newLength);
return new NetMask(m);
}
/// <summary>Abbreviates the current <see cref="T:System.Net.Topology.NetMask"/> instance by a given value (CIDR-wise).</summary>
/// <param name="mask">The mask to use as a reference.</param>
/// <param name="value">The value.</param>
/// <remarks>Because <see cref="T:System.Net.Topology.NetMask"/> is a reference type, this method is static. If it were not like this, you could change the value of <see cref="T:System.Net.Topology.NetMask"/>.Empty, for example.</remarks>
public static NetMask Abbreviate(NetMask mask, int value)
{
int currentCidr = mask.Cidr;
if (currentCidr < 1)
return new NetMask(mask);
if (currentCidr >= MaskLength * 8)
currentCidr = MaskLength * 8;
int newLength = Math.Max(Math.Min(currentCidr - value, 32), 0);
var m = BytesFromCidrValue(newLength);
return new NetMask(m);
}
/// <summary>Returns a value indicating whether the given array of <see cref="T:System.Byte"/> represents a valid net mask.</summary>
/// <returns>True if the given array of <see cref="T:System.Byte"/> represents a valid net mask, otherwise false.</returns>
public static bool GetIsValidNetMask(byte[] mask) => mask.RepresentsValidNetMask();
// TODO: Testing(!)
[Obsolete]
private static byte[] BytesFromCidrValue(int cidr)
{
int target = MaskLength * 8 - cidr;
int mask = 0;
for (int i = 0; i < target; ++i)
{
mask >>= 1;
mask |= unchecked((int)0x80000000);
}
var bytes = BitConverter.GetBytes(~mask);
return new[] {
bytes[0].ReverseBits(),
bytes[1].ReverseBits(),
bytes[2].ReverseBits(),
bytes[3].ReverseBits()
};
}
// TODO: Testing(!)
private static uint GetUIntFromCidrValue(int cidr) => UIntExtensions.CreateWithOnesFromLeft(cidr);
#region Operators
#region Equality
/// <summary>Returns a other indicating whether two instances of <see cref="T:System.Net.Topology.NetMask" /> are equal.</summary>
/// <param name="n1">The first other to compare.</param>
/// <param name="n2">The second other to compare.</param>
/// <returns>true if <paramref name="n1" /> and <paramref name="n2" /> are equal; otherwise, false.</returns>
public static bool operator ==(NetMask n1, NetMask n2)
{
if (ReferenceEquals(n1, n2))
return true;
if (((object)n1 == null) || ((object)n2 == null))
return false;
return n1.Equals(n2);
}
/// <summary>Returns a other indicating whether two instances of <see cref="T:System.Net.Topology.NetMask" /> are not equal.</summary>
/// <param name="n1">The first other to compare. </param>
/// <param name="n2">The second other to compare. </param>
/// <returns>true if <paramref name="n1" /> and <paramref name="n2" /> are not equal; otherwise, false.</returns>
public static bool operator !=(NetMask n1, NetMask n2) => !(n1 == n2); // Problem solved
#endregion
#region And
/// <summary>Bitwise combines a <see cref="T:System.Net.Topology.NetMask" /> instance and an <see cref="T:System.Net.IPAddress"/> the AND operation.</summary>
/// <param name="mask">The net mask.</param>
/// <param name="address">The IPAddress.</param>
/// <returns>The bitwised combination using the AND operation.</returns>
public static IPAddress operator &(IPAddress address, NetMask mask) => mask & address;
/// <summary>Bitwise combines a <see cref="T:System.Net.Topology.NetMask" /> instance and an <see cref="T:System.Net.IPAddress"/> the AND operation.</summary>
/// <param name="mask">The net mask.</param>
/// <param name="address">The IPAddress.</param>
/// <returns>The bitwised combination using the AND operation.</returns>
public static IPAddress BitwiseAnd(IPAddress address, NetMask mask) => mask & address;
/// <summary>Bitwise combines a <see cref="T:System.Net.Topology.NetMask" /> instance and an <see cref="T:System.Net.IPAddress"/> the AND operation.</summary>
/// <param name="mask">The net mask.</param>
/// <param name="address">The IPAddress.</param>
/// <returns>The bitwised combination using the AND operation.</returns>
public static IPAddress operator &(NetMask mask, IPAddress address)
{
var ipBytes = address == null
? new byte[MaskLength]
: address.GetAddressBytes();
var maskBytes = mask == null
? new byte[MaskLength]
: new byte[] { mask._maskB0, mask._maskB1, mask._maskB2, mask._maskB3 };
byte[] combinedBytes = maskBytes.And(ipBytes);
return new IPAddress(combinedBytes);
}
/// <summary>Bitwise combines a <see cref="T:System.Net.Topology.NetMask" /> instance and an <see cref="T:System.Net.IPAddress"/> the AND operation.</summary>
/// <param name="mask">The net mask.</param>
/// <param name="address">The IPAddress.</param>
/// <returns>The bitwised combination using the AND operation.</returns>
public static IPAddress BitwiseAnd(NetMask mask, IPAddress address) => mask & address;
/// <summary>Bitwise combines the two instances of <see cref="T:System.Net.Topology.NetMask" /> using the AND operation.</summary>
/// <param name="n1">The first other.</param>
/// <param name="n2">The second other.</param>
/// <returns>The bitwised combination using the AND operation.</returns>
public static NetMask operator &(NetMask n1, NetMask n2) => new NetMask(n1._mask & n2._mask);
/// <summary>Bitwise combines the two instances of <see cref="T:System.Net.Topology.NetMask" /> using the AND operation.</summary>
/// <param name="n1">The first other.</param>
/// <param name="n2">The second other.</param>
/// <returns>The bitwised combination using the AND operation.</returns>
public static NetMask BitwiseAnd(NetMask n1, NetMask n2) => n1 & n2;
#endregion
#region Or
/// <summary>Bitwise combines the two instances of <see cref="T:System.Net.Topology.NetMask" /> using the OR operation.</summary>
/// <param name="n1">The first other.</param>
/// <param name="n2">The second other.</param>
/// <returns>The bitwised combination using the OR operation.</returns>
public static NetMask operator |(NetMask n1, NetMask n2) => new NetMask(n1._mask | n2._mask);
/// <summary>Bitwise combines the two instances of <see cref="T:System.Net.Topology.NetMask" /> using the OR operation.</summary>
/// <param name="n1">The first other.</param>
/// <param name="n2">The second other.</param>
/// <returns>The bitwised combination using the OR operation.</returns>
public static NetMask BitwiseOr(NetMask n1, NetMask n2) => n1 | n2;
#endregion
#endregion
#region Common overrides
/// <summary>Converts the other of this instance to its equivalent string representation.</summary>
/// <returns>A string that represents the other of this instance.</returns>
/// <filterpriority>1</filterpriority>
public override string ToString()
{
var sb = new StringBuilder(4 * 3 + 3 * 3 + 32 + 3 + 3); // 255.255.255.255 (11111111111111111111111111111111)
var arr = new byte[] { _maskB0, _maskB1, _maskB2, _maskB3 };
var asString = arr.ToBinaryString('.');
sb.Append(arr[0]).Append('.').Append(arr[1]).Append('.').Append(arr[2]).Append('.').Append(arr[3]).Append(" (");
sb.Append(asString).Append(')');
return sb.ToString();
}
/// <summary>Returns a value indicating whether this instance and a specified <see cref="T:System.Object" /> represent the same type and other.</summary>
/// <returns>true if <paramref name="obj" /> is a <see cref="T:System.Net.Topology.NetMask" /> and equal to this instance; otherwise, false.</returns>
/// <param name="obj">The object to compare with this instance. </param>
/// <filterpriority>2</filterpriority>
public override bool Equals(object obj) => obj != null && obj is NetMask && Equals((NetMask)obj);
/// <summary>Returns a value indicating whether this instance and a specified <see cref="T:System.Net.Topology.NetMask" /> object represent the same other.</summary>
/// <returns>true if <paramref name="other" /> is equal to this instance; otherwise, false.</returns>
/// <param name="other">An object to compare to this instance.</param>
/// <filterpriority>2</filterpriority>
public bool Equals(NetMask other) => other._mask == _mask;
/// <summary>Returns the hash code for this instance.</summary>
/// <returns>A 32-bit signed integer hash code.</returns>
/// <filterpriority>2</filterpriority>
public override int GetHashCode() => unchecked((int)_mask);
#endregion
}
}
+36
View File
@@ -0,0 +1,36 @@
namespace System.Net.Topology
{
/// <summary>Provides extension methods for the <see cref="T:System.Net.Topology.NetMask"/>.</summary>
public static class NetMaskExtensions
{
/// <summary>Gets the number of siblings an <see cref="T:System.Net.IPAddress"/> can have in a given network. Compliant to RFC 950 (2^n-2).</summary>
/// <param name="mask">The net mask of the network</param>
/// <returns>The number of siblings an <see cref="T:System.Net.IPAddress"/> can have in the given network.</returns>
public static int GetSiblingCount(this NetMask mask) => GetSiblingCount(mask, SiblingOptions.ExcludeUnusable);
/// <summary>Gets the number of siblings an <see cref="T:System.Net.IPAddress"/> can have in a given network.</summary>
/// <param name="mask">The net mask of the network</param>
/// <param name="options">Options which addresses to include an which not</param>
/// <returns>The number of siblings an <see cref="T:System.Net.IPAddress"/> can have in the given network.</returns>
public static int GetSiblingCount(this NetMask mask, SiblingOptions options)
{
if (mask == null)
throw new ArgumentNullException(nameof(mask));
bool includeSelf = BitHelper.IsOptionSet(options, SiblingOptions.IncludeSelf);
bool includeBroadcast = BitHelper.IsOptionSet(options, SiblingOptions.IncludeBroadcast);
bool includeNetworkIdentifier = BitHelper.IsOptionSet(options, SiblingOptions.IncludeNetworkIdentifier);
var hostPartBits = mask.GetMaskBytes().CountFromRight(false);
var total = 1 << hostPartBits;
total -= includeSelf ? 0 : 1;
total -= includeBroadcast ? 0 : 1;
total -= includeNetworkIdentifier ? 0 : 1;
// TODO: Testing
return total;
}
}
}
+27
View File
@@ -0,0 +1,27 @@
namespace System.Net.Topology
{
/// <summary>Provides options for doing network sibling calculations using a net mask.</summary>
[Flags]
public enum SiblingOptions
{
/// <summary>Do not include the broadcast or net address neither the addess passed to the method.</summary>
ExcludeAll = 0,
/// <summary>Include the addess passed to the method.</summary>
IncludeSelf = 1,
/// <summary>Include the addess passed to the method. Compliant to RFC 950 (2^n-2).</summary>
ExcludeUnusable = IncludeSelf,
/// <summary>Include the broadcast address.</summary>
IncludeBroadcast = 2,
/// <summary>Include the net address.</summary>
IncludeNetworkIdentifier = 4,
/// <summary>Include all addresses possible. RFC 1878 (2^n).</summary>
IncludeAll = IncludeSelf | IncludeBroadcast | IncludeNetworkIdentifier
}
internal static class BitHelper
{
[Runtime.TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] // as if NGen will ever compile this assembly ;)
[Runtime.CompilerServices.MethodImpl(Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
internal static bool IsOptionSet(SiblingOptions value, SiblingOptions testValue) => (value & testValue) == testValue;
}
}
+39
View File
@@ -0,0 +1,39 @@
namespace System.Net.Topology
{
internal static class StringExtensions
{
// TODO: The following method uses unsafe stuff. We don't want to pass the /unsafe flag to the compiler, so we use a simple, safe method instead.
// As soon as .NET Standard with Span<T> and the new String.Create is available, we can make this faster and safe.
/*
internal static unsafe string Reverse(this string input)
{
int len = input.Length;
// Why allocate a char[] array on the heap when you won't use it
// outside of this method? Use the stack.
char* reversed = stackalloc char[len];
// Avoid bounds-checking performance penalties.
fixed (char* str = input)
{
int i = 0;
int j = i + len - 1;
while (i < len)
reversed[i++] = str[j--];
}
// Need to use this overload for the System.String constructor
// as providing just the char* pointer could result in garbage
// at the end of the string (no guarantee of null terminator).
return new string(reversed, 0, len);
}
*/
internal static string Reverse(this string input)
{
char[] chars = input.ToCharArray();
Array.Reverse(chars);
return new string(chars);
}
}
}
+41
View File
@@ -0,0 +1,41 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
namespace System.Net.Topology
{
internal static class UIntExtensions
{
// TODO: Tests
public static int CountOnesFromLeft(this uint value)
{
var occurences = 0;
for (uint i = 1u << 31; i >= 0; i >>= 1)
{
if ((i & value) != 0)
++occurences;
else
break;
}
return occurences;
}
// TODO: Tests
public static uint CreateWithOnesFromLeft(int count)
{
if (count > 32)
throw new ArgumentException("Cannot set more than 32 bits to one!");
var value = 0u;
var mask = 1u << 31;
for (int i = 0; i < count; ++i)
{
value |= mask;
mask >>= 1;
}
return value;
}
}
}
+26
View File
@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Authors>Niklas Mollenhauer</Authors>
<PackageVersion>2.0.2</PackageVersion>
<Description>Library for Sending magic packets and performing IP address operations.</Description>
<PackageLicenseExpression>LGPL-3.0-only</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/nikeee/wake-on-lan</PackageProjectUrl>
<RepositoryUrl>https://github.com/nikeee/wake-on-lan.git</RepositoryUrl>
<PackageTags>WakeOnLan, magic packets</PackageTags>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<RootNamespace>System.Net</RootNamespace>
</PropertyGroup>
<PropertyGroup>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CSharp" Version="4.6.0" />
<PackageReference Include="System.Runtime.Serialization.Formatters" Version="4.3.0" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
</ItemGroup>
</Project>