完善xml注释

This commit is contained in:
xljiulang 2021-06-17 23:39:51 +08:00
parent 72fe4ece58
commit d195641319
23 changed files with 345 additions and 25 deletions

View File

@ -8,6 +8,9 @@ namespace FastGithub
[AttributeUsage(AttributeTargets.Class)] [AttributeUsage(AttributeTargets.Class)]
public sealed class OptionsAttribute : Attribute public sealed class OptionsAttribute : Attribute
{ {
/// <summary>
/// 获取配置节点名称
/// </summary>
public string? SessionKey { get; } public string? SessionKey { get; }
/// <summary> /// <summary>
@ -20,7 +23,7 @@ namespace FastGithub
/// <summary> /// <summary>
/// 选项特性 /// 选项特性
/// </summary> /// </summary>
/// <param name="sessionKey"></param> /// <param name="sessionKey">配置节点名称</param>
public OptionsAttribute(string sessionKey) public OptionsAttribute(string sessionKey)
{ {
this.SessionKey = sessionKey; this.SessionKey = sessionKey;

View File

@ -7,20 +7,34 @@ using System.Threading.Tasks;
namespace FastGithub.Dns namespace FastGithub.Dns
{ {
/// <summary>
/// dns后台服务
/// </summary>
sealed class DnsHostedService : IHostedService sealed class DnsHostedService : IHostedService
{ {
private readonly DnsServer dnsServer; private readonly DnsServer dnsServer;
private readonly ILogger<DnsHostedService> logger; private readonly ILogger<DnsHostedService> logger;
/// <summary>
/// dns后台服务
/// </summary>
/// <param name="githubRequestResolver"></param>
/// <param name="options"></param>
/// <param name="logger"></param>
public DnsHostedService( public DnsHostedService(
GithubRequestResolver githubRequestResolver, GithubRequestResolver githubRequestResolver,
IOptions<DnsOptions> options, IOptions<DnsOptions> options,
ILogger<DnsHostedService> logger) ILogger<DnsHostedService> logger)
{ {
this.dnsServer = new DnsServer(githubRequestResolver, options.Value.UpStream); this.dnsServer = new DnsServer(githubRequestResolver, options.Value.UpStream);
this.logger = logger; this.logger = logger;
} }
/// <summary>
/// 启动dns服务
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public Task StartAsync(CancellationToken cancellationToken) public Task StartAsync(CancellationToken cancellationToken)
{ {
this.dnsServer.Listen(); this.dnsServer.Listen();
@ -28,6 +42,11 @@ namespace FastGithub.Dns
return Task.CompletedTask; return Task.CompletedTask;
} }
/// <summary>
/// 停止dns服务
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public Task StopAsync(CancellationToken cancellationToken) public Task StopAsync(CancellationToken cancellationToken)
{ {
this.dnsServer.Dispose(); this.dnsServer.Dispose();

View File

@ -3,11 +3,20 @@ using System.Net;
namespace FastGithub.Dns namespace FastGithub.Dns
{ {
/// <summary>
/// dns服务选项
/// </summary>
[Options("Dns")] [Options("Dns")]
sealed class DnsOptions sealed class DnsOptions
{ {
/// <summary>
/// 获取或设置上游ip地址
/// </summary>
public IPAddress UpStream { get; set; } = IPAddress.Parse("114.114.114.114"); public IPAddress UpStream { get; set; } = IPAddress.Parse("114.114.114.114");
/// <summary>
/// 获取或设置github相关域名的ip存活时长
/// </summary>
public TimeSpan GithubTTL { get; set; } = TimeSpan.FromMinutes(10d); public TimeSpan GithubTTL { get; set; } = TimeSpan.FromMinutes(10d);
} }
} }

View File

@ -11,13 +11,22 @@ using System.Threading.Tasks;
namespace FastGithub.Dns namespace FastGithub.Dns
{ {
/// <summary>
/// github相关域名解析器
/// </summary>
[Service(ServiceLifetime.Singleton)] [Service(ServiceLifetime.Singleton)]
sealed class GithubRequestResolver : IRequestResolver sealed class GithubRequestResolver : IRequestResolver
{ {
private readonly IGithubScanResults githubScanResults; private readonly IGithubScanResults githubScanResults;
private readonly IOptionsMonitor<DnsOptions> options; private readonly IOptionsMonitor<DnsOptions> options;
private readonly ILogger<GithubRequestResolver> logger; private readonly ILogger<GithubRequestResolver> logger;
/// <summary>
/// github相关域名解析器
/// </summary>
/// <param name="githubScanResults"></param>
/// <param name="options"></param>
/// <param name="logger"></param>
public GithubRequestResolver( public GithubRequestResolver(
IGithubScanResults githubScanResults, IGithubScanResults githubScanResults,
IOptionsMonitor<DnsOptions> options, IOptionsMonitor<DnsOptions> options,
@ -28,6 +37,12 @@ namespace FastGithub.Dns
this.logger = logger; this.logger = logger;
} }
/// <summary>
/// 解析域名
/// </summary>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public Task<IResponse> Resolve(IRequest request, CancellationToken cancellationToken = default) public Task<IResponse> Resolve(IRequest request, CancellationToken cancellationToken = default)
{ {
var response = Response.FromRequest(request); var response = Response.FromRequest(request);

View File

@ -3,6 +3,9 @@ using System.Net;
namespace FastGithub.Scanner namespace FastGithub.Scanner
{ {
/// <summary>
/// 域名与ip关系
/// </summary>
class DomainAddress : IEquatable<DomainAddress> class DomainAddress : IEquatable<DomainAddress>
{ {
/// <summary> /// <summary>
@ -15,6 +18,11 @@ namespace FastGithub.Scanner
/// </summary> /// </summary>
public IPAddress Address { get; } public IPAddress Address { get; }
/// <summary>
/// 域名与ip关系
/// </summary>
/// <param name="domain"></param>
/// <param name="address"></param>
public DomainAddress(string domain, IPAddress address) public DomainAddress(string domain, IPAddress address)
{ {
this.Domain = domain; this.Domain = domain;

View File

@ -4,16 +4,27 @@ using System.Threading.Tasks;
namespace FastGithub.Scanner namespace FastGithub.Scanner
{ {
/// <summary>
/// 域名与ip关系工厂
/// </summary>
[Service(ServiceLifetime.Singleton)] [Service(ServiceLifetime.Singleton)]
sealed class DomainAddressFacotry sealed class DomainAddressFacotry
{ {
private readonly IEnumerable<IDomainAddressProvider> providers; private readonly IEnumerable<IDomainAddressProvider> providers;
/// <summary>
/// 域名与ip关系工厂
/// </summary>
/// <param name="providers"></param>
public DomainAddressFacotry(IEnumerable<IDomainAddressProvider> providers) public DomainAddressFacotry(IEnumerable<IDomainAddressProvider> providers)
{ {
this.providers = providers; this.providers = providers;
} }
/// <summary>
/// 创建域名与ip的关系
/// </summary>
/// <returns></returns>
public async Task<IEnumerable<DomainAddress>> CreateDomainAddressesAsync() public async Task<IEnumerable<DomainAddress>> CreateDomainAddressesAsync()
{ {
var hashSet = new HashSet<DomainAddress>(); var hashSet = new HashSet<DomainAddress>();

View File

@ -12,12 +12,20 @@ using System.Threading.Tasks;
namespace FastGithub.Scanner.DomainMiddlewares namespace FastGithub.Scanner.DomainMiddlewares
{ {
/// <summary>
/// Github公开的域名与ip关系提供者
/// </summary>
[Service(ServiceLifetime.Singleton, ServiceType = typeof(IDomainAddressProvider))] [Service(ServiceLifetime.Singleton, ServiceType = typeof(IDomainAddressProvider))]
sealed class GithubMetaProvider : IDomainAddressProvider sealed class GithubMetaProvider : IDomainAddressProvider
{ {
private readonly IOptionsMonitor<GithubOptions> options; private readonly IOptionsMonitor<GithubOptions> options;
private readonly ILogger<GithubMetaProvider> logger; private readonly ILogger<GithubMetaProvider> logger;
/// <summary>
/// Github公开的域名与ip关系提供者
/// </summary>
/// <param name="options"></param>
/// <param name="logger"></param>
public GithubMetaProvider( public GithubMetaProvider(
IOptionsMonitor<GithubOptions> options, IOptionsMonitor<GithubOptions> options,
ILogger<GithubMetaProvider> logger) ILogger<GithubMetaProvider> logger)
@ -26,6 +34,10 @@ namespace FastGithub.Scanner.DomainMiddlewares
this.logger = logger; this.logger = logger;
} }
/// <summary>
/// 创建域名与ip的关系
/// </summary>
/// <returns></returns>
public async Task<IEnumerable<DomainAddress>> CreateDomainAddressesAsync() public async Task<IEnumerable<DomainAddress>> CreateDomainAddressesAsync()
{ {
var setting = this.options.CurrentValue.DominAddressProviders.GithubMetaProvider; var setting = this.options.CurrentValue.DominAddressProviders.GithubMetaProvider;
@ -51,11 +63,18 @@ namespace FastGithub.Scanner.DomainMiddlewares
return Enumerable.Empty<DomainAddress>(); return Enumerable.Empty<DomainAddress>();
} }
/// <summary>
/// github的meta结构
/// </summary>
private class Meta private class Meta
{ {
[JsonPropertyName("web")] [JsonPropertyName("web")]
public string[] Web { get; set; } = Array.Empty<string>(); public string[] Web { get; set; } = Array.Empty<string>();
/// <summary>
/// 转换为域名与ip关系
/// </summary>
/// <returns></returns>
public IEnumerable<DomainAddress> ToDomainAddresses() public IEnumerable<DomainAddress> ToDomainAddresses()
{ {
foreach (var range in IPAddressRange.From(this.Web).OrderBy(item => item.Size)) foreach (var range in IPAddressRange.From(this.Web).OrderBy(item => item.Size))

View File

@ -11,6 +11,9 @@ using System.Threading.Tasks;
namespace FastGithub.Scanner.DomainMiddlewares namespace FastGithub.Scanner.DomainMiddlewares
{ {
/// <summary>
/// ipaddress.com的域名与ip关系提供者
/// </summary>
[Service(ServiceLifetime.Singleton, ServiceType = typeof(IDomainAddressProvider))] [Service(ServiceLifetime.Singleton, ServiceType = typeof(IDomainAddressProvider))]
sealed class IPAddressComProvider : IDomainAddressProvider sealed class IPAddressComProvider : IDomainAddressProvider
{ {
@ -18,6 +21,11 @@ namespace FastGithub.Scanner.DomainMiddlewares
private readonly ILogger<IPAddressComProvider> logger; private readonly ILogger<IPAddressComProvider> logger;
private readonly Uri lookupUri = new("https://www.ipaddress.com/ip-lookup"); private readonly Uri lookupUri = new("https://www.ipaddress.com/ip-lookup");
/// <summary>
/// ipaddress.com的域名与ip关系提供者
/// </summary>
/// <param name="options"></param>
/// <param name="logger"></param>
public IPAddressComProvider( public IPAddressComProvider(
IOptionsMonitor<GithubOptions> options, IOptionsMonitor<GithubOptions> options,
ILogger<IPAddressComProvider> logger) ILogger<IPAddressComProvider> logger)
@ -26,6 +34,10 @@ namespace FastGithub.Scanner.DomainMiddlewares
this.logger = logger; this.logger = logger;
} }
/// <summary>
/// 创建域名与ip的关系
/// </summary>
/// <returns></returns>
public async Task<IEnumerable<DomainAddress>> CreateDomainAddressesAsync() public async Task<IEnumerable<DomainAddress>> CreateDomainAddressesAsync()
{ {
var setting = this.options.CurrentValue.DominAddressProviders.IPAddressComProvider; var setting = this.options.CurrentValue.DominAddressProviders.IPAddressComProvider;
@ -54,6 +66,12 @@ namespace FastGithub.Scanner.DomainMiddlewares
return result; return result;
} }
/// <summary>
/// 反查ip
/// </summary>
/// <param name="httpClient"></param>
/// <param name="domain"></param>
/// <returns></returns>
private async Task<List<IPAddress>> LookupAsync(HttpClient httpClient, string domain) private async Task<List<IPAddress>> LookupAsync(HttpClient httpClient, string domain)
{ {
var keyValue = new KeyValuePair<string?, string?>("host", domain); var keyValue = new KeyValuePair<string?, string?>("host", domain);

View File

@ -10,12 +10,20 @@ using System.Threading.Tasks;
namespace FastGithub.Scanner.DomainMiddlewares namespace FastGithub.Scanner.DomainMiddlewares
{ {
/// <summary>
/// 公共dns的域名与ip关系提供者
/// </summary>
[Service(ServiceLifetime.Singleton, ServiceType = typeof(IDomainAddressProvider))] [Service(ServiceLifetime.Singleton, ServiceType = typeof(IDomainAddressProvider))]
sealed class PublicDnsProvider : IDomainAddressProvider sealed class PublicDnsProvider : IDomainAddressProvider
{ {
private readonly IOptionsMonitor<GithubOptions> options; private readonly IOptionsMonitor<GithubOptions> options;
private readonly ILogger<PublicDnsProvider> logger; private readonly ILogger<PublicDnsProvider> logger;
/// <summary>
/// 公共dns的域名与ip关系提供者
/// </summary>
/// <param name="options"></param>
/// <param name="logger"></param>
public PublicDnsProvider( public PublicDnsProvider(
IOptionsMonitor<GithubOptions> options, IOptionsMonitor<GithubOptions> options,
ILogger<PublicDnsProvider> logger) ILogger<PublicDnsProvider> logger)
@ -24,6 +32,10 @@ namespace FastGithub.Scanner.DomainMiddlewares
this.logger = logger; this.logger = logger;
} }
/// <summary>
/// 创建域名与ip的关系
/// </summary>
/// <returns></returns>
public async Task<IEnumerable<DomainAddress>> CreateDomainAddressesAsync() public async Task<IEnumerable<DomainAddress>> CreateDomainAddressesAsync()
{ {
var setting = this.options.CurrentValue.DominAddressProviders.PublicDnsProvider; var setting = this.options.CurrentValue.DominAddressProviders.PublicDnsProvider;
@ -45,6 +57,12 @@ namespace FastGithub.Scanner.DomainMiddlewares
return result; return result;
} }
/// <summary>
/// 反查ip
/// </summary>
/// <param name="dns">dns服务器</param>
/// <param name="domains">域名</param>
/// <returns></returns>
private async Task<List<DomainAddress>> LookupAsync(string dns, IEnumerable<string> domains) private async Task<List<DomainAddress>> LookupAsync(string dns, IEnumerable<string> domains)
{ {
var client = new DnsClient(dns); var client = new DnsClient(dns);

View File

@ -3,14 +3,11 @@ using System.Net;
namespace FastGithub.Scanner namespace FastGithub.Scanner
{ {
/// <summary>
/// Github扫描上下文
/// </summary>
sealed class GithubContext : DomainAddress, IEquatable<GithubContext> sealed class GithubContext : DomainAddress, IEquatable<GithubContext>
{ {
private record Github(
string Domain,
IPAddress Address,
double AvailableRate,
double AvgElapsed);
/// <summary> /// <summary>
/// 获取或设置是否可用 /// 获取或设置是否可用
/// </summary> /// </summary>
@ -22,6 +19,11 @@ namespace FastGithub.Scanner
public GithubContextHistory History { get; } = new(); public GithubContextHistory History { get; } = new();
/// <summary>
/// Github扫描上下文
/// </summary>
/// <param name="domain"></param>
/// <param name="address"></param>
public GithubContext(string domain, IPAddress address) public GithubContext(string domain, IPAddress address)
: base(domain, address) : base(domain, address)
{ {
@ -41,5 +43,12 @@ namespace FastGithub.Scanner
this.History.AvgElapsed.TotalSeconds this.History.AvgElapsed.TotalSeconds
).ToString(); ).ToString();
} }
private record Github(
string Domain,
IPAddress Address,
double AvailableRate,
double AvgElapsed);
} }
} }

View File

@ -5,12 +5,20 @@ using System.Net;
namespace FastGithub.Scanner namespace FastGithub.Scanner
{ {
/// <summary>
/// GithubContext集合
/// </summary>
[Service(ServiceLifetime.Singleton)] [Service(ServiceLifetime.Singleton)]
sealed class GithubContextCollection : IGithubScanResults sealed class GithubContextCollection : IGithubScanResults
{ {
private readonly object syncRoot = new(); private readonly object syncRoot = new();
private readonly List<GithubContext> contextList = new(); private readonly List<GithubContext> contextList = new();
/// <summary>
/// 添加GithubContext
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public bool Add(GithubContext context) public bool Add(GithubContext context)
{ {
lock (this.syncRoot) lock (this.syncRoot)
@ -24,7 +32,10 @@ namespace FastGithub.Scanner
} }
} }
/// <summary>
/// 转换为数组
/// </summary>
/// <returns></returns>
public GithubContext[] ToArray() public GithubContext[] ToArray()
{ {
lock (this.syncRoot) lock (this.syncRoot)
@ -33,7 +44,12 @@ namespace FastGithub.Scanner
} }
} }
/// <summary>
/// 查询ip是否可用
/// </summary>
/// <param name="domain"></param>
/// <param name="address"></param>
/// <returns></returns>
public bool IsAvailable(string domain, IPAddress address) public bool IsAvailable(string domain, IPAddress address)
{ {
lock (this.syncRoot) lock (this.syncRoot)
@ -45,7 +61,7 @@ namespace FastGithub.Scanner
} }
/// <summary> /// <summary>
/// 查找又稳又快的ip /// 查找最优的ip
/// </summary> /// </summary>
/// <param name="domain"></param> /// <param name="domain"></param>
/// <returns></returns> /// <returns></returns>

View File

@ -4,8 +4,14 @@ using System.Linq;
namespace FastGithub.Scanner namespace FastGithub.Scanner
{ {
/// <summary>
/// GithubContext的扫描历史
/// </summary>
sealed class GithubContextHistory sealed class GithubContextHistory
{ {
/// <summary>
/// 最多保存最的近的10条记录
/// </summary>
private const int MAX_LOG_COUNT = 10; private const int MAX_LOG_COUNT = 10;
private record ScanLog(bool Available, TimeSpan Elapsed); private record ScanLog(bool Available, TimeSpan Elapsed);
@ -54,6 +60,11 @@ namespace FastGithub.Scanner
} }
} }
/// <summary>
/// 添加记录
/// </summary>
/// <param name="available">是否可用</param>
/// <param name="elapsed">扫描耗时</param>
public void Add(bool available, TimeSpan elapsed) public void Add(bool available, TimeSpan elapsed)
{ {
this.scanLogs.Enqueue(new ScanLog(available, elapsed)); this.scanLogs.Enqueue(new ScanLog(available, elapsed));

View File

@ -6,11 +6,19 @@ using System.Threading.Tasks;
namespace FastGithub namespace FastGithub
{ {
/// <summary>
/// 完整扫描后台服务
/// </summary>
sealed class GithubFullScanHostedService : BackgroundService sealed class GithubFullScanHostedService : BackgroundService
{ {
private readonly GithubScanService githubScanService; private readonly GithubScanService githubScanService;
private readonly IOptionsMonitor<GithubOptions> options; private readonly IOptionsMonitor<GithubOptions> options;
/// <summary>
/// 完整扫描后台服务
/// </summary>
/// <param name="githubScanService"></param>
/// <param name="options"></param>
public GithubFullScanHostedService( public GithubFullScanHostedService(
GithubScanService githubScanService, GithubScanService githubScanService,
IOptionsMonitor<GithubOptions> options) IOptionsMonitor<GithubOptions> options)
@ -19,7 +27,11 @@ namespace FastGithub
this.options = options; this.options = options;
} }
/// <summary>
/// 后台轮询扫描
/// </summary>
/// <param name="stoppingToken"></param>
/// <returns></returns>
protected override async Task ExecuteAsync(CancellationToken stoppingToken) protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{ {
while (stoppingToken.IsCancellationRequested == false) while (stoppingToken.IsCancellationRequested == false)

View File

@ -2,13 +2,25 @@
namespace FastGithub.Scanner namespace FastGithub.Scanner
{ {
/// <summary>
/// github选项
/// </summary>
[Options("Github")] [Options("Github")]
sealed class GithubOptions sealed class GithubOptions
{ {
/// <summary>
/// 扫描配置
/// </summary>
public ScanSetting Scan { get; set; } = new ScanSetting(); public ScanSetting Scan { get; set; } = new ScanSetting();
/// <summary>
/// 域名与ip关系提供者配置
/// </summary>
public DomainAddressProvidersSetting DominAddressProviders { get; set; } = new DomainAddressProvidersSetting(); public DomainAddressProvidersSetting DominAddressProviders { get; set; } = new DomainAddressProvidersSetting();
/// <summary>
/// 扫描配置
/// </summary>
public class ScanSetting public class ScanSetting
{ {
public TimeSpan FullScanInterval = TimeSpan.FromHours(2d); public TimeSpan FullScanInterval = TimeSpan.FromHours(2d);
@ -20,6 +32,9 @@ namespace FastGithub.Scanner
public TimeSpan HttpsScanTimeout { get; set; } = TimeSpan.FromSeconds(2d); public TimeSpan HttpsScanTimeout { get; set; } = TimeSpan.FromSeconds(2d);
} }
/// <summary>
/// 域名与ip关系提供者配置
/// </summary>
public class DomainAddressProvidersSetting public class DomainAddressProvidersSetting
{ {
public GithubMetaProviderSetting GithubMetaProvider { get; set; } = new GithubMetaProviderSetting(); public GithubMetaProviderSetting GithubMetaProvider { get; set; } = new GithubMetaProviderSetting();

View File

@ -6,11 +6,19 @@ using System.Threading.Tasks;
namespace FastGithub namespace FastGithub
{ {
/// <summary>
/// 扫描结果轮询扫描后台服务
/// </summary>
sealed class GithubResultScanHostedService : BackgroundService sealed class GithubResultScanHostedService : BackgroundService
{ {
private readonly GithubScanService githubScanService; private readonly GithubScanService githubScanService;
private readonly IOptionsMonitor<GithubOptions> options; private readonly IOptionsMonitor<GithubOptions> options;
/// <summary>
/// 扫描结果轮询扫描后台服务
/// </summary>
/// <param name="githubScanService"></param>
/// <param name="options"></param>
public GithubResultScanHostedService( public GithubResultScanHostedService(
GithubScanService githubScanService, GithubScanService githubScanService,
IOptionsMonitor<GithubOptions> options) IOptionsMonitor<GithubOptions> options)
@ -19,6 +27,11 @@ namespace FastGithub
this.options = options; this.options = options;
} }
/// <summary>
/// 后台轮询扫描
/// </summary>
/// <param name="stoppingToken"></param>
/// <returns></returns>
protected override async Task ExecuteAsync(CancellationToken stoppingToken) protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{ {
while (stoppingToken.IsCancellationRequested == false) while (stoppingToken.IsCancellationRequested == false)

View File

@ -7,24 +7,34 @@ using System.Threading.Tasks;
namespace FastGithub.Scanner namespace FastGithub.Scanner
{ {
/// <summary>
/// github扫描服务
/// </summary>
[Service(ServiceLifetime.Singleton)] [Service(ServiceLifetime.Singleton)]
sealed class GithubScanService sealed class GithubScanService
{ {
private readonly DomainAddressFacotry domainAddressFactory; private readonly DomainAddressFacotry domainAddressFactory;
private readonly GithubContextCollection scanResults;
private readonly ILogger<GithubScanService> logger; private readonly ILogger<GithubScanService> logger;
private readonly GithubContextCollection contextCollection;
private readonly InvokeDelegate<GithubContext> fullScanDelegate; private readonly InvokeDelegate<GithubContext> fullScanDelegate;
private readonly InvokeDelegate<GithubContext> resultScanDelegate; private readonly InvokeDelegate<GithubContext> resultScanDelegate;
/// <summary>
/// github扫描服务
/// </summary>
/// <param name="domainAddressFactory"></param>
/// <param name="scanResults"></param>
/// <param name="appService"></param>
/// <param name="logger"></param>
public GithubScanService( public GithubScanService(
DomainAddressFacotry domainAddressFactory, DomainAddressFacotry domainAddressFactory,
GithubContextCollection contextCollection, GithubContextCollection scanResults,
IServiceProvider appService, IServiceProvider appService,
ILogger<GithubScanService> logger) ILogger<GithubScanService> logger)
{ {
this.domainAddressFactory = domainAddressFactory; this.domainAddressFactory = domainAddressFactory;
this.contextCollection = contextCollection; this.scanResults = scanResults;
this.logger = logger; this.logger = logger;
this.fullScanDelegate = new PipelineBuilder<GithubContext>(appService, ctx => Task.CompletedTask) this.fullScanDelegate = new PipelineBuilder<GithubContext>(appService, ctx => Task.CompletedTask)
@ -40,6 +50,10 @@ namespace FastGithub.Scanner
.Build(); .Build();
} }
/// <summary>
/// 扫描所有的ip
/// </summary>
/// <returns></returns>
public async Task ScanAllAsync() public async Task ScanAllAsync()
{ {
this.logger.LogInformation("完整扫描开始.."); this.logger.LogInformation("完整扫描开始..");
@ -59,17 +73,21 @@ namespace FastGithub.Scanner
await this.fullScanDelegate(context); await this.fullScanDelegate(context);
if (context.Available == true) if (context.Available == true)
{ {
this.contextCollection.Add(context); this.scanResults.Add(context);
} }
return context.Available; return context.Available;
} }
} }
/// <summary>
/// 扫描曾经扫描到的结果
/// </summary>
/// <returns></returns>
public async Task ScanResultAsync() public async Task ScanResultAsync()
{ {
this.logger.LogInformation("结果扫描开始.."); this.logger.LogInformation("结果扫描开始..");
var contexts = this.contextCollection.ToArray(); var contexts = this.scanResults.ToArray();
foreach (var context in contexts) foreach (var context in contexts)
{ {
await this.resultScanDelegate(context); await this.resultScanDelegate(context);

View File

@ -3,8 +3,15 @@ using System.Threading.Tasks;
namespace FastGithub.Scanner namespace FastGithub.Scanner
{ {
/// <summary>
/// 定义域名的ip提值者
/// </summary>
interface IDomainAddressProvider interface IDomainAddressProvider
{ {
/// <summary>
/// 创建域名与ip的关系
/// </summary>
/// <returns></returns>
Task<IEnumerable<DomainAddress>> CreateDomainAddressesAsync(); Task<IEnumerable<DomainAddress>> CreateDomainAddressesAsync();
} }
} }

View File

@ -2,10 +2,24 @@
namespace FastGithub.Scanner namespace FastGithub.Scanner
{ {
/// <summary>
/// 定义扫描结果的接口
/// </summary>
public interface IGithubScanResults public interface IGithubScanResults
{ {
/// <summary>
/// 查询ip是否可用
/// </summary>
/// <param name="domain"></param>
/// <param name="address"></param>
/// <returns></returns>
bool IsAvailable(string domain, IPAddress address); bool IsAvailable(string domain, IPAddress address);
/// <summary>
/// 查找最优的ip
/// </summary>
/// <param name="domain"></param>
/// <returns></returns>
IPAddress? FindBestAddress(string domain); IPAddress? FindBestAddress(string domain);
} }
} }

View File

@ -8,12 +8,29 @@ using System.Net.Sockets;
namespace FastGithub.Scanner namespace FastGithub.Scanner
{ {
/// <summary>
/// 表示IP范围
/// </summary>
/// <remarks>
/// <para>• 192.168.1.0/24</para>
/// <para>• 192.168.1.1-192.168.1.254</para>
/// </remarks>
abstract class IPAddressRange : IEnumerable<IPAddress> abstract class IPAddressRange : IEnumerable<IPAddress>
{ {
/// <summary>
/// 获取ip数量
/// </summary>
public abstract int Size { get; } public abstract int Size { get; }
/// <summary>
/// 获取地址族
/// </summary>
public abstract AddressFamily AddressFamily { get; } public abstract AddressFamily AddressFamily { get; }
/// <summary>
/// 获取迭代器
/// </summary>
/// <returns></returns>
public abstract IEnumerator<IPAddress> GetEnumerator(); public abstract IEnumerator<IPAddress> GetEnumerator();
@ -22,6 +39,11 @@ namespace FastGithub.Scanner
return this.GetEnumerator(); return this.GetEnumerator();
} }
/// <summary>
/// 从多个ip范围文本解析
/// </summary>
/// <param name="ranges"></param>
/// <returns></returns>
public static IEnumerable<IPAddressRange> From(IEnumerable<string> ranges) public static IEnumerable<IPAddressRange> From(IEnumerable<string> ranges)
{ {
foreach (var item in ranges) foreach (var item in ranges)
@ -33,12 +55,17 @@ namespace FastGithub.Scanner
} }
} }
/// <summary>
/// 尝试解析
/// </summary>
/// <param name="range"></param>
/// <param name="value"></param>
/// <returns></returns>
public static bool TryParse(ReadOnlySpan<char> range, [MaybeNullWhen(false)] out IPAddressRange value) public static bool TryParse(ReadOnlySpan<char> range, [MaybeNullWhen(false)] out IPAddressRange value)
{ {
if (range.IsEmpty == false && IPNetwork.TryParse(range.ToString(), out var ipNetwork)) if (range.IsEmpty == false && IPNetwork.TryParse(range.ToString(), out var ipNetwork))
{ {
value = new NetworkIPAddressRange(ipNetwork); value = new CidrIPAddressRange(ipNetwork);
return true; return true;
} }
@ -61,8 +88,10 @@ namespace FastGithub.Scanner
return false; return false;
} }
/// <summary>
private class NetworkIPAddressRange : IPAddressRange /// 192.168.1.0/24
/// </summary>
private class CidrIPAddressRange : IPAddressRange
{ {
private readonly IPAddressCollection addressCollection; private readonly IPAddressCollection addressCollection;
@ -72,7 +101,7 @@ namespace FastGithub.Scanner
public override AddressFamily AddressFamily => this.addressFamily; public override AddressFamily AddressFamily => this.addressFamily;
public NetworkIPAddressRange(IPNetwork network) public CidrIPAddressRange(IPNetwork network)
{ {
this.addressCollection = network.ListIPAddress(FilterEnum.All); this.addressCollection = network.ListIPAddress(FilterEnum.All);
this.addressFamily = network.AddressFamily; this.addressFamily = network.AddressFamily;
@ -84,6 +113,9 @@ namespace FastGithub.Scanner
} }
} }
/// <summary>
/// 192.168.1.1-192.168.1.254
/// </summary>
private class SplitIPAddressRange : IPAddressRange private class SplitIPAddressRange : IPAddressRange
{ {
private readonly IPAddress start; private readonly IPAddress start;

View File

@ -5,17 +5,29 @@ using System.Threading.Tasks;
namespace FastGithub.Scanner.ScanMiddlewares namespace FastGithub.Scanner.ScanMiddlewares
{ {
/// <summary>
/// 扫描并发限制中间件
/// </summary>
[Service(ServiceLifetime.Singleton)] [Service(ServiceLifetime.Singleton)]
sealed class ConcurrentMiddleware : IMiddleware<GithubContext> sealed class ConcurrentMiddleware : IMiddleware<GithubContext>
{ {
private readonly SemaphoreSlim semaphoreSlim; private readonly SemaphoreSlim semaphoreSlim;
/// <summary>
/// 扫描并发限制中间件
/// </summary>
public ConcurrentMiddleware() public ConcurrentMiddleware()
{ {
var currentCount = Environment.ProcessorCount * 2; var currentCount = Environment.ProcessorCount * 2;
this.semaphoreSlim = new SemaphoreSlim(currentCount, currentCount); this.semaphoreSlim = new SemaphoreSlim(currentCount, currentCount);
} }
/// <summary>
/// 限制描并发扫
/// </summary>
/// <param name="context"></param>
/// <param name="next"></param>
/// <returns></returns>
public async Task InvokeAsync(GithubContext context, Func<Task> next) public async Task InvokeAsync(GithubContext context, Func<Task> next)
{ {
try try

View File

@ -10,12 +10,20 @@ using System.Threading.Tasks;
namespace FastGithub.Scanner.ScanMiddlewares namespace FastGithub.Scanner.ScanMiddlewares
{ {
/// <summary>
/// https扫描中间件
/// </summary>
[Service(ServiceLifetime.Singleton)] [Service(ServiceLifetime.Singleton)]
sealed class HttpsScanMiddleware : IMiddleware<GithubContext> sealed class HttpsScanMiddleware : IMiddleware<GithubContext>
{ {
private readonly IOptionsMonitor<GithubOptions> options; private readonly IOptionsMonitor<GithubOptions> options;
private readonly ILogger<HttpsScanMiddleware> logger; private readonly ILogger<HttpsScanMiddleware> logger;
/// <summary>
/// https扫描中间件
/// </summary>
/// <param name="options"></param>
/// <param name="logger"></param>
public HttpsScanMiddleware( public HttpsScanMiddleware(
IOptionsMonitor<GithubOptions> options, IOptionsMonitor<GithubOptions> options,
ILogger<HttpsScanMiddleware> logger) ILogger<HttpsScanMiddleware> logger)
@ -24,6 +32,12 @@ namespace FastGithub.Scanner.ScanMiddlewares
this.logger = logger; this.logger = logger;
} }
/// <summary>
/// https扫描
/// </summary>
/// <param name="context"></param>
/// <param name="next"></param>
/// <returns></returns>
public async Task InvokeAsync(GithubContext context, Func<Task> next) public async Task InvokeAsync(GithubContext context, Func<Task> next)
{ {
try try

View File

@ -6,16 +6,29 @@ using System.Threading.Tasks;
namespace FastGithub.Scanner.ScanMiddlewares namespace FastGithub.Scanner.ScanMiddlewares
{ {
/// <summary>
/// 扫描统计中间件
/// </summary>
[Service(ServiceLifetime.Singleton)] [Service(ServiceLifetime.Singleton)]
sealed class StatisticsMiddleware : IMiddleware<GithubContext> sealed class StatisticsMiddleware : IMiddleware<GithubContext>
{ {
private readonly ILogger<StatisticsMiddleware> logger; private readonly ILogger<StatisticsMiddleware> logger;
/// <summary>
/// 扫描统计中间件
/// </summary>
/// <param name="logger"></param>
public StatisticsMiddleware(ILogger<StatisticsMiddleware> logger) public StatisticsMiddleware(ILogger<StatisticsMiddleware> logger)
{ {
this.logger = logger; this.logger = logger;
} }
/// <summary>
/// 记录扫描结果
/// </summary>
/// <param name="context"></param>
/// <param name="next"></param>
/// <returns></returns>
public async Task InvokeAsync(GithubContext context, Func<Task> next) public async Task InvokeAsync(GithubContext context, Func<Task> next)
{ {
var stopwatch = new Stopwatch(); var stopwatch = new Stopwatch();

View File

@ -8,6 +8,9 @@ using System.Threading.Tasks;
namespace FastGithub.Scanner.ScanMiddlewares namespace FastGithub.Scanner.ScanMiddlewares
{ {
/// <summary>
/// tcp扫描中间件
/// </summary>
[Service(ServiceLifetime.Singleton)] [Service(ServiceLifetime.Singleton)]
sealed class TcpScanMiddleware : IMiddleware<GithubContext> sealed class TcpScanMiddleware : IMiddleware<GithubContext>
{ {
@ -15,6 +18,11 @@ namespace FastGithub.Scanner.ScanMiddlewares
private readonly IOptionsMonitor<GithubOptions> options; private readonly IOptionsMonitor<GithubOptions> options;
private readonly ILogger<TcpScanMiddleware> logger; private readonly ILogger<TcpScanMiddleware> logger;
/// <summary>
/// tcp扫描中间件
/// </summary>
/// <param name="options"></param>
/// <param name="logger"></param>
public TcpScanMiddleware( public TcpScanMiddleware(
IOptionsMonitor<GithubOptions> options, IOptionsMonitor<GithubOptions> options,
ILogger<TcpScanMiddleware> logger) ILogger<TcpScanMiddleware> logger)
@ -23,6 +31,12 @@ namespace FastGithub.Scanner.ScanMiddlewares
this.logger = logger; this.logger = logger;
} }
/// <summary>
/// tcp扫描
/// </summary>
/// <param name="context"></param>
/// <param name="next"></param>
/// <returns></returns>
public async Task InvokeAsync(GithubContext context, Func<Task> next) public async Task InvokeAsync(GithubContext context, Func<Task> next)
{ {
try try