Refactor address classes
This commit is contained in:
parent
d7ccd3069f
commit
912945a142
11 changed files with 199 additions and 92 deletions
35
src/IPMeow.Lib/Address/IPv4Address.cs
Normal file
35
src/IPMeow.Lib/Address/IPv4Address.cs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
|
||||||
|
namespace IPMeow.Lib.Address;
|
||||||
|
|
||||||
|
public class IPv4Address
|
||||||
|
{
|
||||||
|
public IPv4Address(byte[] bytes)
|
||||||
|
{
|
||||||
|
if (bytes.Length != 4)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Invalid byte length.");
|
||||||
|
}
|
||||||
|
|
||||||
|
_addr = BitConverter.ToUInt32(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IPv4Address(long address)
|
||||||
|
{
|
||||||
|
_addr = (uint)address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IPv4Address(IPAddress address)
|
||||||
|
{
|
||||||
|
if (address.AddressFamily != AddressFamily.InterNetwork)
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"Invalid address type: {address.AddressFamily}. Expected IPv4.");
|
||||||
|
}
|
||||||
|
|
||||||
|
_addr = BitConverter.ToUInt32(address.GetAddressBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly uint _addr;
|
||||||
|
public static implicit operator IPAddress(IPv4Address addr) => new(addr._addr);
|
||||||
|
}
|
30
src/IPMeow.Lib/Address/IPv6Address.cs
Normal file
30
src/IPMeow.Lib/Address/IPv6Address.cs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
|
||||||
|
namespace IPMeow.Lib.Address;
|
||||||
|
|
||||||
|
public class IPv6Address
|
||||||
|
{
|
||||||
|
public IPv6Address(byte[] address)
|
||||||
|
{
|
||||||
|
if (address.Length != 16)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Invalid address. Expected 16 bytes.");
|
||||||
|
}
|
||||||
|
|
||||||
|
_addr = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IPv6Address(IPAddress address)
|
||||||
|
{
|
||||||
|
if (address.AddressFamily != AddressFamily.InterNetworkV6)
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"Invalid address type: {address.AddressFamily}. Expected IPv6.");
|
||||||
|
}
|
||||||
|
|
||||||
|
_addr = address.GetAddressBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly byte[] _addr;
|
||||||
|
public static implicit operator IPAddress(IPv6Address addr) => new(addr._addr);
|
||||||
|
}
|
104
src/IPMeow.Lib/Address/MacAddress.cs
Normal file
104
src/IPMeow.Lib/Address/MacAddress.cs
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
namespace IPMeow.Lib.Address;
|
||||||
|
|
||||||
|
public readonly struct MacAddress
|
||||||
|
{
|
||||||
|
public MacAddress(byte[] addr)
|
||||||
|
{
|
||||||
|
if (addr.Length != 6)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Invalid address bytes.");
|
||||||
|
}
|
||||||
|
|
||||||
|
addrBytes = addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MacAddress Parse(byte[] addr)
|
||||||
|
{
|
||||||
|
if (TryParse(addr, out MacAddress? mac))
|
||||||
|
{
|
||||||
|
return mac.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ArgumentException("Invalid address byte length. Expected 6 octets.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MacAddress Parse(string addr)
|
||||||
|
{
|
||||||
|
if (TryParse(addr, out MacAddress? mac))
|
||||||
|
{
|
||||||
|
return mac.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new FormatException("Invalid address format.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryParse(byte[] addr, [NotNullWhen(true)] out MacAddress? mac)
|
||||||
|
{
|
||||||
|
mac = null;
|
||||||
|
|
||||||
|
if (addr.Length != 6)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mac = new(addr);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryParse(string addr, [NotNullWhen(true)] out MacAddress? mac)
|
||||||
|
{
|
||||||
|
mac = null;
|
||||||
|
|
||||||
|
string[] bytes = addr.Split(":");
|
||||||
|
|
||||||
|
if (bytes.Length != 6)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Invalid address length. Expected 6 octets.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var addrBytes = bytes.Select(byteStr =>
|
||||||
|
{
|
||||||
|
if (byte.TryParse(byteStr, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out byte b))
|
||||||
|
{
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ArgumentException($"{byteStr} is not a valid hex byte.");
|
||||||
|
}).ToArray();
|
||||||
|
|
||||||
|
mac = new(addrBytes);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly byte[] addrBytes;
|
||||||
|
|
||||||
|
public override readonly bool Equals([NotNullWhen(true)] object? obj)
|
||||||
|
{
|
||||||
|
return obj is MacAddress addr && this.addrBytes.SequenceEqual(addr.addrBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(MacAddress a, MacAddress b)
|
||||||
|
{
|
||||||
|
return a.addrBytes.SequenceEqual(b.addrBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(MacAddress a, MacAddress b)
|
||||||
|
{
|
||||||
|
return !(a == b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override readonly string ToString()
|
||||||
|
{
|
||||||
|
return string.Join(':', addrBytes.Select(b => b.ToString("x2")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return addrBytes.GetHashCode();
|
||||||
|
}
|
||||||
|
}
|
10
src/IPMeow.Lib/Address/Network.cs
Normal file
10
src/IPMeow.Lib/Address/Network.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace IPMeow.Lib.Address;
|
||||||
|
|
||||||
|
public abstract class Network
|
||||||
|
{
|
||||||
|
public abstract bool IsInNetwork(IPAddress addr);
|
||||||
|
|
||||||
|
public abstract bool IsSubnetOf(Network n);
|
||||||
|
};
|
|
@ -1,8 +1,3 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace IPMeow.Lib;
|
namespace IPMeow.Lib;
|
||||||
|
|
||||||
public class BitEnumerator
|
public class BitEnumerator
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
using System;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.NetworkInformation;
|
using System.Net.NetworkInformation;
|
||||||
using System.Threading.Tasks;
|
using IPMeow.Lib.Address;
|
||||||
|
|
||||||
namespace IPMeow.Lib;
|
namespace IPMeow.Lib.Host;
|
||||||
|
|
||||||
public class Host : IBindable
|
public class Host : IBindable
|
||||||
{
|
{
|
||||||
|
[Key]
|
||||||
public required string Id { get; set; }
|
public required string Id { get; set; }
|
||||||
|
|
||||||
public DateTime? LastPing { get; set; }
|
public DateTime? LastPing { get; set; }
|
||||||
public required IPAddressCollection Addresses { get; set; }
|
public required IPAddressCollection Addresses { get; set; }
|
||||||
public required MacAddress Mac { get; set; }
|
public required MacAddress Mac { get; set; }
|
||||||
}
|
}
|
10
src/IPMeow.Lib/Host/HostEntry.cs
Normal file
10
src/IPMeow.Lib/Host/HostEntry.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace IPMeow.Lib.Host;
|
||||||
|
|
||||||
|
public class HostEntry
|
||||||
|
{
|
||||||
|
public string? Name { get; set; }
|
||||||
|
public required IPAddress Address { get; set; }
|
||||||
|
public int Priority { get; set; } = 0;
|
||||||
|
}
|
|
@ -1,10 +1,7 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.NetworkInformation;
|
using System.Net.NetworkInformation;
|
||||||
using System.Threading.Tasks;
|
using IPMeow.Lib.Address;
|
||||||
|
|
||||||
namespace IPMeow.Lib;
|
namespace IPMeow.Lib.Host;
|
||||||
|
|
||||||
public interface IBindable
|
public interface IBindable
|
||||||
{
|
{
|
|
@ -1,14 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace IPMeow.Lib;
|
|
||||||
|
|
||||||
public class HostEntry
|
|
||||||
{
|
|
||||||
public string? Name { get; set; }
|
|
||||||
public required IPAddress Address { get; set; }
|
|
||||||
public int Priority { get; set; } = 0;
|
|
||||||
}
|
|
|
@ -1,58 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace IPMeow.Lib;
|
|
||||||
|
|
||||||
public readonly struct MacAddress
|
|
||||||
{
|
|
||||||
public MacAddress(byte[] addr)
|
|
||||||
{
|
|
||||||
if (addr.Length != 6)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Invalid address bytes.");
|
|
||||||
}
|
|
||||||
|
|
||||||
addrBytes = addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MacAddress(string addr)
|
|
||||||
{
|
|
||||||
string[] bytes = addr.Split(":");
|
|
||||||
|
|
||||||
if (bytes.Length != 6)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Invalid format.");
|
|
||||||
}
|
|
||||||
|
|
||||||
addrBytes = bytes.Select(byteStr =>
|
|
||||||
{
|
|
||||||
if (byte.TryParse(byteStr, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out byte b))
|
|
||||||
{
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new ArgumentException($"{byteStr} is not a valid hex byte.");
|
|
||||||
}).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly byte[] addrBytes;
|
|
||||||
|
|
||||||
public override readonly bool Equals([NotNullWhen(true)] object? obj)
|
|
||||||
{
|
|
||||||
return obj is MacAddress addr && this.addrBytes.SequenceEqual(addr.addrBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override readonly string ToString()
|
|
||||||
{
|
|
||||||
return string.Join(':', addrBytes.Select(b => b.ToString("x2")));
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
return addrBytes.GetHashCode();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,5 @@
|
||||||
using IPMeow.Lib;
|
using IPMeow.Lib;
|
||||||
using Xunit;
|
using IPMeow.Lib.Address;
|
||||||
|
|
||||||
namespace IPMeow.Test;
|
namespace IPMeow.Test;
|
||||||
|
|
||||||
|
@ -8,8 +8,8 @@ public class StructTests
|
||||||
[Fact]
|
[Fact]
|
||||||
public void MacAddressSerializationTest()
|
public void MacAddressSerializationTest()
|
||||||
{
|
{
|
||||||
var addrFromString = new MacAddress("fe:ed:de:ad:be:ef");
|
var addrFromString = MacAddress.Parse("fe:ed:de:ad:be:ef");
|
||||||
var addrFromBytes = new MacAddress(new byte[] { 0xfe, 0xed, 0xde, 0xad, 0xbe, 0xef });
|
var addrFromBytes = MacAddress.Parse(new byte[] { 0xfe, 0xed, 0xde, 0xad, 0xbe, 0xef });
|
||||||
|
|
||||||
Assert.Equal(addrFromString, addrFromBytes);
|
Assert.Equal(addrFromString, addrFromBytes);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue