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 { abstract class IPAddressRange : IEnumerable { public abstract int Size { get; } public abstract AddressFamily AddressFamily { get; } public abstract IEnumerator GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } 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 NetworkIPAddressRange(ipNetwork); return true; } var index = range.IndexOf('-'); if (index >= 0) { var start = range.Slice(0, index); var end = range.Slice(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; } private class NetworkIPAddressRange : IPAddressRange { private readonly IPAddressCollection addressCollection; private readonly AddressFamily addressFamily; public override int Size => (int)this.addressCollection.Count; public override AddressFamily AddressFamily => this.addressFamily; public NetworkIPAddressRange(IPNetwork network) { this.addressCollection = network.ListIPAddress(FilterEnum.All); this.addressFamily = network.AddressFamily; } public override IEnumerator GetEnumerator() { return ((IEnumerable)this.addressCollection).GetEnumerator(); } } 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); } } } }