using System;
using System.Buffers.Binary;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Net;
using System.Net.Sockets;
namespace FastGithub.Scanner
{
///
/// 表示IP范围
///
///
/// • 192.168.1.0/24
/// • 192.168.1.1-192.168.1.254
///
abstract class IPAddressRange : IEnumerable
{
///
/// 获取ip数量
///
public abstract int Size { get; }
///
/// 获取地址族
///
public abstract AddressFamily AddressFamily { get; }
///
/// 获取迭代器
///
///
public abstract IEnumerator GetEnumerator();
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
///
/// 从多个ip范围文本解析
///
///
///
public static IEnumerable From(IEnumerable ranges)
{
foreach (var item in ranges)
{
if (TryParse(item, out var range))
{
yield return range;
}
}
}
///
/// 尝试解析
///
///
///
///
public static bool TryParse(ReadOnlySpan range, [MaybeNullWhen(false)] out IPAddressRange value)
{
if (range.IsEmpty == false && IPNetwork.TryParse(range.ToString(), out var ipNetwork))
{
value = new CidrIPAddressRange(ipNetwork);
return true;
}
var index = range.IndexOf('-');
if (index >= 0)
{
var start = range.Slice(0, index);
var end = range[(index + 1)..];
if (IPAddress.TryParse(start, out var startIp) &&
IPAddress.TryParse(end, out var endIp) &&
startIp.AddressFamily == endIp.AddressFamily)
{
value = new SplitIPAddressRange(startIp, endIp);
return true;
}
}
value = null;
return false;
}
///
/// 192.168.1.0/24
///
private class CidrIPAddressRange : IPAddressRange
{
private readonly IPAddressCollection addressCollection;
private readonly AddressFamily addressFamily;
public override int Size => (int)this.addressCollection.Count;
public override AddressFamily AddressFamily => this.addressFamily;
public CidrIPAddressRange(IPNetwork network)
{
this.addressCollection = network.ListIPAddress(FilterEnum.All);
this.addressFamily = network.AddressFamily;
}
public override IEnumerator GetEnumerator()
{
return ((IEnumerable)this.addressCollection).GetEnumerator();
}
}
///
/// 192.168.1.1-192.168.1.254
///
private class SplitIPAddressRange : IPAddressRange
{
private readonly IPAddress start;
private readonly IPAddress end;
private readonly AddressFamily addressFamily;
public override AddressFamily AddressFamily => this.addressFamily;
public SplitIPAddressRange(IPAddress start, IPAddress end)
{
this.start = start;
this.end = end;
this.addressFamily = start.AddressFamily;
}
public override int Size
{
get
{
if (this.start.AddressFamily == AddressFamily.InterNetworkV6)
{
var startValue = BinaryPrimitives.ReadInt64BigEndian(this.start.GetAddressBytes());
var endValue = BinaryPrimitives.ReadInt64BigEndian(this.end.GetAddressBytes());
return (int)(endValue - startValue) + 1;
}
else
{
var startValue = BinaryPrimitives.ReadInt32BigEndian(this.start.GetAddressBytes());
var endValue = BinaryPrimitives.ReadInt32BigEndian(this.end.GetAddressBytes());
return endValue - startValue + 1;
}
}
}
public override IEnumerator GetEnumerator()
{
return this.GetIPAddresses().GetEnumerator();
}
private IEnumerable GetIPAddresses()
{
for (var i = 0; i < this.Size; i++)
{
var value = i;
yield return Add(this.start, value);
}
}
///
/// 添加值
///
///
///
///
private static IPAddress Add(IPAddress address, int value)
{
var span = address.GetAddressBytes().AsSpan();
var hostValue = BinaryPrimitives.ReadInt32BigEndian(span);
BinaryPrimitives.WriteInt32BigEndian(span, hostValue + value);
return new IPAddress(span);
}
}
}
}