119 lines
3.1 KiB
C#
119 lines
3.1 KiB
C#
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
|
|
{
|
|
sealed class IPRange : IEnumerable<IPAddress>
|
|
{
|
|
private readonly IPNetwork network;
|
|
|
|
public AddressFamily AddressFamily => this.network.AddressFamily;
|
|
|
|
public int Size => (int)this.network.Total;
|
|
|
|
private IPRange(IPNetwork network)
|
|
{
|
|
this.network = network;
|
|
}
|
|
|
|
public IEnumerator<IPAddress> GetEnumerator()
|
|
{
|
|
return new Enumerator(this.network);
|
|
}
|
|
|
|
IEnumerator IEnumerable.GetEnumerator()
|
|
{
|
|
return this.GetEnumerator();
|
|
}
|
|
|
|
private class Enumerator : IEnumerator<IPAddress>
|
|
{
|
|
private IPAddress? currrent;
|
|
private readonly IPNetwork network;
|
|
private readonly IPAddress maxAddress;
|
|
|
|
public Enumerator(IPNetwork network)
|
|
{
|
|
this.network = network;
|
|
this.maxAddress = Add(network.LastUsable, 1);
|
|
}
|
|
|
|
public IPAddress Current => this.currrent ?? throw new NotImplementedException();
|
|
|
|
object IEnumerator.Current => this.Current;
|
|
|
|
public void Dispose()
|
|
{
|
|
}
|
|
|
|
public bool MoveNext()
|
|
{
|
|
var value = this.currrent == null
|
|
? this.network.FirstUsable
|
|
: Add(this.currrent, 1);
|
|
|
|
if (value.Equals(maxAddress))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
this.currrent = value;
|
|
return true;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
this.currrent = null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 添加值
|
|
/// </summary>
|
|
/// <param name="ip"></param>
|
|
/// <param name="value"></param>
|
|
/// <returns></returns>
|
|
private static IPAddress Add(IPAddress ip, int value)
|
|
{
|
|
var span = ip.GetAddressBytes().AsSpan();
|
|
var hostValue = BinaryPrimitives.ReadInt32BigEndian(span);
|
|
BinaryPrimitives.WriteInt32BigEndian(span, hostValue + value);
|
|
return new IPAddress(span);
|
|
}
|
|
|
|
public static IEnumerable<IPRange> From(IEnumerable<string> networks)
|
|
{
|
|
foreach (var item in networks)
|
|
{
|
|
if (TryParse(item, out var value))
|
|
{
|
|
yield return value;
|
|
}
|
|
}
|
|
}
|
|
|
|
public static bool TryParse(ReadOnlySpan<char> network, [MaybeNullWhen(false)] out IPRange value)
|
|
{
|
|
if (network.IsEmpty == false && IPNetwork.TryParse(network.ToString(), out var ipNetwork))
|
|
{
|
|
value = new IPRange(ipNetwork);
|
|
return true;
|
|
}
|
|
|
|
value = null;
|
|
return false;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return this.network.ToString();
|
|
}
|
|
|
|
}
|
|
}
|