diff --git a/FastGithub/FastGithub.csproj b/FastGithub/FastGithub.csproj index a36eb2d..4772b89 100644 --- a/FastGithub/FastGithub.csproj +++ b/FastGithub/FastGithub.csproj @@ -8,13 +8,14 @@ + - Always + PreserveNewest diff --git a/FastGithub/GithubHostedService.cs b/FastGithub/GithubHostedService.cs index 79cb597..ba7a269 100644 --- a/FastGithub/GithubHostedService.cs +++ b/FastGithub/GithubHostedService.cs @@ -8,17 +8,23 @@ namespace FastGithub sealed class GithubHostedService : IHostedService { private readonly IServiceScopeFactory serviceScopeFactory; + private readonly IHostApplicationLifetime hostApplicationLifetime; - public GithubHostedService(IServiceScopeFactory serviceScopeFactory) + public GithubHostedService( + IServiceScopeFactory serviceScopeFactory, + IHostApplicationLifetime hostApplicationLifetime) { this.serviceScopeFactory = serviceScopeFactory; + this.hostApplicationLifetime = hostApplicationLifetime; } - public Task StartAsync(CancellationToken cancellationToken) + + public async Task StartAsync(CancellationToken cancellationToken) { var scope = this.serviceScopeFactory.CreateScope(); var service = scope.ServiceProvider.GetRequiredService(); - return service.ScanAddressAsync(cancellationToken); + await service.ScanAddressAsync(cancellationToken); + this.hostApplicationLifetime.StopApplication(); } public Task StopAsync(CancellationToken cancellationToken) diff --git a/FastGithub/GithubService.cs b/FastGithub/GithubService.cs index 9b89e33..5adb1ee 100644 --- a/FastGithub/GithubService.cs +++ b/FastGithub/GithubService.cs @@ -28,13 +28,13 @@ namespace FastGithub var meta = await this.githubMetaService.GetMetaAsync(cancellationToken); if (meta != null) { - var contexts = new List(); - var scanTasks = this.GetMetaScanTasks(meta, contexts); - await Task.WhenAll(scanTasks); + var scanTasks = this.GetMetaScanTasks(meta); + var contexts = await Task.WhenAll(scanTasks); var sortedContexts = contexts .Where(item => item.HttpElapsed != null) - .OrderBy(item => item.HttpElapsed); + .OrderBy(item => item.Domain) + .ThenBy(item => item.HttpElapsed); using var fileStream = File.OpenWrite("github.txt"); using var fileWriter = new StreamWriter(fileStream); @@ -42,7 +42,6 @@ namespace FastGithub foreach (var context in sortedContexts) { var message = context.ToString(); - this.logger.LogInformation(message); await fileWriter.WriteLineAsync(message); } } @@ -51,7 +50,7 @@ namespace FastGithub } - private IEnumerable GetMetaScanTasks(Meta meta, IList contexts) + private IEnumerable> GetMetaScanTasks(Meta meta) { foreach (var item in meta.ToDomainAddress()) { @@ -60,8 +59,14 @@ namespace FastGithub Domain = item.Domain, Address = item.Address, }; - contexts.Add(context); - yield return this.githubDelegate(context); + yield return InvokeAsync(context); + } + + + async Task InvokeAsync(GithubContext context) + { + await this.githubDelegate(context); + return context; } } } diff --git a/FastGithub/IPRange.cs b/FastGithub/IPRange.cs new file mode 100644 index 0000000..910a953 --- /dev/null +++ b/FastGithub/IPRange.cs @@ -0,0 +1,118 @@ +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 +{ + sealed class IPRange : IEnumerable + { + 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 GetEnumerator() + { + return new Enumerator(this.network); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } + + private class Enumerator : IEnumerator + { + 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; + } + } + + /// + /// 添加值 + /// + /// + /// + /// + 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 From(IEnumerable networks) + { + foreach (var item in networks) + { + if (TryParse(item, out var value)) + { + yield return value; + } + } + } + + public static bool TryParse(ReadOnlySpan 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(); + } + + } +} diff --git a/FastGithub/IPv4CIDR.cs b/FastGithub/IPv4CIDR.cs deleted file mode 100644 index cab17b4..0000000 --- a/FastGithub/IPv4CIDR.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System; -using System.Buffers.Binary; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Net; -using System.Net.Sockets; - -namespace FastGithub -{ - sealed class IPv4CIDR - { - public IPAddress IPAddress { get; } - - public int Mask { get; } - - public int Size { get; } - - public IPv4CIDR(IPAddress ipAddress, int mask) - { - this.IPAddress = ipAddress; - this.Mask = mask; - this.Size = Math.Abs((int)(uint.MaxValue << mask >> mask)); - } - - public IEnumerable GetAllIPAddress() - { - for (var i = 0; i < this.Size; i++) - { - var value = i; - yield return Add(this.IPAddress, value); - } - } - - /// - /// 添加值 - /// - /// - /// - /// - 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 From(IEnumerable cidrs) - { - foreach (var item in cidrs) - { - if (TryParse(item, out var value)) - { - yield return value; - } - } - } - - public static bool TryParse(ReadOnlySpan cidr, [MaybeNullWhen(false)] out IPv4CIDR value) - { - value = null; - var index = cidr.IndexOf('/'); - if (index <= 0) - { - return false; - } - - var addressSpan = cidr.Slice(0, index); - if (IPAddress.TryParse(addressSpan, out var address) == false - || address.AddressFamily != AddressFamily.InterNetwork) - { - return false; - } - - var maskSpan = cidr.Slice(index + 1); - if (int.TryParse(maskSpan, out var mask) == false) - { - return false; - } - - value = new IPv4CIDR(address, mask); - return true; - } - - public override string ToString() - { - return $"{this.IPAddress}/{this.Mask}"; - } - } -} diff --git a/FastGithub/Meta.cs b/FastGithub/Meta.cs index a6c4d50..3a558ec 100644 --- a/FastGithub/Meta.cs +++ b/FastGithub/Meta.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Net; +using System.Net.Sockets; using System.Text.Json.Serialization; namespace FastGithub @@ -38,19 +39,25 @@ namespace FastGithub public IEnumerable ToDomainAddress() { - foreach (var cidr in IPv4CIDR.From(this.Web).OrderBy(item => item.Size)) + foreach (var range in IPRange.From(this.Web).OrderBy(item => item.Size)) { - foreach (var address in cidr.GetAllIPAddress()) + if (range.AddressFamily == AddressFamily.InterNetwork) { - yield return new DomainAddress("github.com", address); + foreach (var address in range) + { + yield return new DomainAddress("github.com", address); + } } } - foreach (var cidr in IPv4CIDR.From(this.Api).OrderBy(item => item.Size)) + foreach (var range in IPRange.From(this.Api).OrderBy(item => item.Size)) { - foreach (var address in cidr.GetAllIPAddress()) + if (range.AddressFamily == AddressFamily.InterNetwork) { - yield return new DomainAddress("api.github.com", address); + foreach (var address in range) + { + yield return new DomainAddress("api.github.com", address); + } } } } diff --git a/FastGithub/Properties/launchSettings.json b/FastGithub/Properties/launchSettings.json new file mode 100644 index 0000000..2d7291b --- /dev/null +++ b/FastGithub/Properties/launchSettings.json @@ -0,0 +1,14 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "profiles": { + "FastGithub": { + "commandName": "Project", + "dotnetRunMessages": "true", + "launchBrowser": true, + "environmentVariables": { + "DOTNET_ENVIRONMENT": "Development", + "Logging__LogLevel__Default": "Information" + } + } + } +} diff --git a/FastGithub/appsettings.json b/FastGithub/appsettings.json index 44ee0af..8e41b4b 100644 --- a/FastGithub/appsettings.json +++ b/FastGithub/appsettings.json @@ -6,7 +6,7 @@ }, "Logging": { "LogLevel": { - "Default": "Information", + "Default": "Warning", "System": "Warning", "Microsoft": "Warning" }