From ad51a0a572441dd7c584d2f98feceb0defbdfb32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=9B=BD=E4=BC=9F?= <366193849@qq.com> Date: Tue, 28 Sep 2021 08:47:06 +0800 Subject: [PATCH 1/8] =?UTF-8?q?=E5=BC=BA=E5=8C=96dns=E5=AE=A2=E6=88=B7?= =?UTF-8?q?=E7=AB=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FastGithub.DomainResolve/DnsClient.cs | 59 ++++++++++++++++++- FastGithub.DomainResolve/DomainResolver.cs | 47 ++------------- FastGithub.DomainResolve/IPAddressItem.cs | 50 ++++++++++++++++ .../IPAddressItemHashSet.cs | 48 +++++++++++++++ 4 files changed, 158 insertions(+), 46 deletions(-) create mode 100644 FastGithub.DomainResolve/IPAddressItem.cs create mode 100644 FastGithub.DomainResolve/IPAddressItemHashSet.cs diff --git a/FastGithub.DomainResolve/DnsClient.cs b/FastGithub.DomainResolve/DnsClient.cs index e60f20a..4d1f03f 100644 --- a/FastGithub.DomainResolve/DnsClient.cs +++ b/FastGithub.DomainResolve/DnsClient.cs @@ -2,13 +2,16 @@ using DNS.Client.RequestResolver; using DNS.Protocol; using DNS.Protocol.ResourceRecords; +using FastGithub.Configuration; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System; using System.Collections.Concurrent; +using System.Collections.Generic; using System.Linq; using System.Net; +using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; @@ -21,6 +24,9 @@ namespace FastGithub.DomainResolve { private const int DNS_PORT = 53; private const string LOCALHOST = "localhost"; + + private readonly DnscryptProxy dnscryptProxy; + private readonly FastGithubConfig fastGithubConfig; private readonly ILogger logger; private readonly ConcurrentDictionary semaphoreSlims = new(); @@ -30,13 +36,60 @@ namespace FastGithub.DomainResolve /// /// DNS客户端 - /// + /// + /// + /// /// - public DnsClient(ILogger logger) + public DnsClient( + DnscryptProxy dnscryptProxy, + FastGithubConfig fastGithubConfig, + ILogger logger) { + this.dnscryptProxy = dnscryptProxy; + this.fastGithubConfig = fastGithubConfig; this.logger = logger; } + /// + /// 解析域名 + /// + /// 域名 + /// + /// + public async IAsyncEnumerable ResolveAsync(string domain, [EnumeratorCancellation] CancellationToken cancellationToken) + { + var hashSet = new HashSet(); + foreach (var dns in this.GetDnsServers()) + { + foreach (var address in await this.LookupAsync(dns, domain, cancellationToken)) + { + if (hashSet.Add(address) == true) + { + yield return address; + } + } + } + } + + /// + /// 获取dns服务 + /// + /// + private IEnumerable GetDnsServers() + { + var cryptDns = this.dnscryptProxy.LocalEndPoint; + if (cryptDns != null) + { + yield return cryptDns; + yield return cryptDns; + } + + foreach (var fallbackDns in this.fastGithubConfig.FallbackDns) + { + yield return fallbackDns; + } + } + /// /// 解析域名 /// @@ -44,7 +97,7 @@ namespace FastGithub.DomainResolve /// /// /// - public async Task LookupAsync(IPEndPoint dns, string domain, CancellationToken cancellationToken = default) + private async Task LookupAsync(IPEndPoint dns, string domain, CancellationToken cancellationToken = default) { var key = $"{dns}:{domain}"; var semaphore = this.semaphoreSlims.GetOrAdd(key, _ => new SemaphoreSlim(1, 1)); diff --git a/FastGithub.DomainResolve/DomainResolver.cs b/FastGithub.DomainResolve/DomainResolver.cs index fa88a8a..e44ef41 100644 --- a/FastGithub.DomainResolve/DomainResolver.cs +++ b/FastGithub.DomainResolve/DomainResolver.cs @@ -1,7 +1,6 @@ using FastGithub.Configuration; using System.Collections.Generic; using System.Net; -using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; @@ -12,23 +11,14 @@ namespace FastGithub.DomainResolve /// sealed class DomainResolver : IDomainResolver { - private readonly DnscryptProxy dnscryptProxy; - private readonly FastGithubConfig fastGithubConfig; private readonly DnsClient dnsClient; /// /// 域名解析器 - /// - /// - /// + /// /// - public DomainResolver( - DnscryptProxy dnscryptProxy, - FastGithubConfig fastGithubConfig, - DnsClient dnsClient) + public DomainResolver(DnsClient dnsClient) { - this.dnscryptProxy = dnscryptProxy; - this.fastGithubConfig = fastGithubConfig; this.dnsClient = dnsClient; } @@ -53,38 +43,9 @@ namespace FastGithub.DomainResolve /// 域名 /// /// - public async IAsyncEnumerable ResolveAllAsync(string domain, [EnumeratorCancellation] CancellationToken cancellationToken) + public IAsyncEnumerable ResolveAllAsync(string domain, CancellationToken cancellationToken) { - var hashSet = new HashSet(); - foreach (var dns in this.GetDnsServers()) - { - foreach (var address in await this.dnsClient.LookupAsync(dns, domain, cancellationToken)) - { - if (hashSet.Add(address) == true) - { - yield return address; - } - } - } - } - - /// - /// 获取dns服务 - /// - /// - private IEnumerable GetDnsServers() - { - var cryptDns = this.dnscryptProxy.LocalEndPoint; - if (cryptDns != null) - { - yield return cryptDns; - yield return cryptDns; - } - - foreach (var fallbackDns in this.fastGithubConfig.FallbackDns) - { - yield return fallbackDns; - } + return this.dnsClient.ResolveAsync(domain, cancellationToken); } } } diff --git a/FastGithub.DomainResolve/IPAddressItem.cs b/FastGithub.DomainResolve/IPAddressItem.cs new file mode 100644 index 0000000..189bf1b --- /dev/null +++ b/FastGithub.DomainResolve/IPAddressItem.cs @@ -0,0 +1,50 @@ +using System; +using System.Net; +using System.Net.NetworkInformation; +using System.Threading.Tasks; + +namespace FastGithub.DomainResolve +{ + sealed class IPAddressItem : IEquatable + { + public IPAddress Address { get; } + + public TimeSpan Elapsed { get; private set; } = TimeSpan.MaxValue; + + public IPAddressItem(IPAddress address) + { + this.Address = address; + } + + public async Task TestSpeedAsync() + { + try + { + using var ping = new Ping(); + var reply = await ping.SendPingAsync(this.Address); + this.Elapsed = reply.Status == IPStatus.Success + ? TimeSpan.FromMilliseconds(reply.RoundtripTime) + : TimeSpan.MaxValue; + } + catch (Exception) + { + this.Elapsed = TimeSpan.MaxValue; + } + } + + public bool Equals(IPAddressItem? other) + { + return other != null && other.Address.Equals(this.Address); + } + + public override bool Equals(object? obj) + { + return obj is IPAddressItem other && this.Equals(other); + } + + public override int GetHashCode() + { + return this.Address.GetHashCode(); + } + } +} diff --git a/FastGithub.DomainResolve/IPAddressItemHashSet.cs b/FastGithub.DomainResolve/IPAddressItemHashSet.cs new file mode 100644 index 0000000..c98b2da --- /dev/null +++ b/FastGithub.DomainResolve/IPAddressItemHashSet.cs @@ -0,0 +1,48 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace FastGithub.DomainResolve +{ + sealed class IPAddressItemHashSet + { + private readonly object syncRoot = new(); + + private readonly HashSet hashSet = new(); + + public int Count => this.hashSet.Count; + + public bool Add(IPAddressItem item) + { + lock (this.syncRoot) + { + return this.hashSet.Add(item); + } + } + + public void AddRange(IEnumerable items) + { + lock (this.syncRoot) + { + foreach (var item in items) + { + this.hashSet.Add(item); + } + } + } + + public IPAddressItem[] ToArray() + { + lock (this.syncRoot) + { + return this.hashSet.ToArray(); + } + } + + public Task TestSpeedAsync() + { + var tasks = this.ToArray().Select(item => item.TestSpeedAsync()); + return Task.WhenAll(tasks); + } + } +} From f29dca6b43a70171c44dc5de139944d49a4c7ebf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=9B=BD=E4=BC=9F?= <366193849@qq.com> Date: Tue, 28 Sep 2021 11:48:22 +0800 Subject: [PATCH 2/8] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=9F=9F=E5=90=8D?= =?UTF-8?q?=E4=B8=8B=E7=9A=84ip=E6=B5=8B=E9=80=9F=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FastGithub.DomainResolve/DnsClient.cs | 4 - FastGithub.DomainResolve/DomainResolver.cs | 29 +++- .../DomainSpeedTestHostedService.cs | 61 +++++++++ .../DomainSpeedTestService.cs | 126 ++++++++++++++++++ FastGithub.DomainResolve/IPAddressItem.cs | 32 ++++- .../IPAddressItemHashSet.cs | 44 ++++-- .../ServiceCollectionExtensions.cs | 5 +- 7 files changed, 272 insertions(+), 29 deletions(-) create mode 100644 FastGithub.DomainResolve/DomainSpeedTestHostedService.cs create mode 100644 FastGithub.DomainResolve/DomainSpeedTestService.cs diff --git a/FastGithub.DomainResolve/DnsClient.cs b/FastGithub.DomainResolve/DnsClient.cs index 4d1f03f..8a29636 100644 --- a/FastGithub.DomainResolve/DnsClient.cs +++ b/FastGithub.DomainResolve/DnsClient.cs @@ -81,7 +81,6 @@ namespace FastGithub.DomainResolve if (cryptDns != null) { yield return cryptDns; - yield return cryptDns; } foreach (var fallbackDns in this.fastGithubConfig.FallbackDns) @@ -109,9 +108,6 @@ namespace FastGithub.DomainResolve { value = await this.LookupCoreAsync(dns, domain, cancellationToken); this.dnsCache.Set(key, value, this.dnsExpiration); - - var items = string.Join(", ", value.Select(item => item.ToString())); - this.logger.LogInformation($"dns://{dns}:{domain}->[{items}]"); } return value; } diff --git a/FastGithub.DomainResolve/DomainResolver.cs b/FastGithub.DomainResolve/DomainResolver.cs index e44ef41..236e1a4 100644 --- a/FastGithub.DomainResolve/DomainResolver.cs +++ b/FastGithub.DomainResolve/DomainResolver.cs @@ -1,6 +1,7 @@ using FastGithub.Configuration; using System.Collections.Generic; using System.Net; +using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; @@ -12,14 +13,19 @@ namespace FastGithub.DomainResolve sealed class DomainResolver : IDomainResolver { private readonly DnsClient dnsClient; + private readonly DomainSpeedTestService speedTestService; /// /// 域名解析器 - /// + /// /// - public DomainResolver(DnsClient dnsClient) + /// + public DomainResolver( + DnsClient dnsClient, + DomainSpeedTestService speedTestService) { this.dnsClient = dnsClient; + this.speedTestService = speedTestService; } /// @@ -43,9 +49,24 @@ namespace FastGithub.DomainResolve /// 域名 /// /// - public IAsyncEnumerable ResolveAllAsync(string domain, CancellationToken cancellationToken) + public async IAsyncEnumerable ResolveAllAsync(string domain, [EnumeratorCancellation] CancellationToken cancellationToken) { - return this.dnsClient.ResolveAsync(domain, cancellationToken); + var addresses = this.speedTestService.GetIPAddresses(domain); + if (addresses.Length > 0) + { + foreach (var address in addresses) + { + yield return address; + } + } + else + { + this.speedTestService.Add(domain); + await foreach (var address in this.dnsClient.ResolveAsync(domain, cancellationToken)) + { + yield return address; + } + } } } } diff --git a/FastGithub.DomainResolve/DomainSpeedTestHostedService.cs b/FastGithub.DomainResolve/DomainSpeedTestHostedService.cs new file mode 100644 index 0000000..6699073 --- /dev/null +++ b/FastGithub.DomainResolve/DomainSpeedTestHostedService.cs @@ -0,0 +1,61 @@ +using Microsoft.Extensions.Hosting; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace FastGithub.DomainResolve +{ + /// + /// 域名的IP测速后台服务 + /// + sealed class DomainSpeedTestHostedService : BackgroundService + { + private readonly DomainSpeedTestService speedTestService; + private readonly TimeSpan testDueTime = TimeSpan.FromMinutes(1d); + + /// + /// 域名的IP测速后台服务 + /// + /// + public DomainSpeedTestHostedService(DomainSpeedTestService speedTestService) + { + this.speedTestService = speedTestService; + } + + /// + /// 启动时 + /// + /// + /// + public override async Task StartAsync(CancellationToken cancellationToken) + { + await this.speedTestService.LoadDataAsync(cancellationToken); + await base.StartAsync(cancellationToken); + } + + /// + /// 停止时 + /// + /// + /// + public override async Task StopAsync(CancellationToken cancellationToken) + { + await this.speedTestService.SaveDataAsync(); + await base.StopAsync(cancellationToken); + } + + /// + /// 后台测速 + /// + /// + /// + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + while (stoppingToken.IsCancellationRequested == false) + { + await this.speedTestService.TestSpeedAsync(stoppingToken); + await Task.Delay(this.testDueTime, stoppingToken); + } + } + } +} diff --git a/FastGithub.DomainResolve/DomainSpeedTestService.cs b/FastGithub.DomainResolve/DomainSpeedTestService.cs new file mode 100644 index 0000000..890305c --- /dev/null +++ b/FastGithub.DomainResolve/DomainSpeedTestService.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; + +namespace FastGithub.DomainResolve +{ + /// + /// 域名的IP测速服务 + /// + sealed class DomainSpeedTestService + { + private const string DATA_FILE = "domains.json"; + private readonly DnsClient dnsClient; + + private readonly object syncRoot = new(); + private readonly Dictionary domainIPAddressHashSet = new(); + + /// + /// 域名的IP测速服务 + /// + /// + public DomainSpeedTestService(DnsClient dnsClient) + { + this.dnsClient = dnsClient; + } + + /// + /// 添加要测速的域名 + /// + /// + /// + public bool Add(string domain) + { + lock (this.syncRoot) + { + return this.domainIPAddressHashSet.TryAdd(domain, new IPAddressItemHashSet()); + } + } + + /// + /// 获取测试后排序的IP + /// + /// + /// + public IPAddress[] GetIPAddresses(string domain) + { + lock (this.syncRoot) + { + if (this.domainIPAddressHashSet.TryGetValue(domain, out var hashSet) && hashSet.Count > 0) + { + return hashSet.ToArray().OrderBy(item => item.PingElapsed).Select(item => item.Address).ToArray(); + } + return Array.Empty(); + } + } + + /// + /// 加载数据 + /// + /// + /// + public async Task LoadDataAsync(CancellationToken cancellationToken) + { + if (File.Exists(DATA_FILE) == false) + { + return; + } + + var fileStream = File.OpenRead(DATA_FILE); + var domains = await JsonSerializer.DeserializeAsync(fileStream, cancellationToken: cancellationToken); + if (domains == null) + { + return; + } + + lock (this.syncRoot) + { + foreach (var domain in domains) + { + this.domainIPAddressHashSet.TryAdd(domain, new IPAddressItemHashSet()); + } + } + } + + /// + /// 保存数据 + /// + /// + public async Task SaveDataAsync() + { + var domains = this.domainIPAddressHashSet.Keys.ToArray(); + using var fileStream = File.OpenWrite(DATA_FILE); + await JsonSerializer.SerializeAsync(fileStream, domains); + } + + /// + /// 进行一轮IP测速 + /// + /// + /// + public async Task TestSpeedAsync(CancellationToken cancellationToken) + { + KeyValuePair[] keyValues; + lock (this.syncRoot) + { + keyValues = this.domainIPAddressHashSet.ToArray(); + } + + foreach (var keyValue in keyValues) + { + var domain = keyValue.Key; + var hashSet = keyValue.Value; + await foreach (var address in this.dnsClient.ResolveAsync(domain, cancellationToken)) + { + hashSet.Add(new IPAddressItem(address)); + } + await hashSet.PingAllAsync(); + } + } + } +} diff --git a/FastGithub.DomainResolve/IPAddressItem.cs b/FastGithub.DomainResolve/IPAddressItem.cs index 189bf1b..0e058ea 100644 --- a/FastGithub.DomainResolve/IPAddressItem.cs +++ b/FastGithub.DomainResolve/IPAddressItem.cs @@ -1,34 +1,54 @@ using System; +using System.Diagnostics; using System.Net; using System.Net.NetworkInformation; using System.Threading.Tasks; namespace FastGithub.DomainResolve { + /// + /// IP地址项 + /// + [DebuggerDisplay("Address = {Address}, PingElapsed = {PingElapsed}")] sealed class IPAddressItem : IEquatable { + private readonly Ping ping = new(); + + /// + /// 地址 + /// public IPAddress Address { get; } - public TimeSpan Elapsed { get; private set; } = TimeSpan.MaxValue; + /// + /// Ping耗时 + /// + public TimeSpan PingElapsed { get; private set; } = TimeSpan.MaxValue; + /// + /// IP地址项 + /// + /// public IPAddressItem(IPAddress address) { this.Address = address; } - public async Task TestSpeedAsync() + /// + /// 发起ping请求 + /// + /// + public async Task PingAsync() { try { - using var ping = new Ping(); - var reply = await ping.SendPingAsync(this.Address); - this.Elapsed = reply.Status == IPStatus.Success + var reply = await this.ping.SendPingAsync(this.Address); + this.PingElapsed = reply.Status == IPStatus.Success ? TimeSpan.FromMilliseconds(reply.RoundtripTime) : TimeSpan.MaxValue; } catch (Exception) { - this.Elapsed = TimeSpan.MaxValue; + this.PingElapsed = TimeSpan.MaxValue; } } diff --git a/FastGithub.DomainResolve/IPAddressItemHashSet.cs b/FastGithub.DomainResolve/IPAddressItemHashSet.cs index c98b2da..d8de684 100644 --- a/FastGithub.DomainResolve/IPAddressItemHashSet.cs +++ b/FastGithub.DomainResolve/IPAddressItemHashSet.cs @@ -4,14 +4,24 @@ using System.Threading.Tasks; namespace FastGithub.DomainResolve { + /// + /// IPAddressItem集合 + /// sealed class IPAddressItemHashSet { private readonly object syncRoot = new(); - private readonly HashSet hashSet = new(); + /// + /// 获取元素数量 + /// public int Count => this.hashSet.Count; + /// + /// 添加元素 + /// + /// + /// public bool Add(IPAddressItem item) { lock (this.syncRoot) @@ -20,17 +30,10 @@ namespace FastGithub.DomainResolve } } - public void AddRange(IEnumerable items) - { - lock (this.syncRoot) - { - foreach (var item in items) - { - this.hashSet.Add(item); - } - } - } - + /// + /// 转换为数组 + /// + /// public IPAddressItem[] ToArray() { lock (this.syncRoot) @@ -39,9 +42,22 @@ namespace FastGithub.DomainResolve } } - public Task TestSpeedAsync() + /// + /// Ping所有IP + /// + /// + public Task PingAllAsync() { - var tasks = this.ToArray().Select(item => item.TestSpeedAsync()); + var items = this.ToArray(); + if (items.Length == 0) + { + return Task.CompletedTask; + } + if (items.Length == 1) + { + return items[0].PingAsync(); + } + var tasks = items.Select(item => item.PingAsync()); return Task.WhenAll(tasks); } } diff --git a/FastGithub.DomainResolve/ServiceCollectionExtensions.cs b/FastGithub.DomainResolve/ServiceCollectionExtensions.cs index c35acc7..cf646a5 100644 --- a/FastGithub.DomainResolve/ServiceCollectionExtensions.cs +++ b/FastGithub.DomainResolve/ServiceCollectionExtensions.cs @@ -18,8 +18,11 @@ namespace FastGithub { services.TryAddSingleton(); services.TryAddSingleton(); + services.TryAddSingleton(); services.TryAddSingleton(); - return services.AddHostedService(); + services.AddHostedService(); + services.AddHostedService(); + return services; } } } From c542c628f1512ec29fc9e1128a0224a14d870b69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=9B=BD=E4=BC=9F?= <366193849@qq.com> Date: Tue, 28 Sep 2021 12:03:16 +0800 Subject: [PATCH 3/8] =?UTF-8?q?=E5=9F=9F=E5=90=8D=E6=8E=92=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FastGithub.Configuration/DomainPattern.cs | 2 +- FastGithub.Configuration/FastGithubConfig.cs | 4 +-- .../DomainSpeedTestService.cs | 26 ++++++++++++++----- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/FastGithub.Configuration/DomainPattern.cs b/FastGithub.Configuration/DomainPattern.cs index 12f425e..0e841f2 100644 --- a/FastGithub.Configuration/DomainPattern.cs +++ b/FastGithub.Configuration/DomainPattern.cs @@ -7,7 +7,7 @@ namespace FastGithub.Configuration /// 表示域名表达式 /// *表示除.之外任意0到多个字符 /// - sealed class DomainPattern : IComparable + public class DomainPattern : IComparable { private readonly Regex regex; private readonly string domainPattern; diff --git a/FastGithub.Configuration/FastGithubConfig.cs b/FastGithub.Configuration/FastGithubConfig.cs index 17fcb40..bf929e5 100644 --- a/FastGithub.Configuration/FastGithubConfig.cs +++ b/FastGithub.Configuration/FastGithubConfig.cs @@ -117,9 +117,9 @@ namespace FastGithub.Configuration /// 获取所有域名表达式 /// /// - public string[] GetDomainPatterns() + public DomainPattern[] GetDomainPatterns() { - return this.domainConfigs.Keys.Select(item => item.ToString()).ToArray(); + return this.domainConfigs.Keys.ToArray(); } } } diff --git a/FastGithub.DomainResolve/DomainSpeedTestService.cs b/FastGithub.DomainResolve/DomainSpeedTestService.cs index 890305c..c957ff2 100644 --- a/FastGithub.DomainResolve/DomainSpeedTestService.cs +++ b/FastGithub.DomainResolve/DomainSpeedTestService.cs @@ -1,4 +1,5 @@ -using System; +using FastGithub.Configuration; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -71,7 +72,7 @@ namespace FastGithub.DomainResolve return; } - var fileStream = File.OpenRead(DATA_FILE); + using var fileStream = File.OpenRead(DATA_FILE); var domains = await JsonSerializer.DeserializeAsync(fileStream, cancellationToken: cancellationToken); if (domains == null) { @@ -91,11 +92,24 @@ namespace FastGithub.DomainResolve /// 保存数据 /// /// - public async Task SaveDataAsync() + public async Task SaveDataAsync() { - var domains = this.domainIPAddressHashSet.Keys.ToArray(); - using var fileStream = File.OpenWrite(DATA_FILE); - await JsonSerializer.SerializeAsync(fileStream, domains); + var domains = this.domainIPAddressHashSet.Keys + .Select(item => new DomainPattern(item)) + .OrderBy(item => item) + .Select(item => item.ToString()) + .ToArray(); + + try + { + using var fileStream = File.OpenWrite(DATA_FILE); + await JsonSerializer.SerializeAsync(fileStream, domains, new JsonSerializerOptions { WriteIndented = true }); + return true; + } + catch (Exception) + { + return false; + } } /// From 249ff7a08168835e4b282e5d9ef041941a37c8cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=9B=BD=E4=BC=9F?= <366193849@qq.com> Date: Tue, 28 Sep 2021 12:44:08 +0800 Subject: [PATCH 4/8] =?UTF-8?q?=E5=90=88=E5=B9=B6=E5=90=8E=E5=8F=B0?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FastGithub.DomainResolve/DnscryptProxy.cs | 27 +++++-- .../DnscryptProxyHostedService.cs | 65 ---------------- .../DomainResolveHostedService.cs | 74 +++++++++++++++++++ FastGithub.DomainResolve/DomainResolver.cs | 12 +-- .../DomainSpeedTestHostedService.cs | 61 --------------- ...eedTestService.cs => DomainSpeedTester.cs} | 20 ++--- .../ServiceCollectionExtensions.cs | 5 +- 7 files changed, 111 insertions(+), 153 deletions(-) delete mode 100644 FastGithub.DomainResolve/DnscryptProxyHostedService.cs create mode 100644 FastGithub.DomainResolve/DomainResolveHostedService.cs delete mode 100644 FastGithub.DomainResolve/DomainSpeedTestHostedService.cs rename FastGithub.DomainResolve/{DomainSpeedTestService.cs => DomainSpeedTester.cs} (87%) diff --git a/FastGithub.DomainResolve/DnscryptProxy.cs b/FastGithub.DomainResolve/DnscryptProxy.cs index 7905e0d..e6cbea6 100644 --- a/FastGithub.DomainResolve/DnscryptProxy.cs +++ b/FastGithub.DomainResolve/DnscryptProxy.cs @@ -116,19 +116,30 @@ namespace FastGithub.DomainResolve /// /// 停止dnscrypt-proxy /// - public void Stop() + /// + public bool Stop() { - if (OperatingSystem.IsWindows()) + try { - StartDnscryptProxy("-service stop")?.WaitForExit(); - StartDnscryptProxy("-service uninstall")?.WaitForExit(); + if (OperatingSystem.IsWindows()) + { + StartDnscryptProxy("-service stop")?.WaitForExit(); + StartDnscryptProxy("-service uninstall")?.WaitForExit(); + } + if (this.process != null && this.process.HasExited == false) + { + this.process.Kill(); + } + return true; } - - if (this.process != null && this.process.HasExited == false) + catch (Exception) { - this.process.Kill(); + return false; + } + finally + { + this.LocalEndPoint = null; } - this.LocalEndPoint = null; } /// diff --git a/FastGithub.DomainResolve/DnscryptProxyHostedService.cs b/FastGithub.DomainResolve/DnscryptProxyHostedService.cs deleted file mode 100644 index 219c068..0000000 --- a/FastGithub.DomainResolve/DnscryptProxyHostedService.cs +++ /dev/null @@ -1,65 +0,0 @@ -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using System; -using System.Threading; -using System.Threading.Tasks; - -namespace FastGithub.DomainResolve -{ - /// - /// DnscryptProxy后台服务 - /// - sealed class DnscryptProxyHostedService : BackgroundService - { - private readonly ILogger logger; - private readonly DnscryptProxy dnscryptProxy; - - /// - /// DnscryptProxy后台服务 - /// - /// - /// - public DnscryptProxyHostedService( - DnscryptProxy dnscryptProxy, - ILogger logger) - { - this.dnscryptProxy = dnscryptProxy; - this.logger = logger; - } - - /// - /// 启动dnscrypt-proxy - /// - /// - /// - protected override async Task ExecuteAsync(CancellationToken stoppingToken) - { - try - { - await this.dnscryptProxy.StartAsync(stoppingToken); - } - catch (Exception ex) - { - this.logger.LogWarning($"{this.dnscryptProxy}启动失败:{ex.Message}"); - } - } - - /// - /// 停止dnscrypt-proxy - /// - /// - /// - public override Task StopAsync(CancellationToken cancellationToken) - { - try - { - this.dnscryptProxy.Stop(); - } - catch (Exception ex) - { - this.logger.LogWarning($"{this.dnscryptProxy}停止失败:{ex.Message}"); - } - return base.StopAsync(cancellationToken); - } - } -} diff --git a/FastGithub.DomainResolve/DomainResolveHostedService.cs b/FastGithub.DomainResolve/DomainResolveHostedService.cs new file mode 100644 index 0000000..3e18641 --- /dev/null +++ b/FastGithub.DomainResolve/DomainResolveHostedService.cs @@ -0,0 +1,74 @@ +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace FastGithub.DomainResolve +{ + /// + /// 域名解析后台服务 + /// + sealed class DomainResolveHostedService : BackgroundService + { + private readonly DnscryptProxy dnscryptProxy; + private readonly DomainSpeedTester speedTester; + private readonly ILogger logger; + + private readonly TimeSpan speedTestDueTime = TimeSpan.FromSeconds(10d); + private readonly TimeSpan speedTestPeriod = TimeSpan.FromMinutes(2d); + + /// + /// 域名解析后台服务 + /// + /// + /// + /// + public DomainResolveHostedService( + DnscryptProxy dnscryptProxy, + DomainSpeedTester speedTester, + ILogger logger) + { + this.dnscryptProxy = dnscryptProxy; + this.speedTester = speedTester; + this.logger = logger; + } + + /// + /// 停止时 + /// + /// + /// + public override async Task StopAsync(CancellationToken cancellationToken) + { + await this.speedTester.SaveDomainsAsync(); + this.dnscryptProxy.Stop(); + await base.StopAsync(cancellationToken); + } + + /// + /// 后台任务 + /// + /// + /// + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + try + { + await this.dnscryptProxy.StartAsync(stoppingToken); + } + catch (Exception ex) + { + this.logger.LogWarning($"{this.dnscryptProxy}启动失败:{ex.Message}"); + } + + await Task.Delay(this.speedTestDueTime, stoppingToken); + await this.speedTester.LoadDomainsAsync(stoppingToken); + while (stoppingToken.IsCancellationRequested == false) + { + await this.speedTester.TestSpeedAsync(stoppingToken); + await Task.Delay(this.speedTestPeriod, stoppingToken); + } + } + } +} diff --git a/FastGithub.DomainResolve/DomainResolver.cs b/FastGithub.DomainResolve/DomainResolver.cs index 236e1a4..c0374af 100644 --- a/FastGithub.DomainResolve/DomainResolver.cs +++ b/FastGithub.DomainResolve/DomainResolver.cs @@ -13,19 +13,19 @@ namespace FastGithub.DomainResolve sealed class DomainResolver : IDomainResolver { private readonly DnsClient dnsClient; - private readonly DomainSpeedTestService speedTestService; + private readonly DomainSpeedTester speedTester; /// /// 域名解析器 /// /// - /// + /// public DomainResolver( DnsClient dnsClient, - DomainSpeedTestService speedTestService) + DomainSpeedTester speedTester) { this.dnsClient = dnsClient; - this.speedTestService = speedTestService; + this.speedTester = speedTester; } /// @@ -51,7 +51,7 @@ namespace FastGithub.DomainResolve /// public async IAsyncEnumerable ResolveAllAsync(string domain, [EnumeratorCancellation] CancellationToken cancellationToken) { - var addresses = this.speedTestService.GetIPAddresses(domain); + var addresses = this.speedTester.GetIPAddresses(domain); if (addresses.Length > 0) { foreach (var address in addresses) @@ -61,7 +61,7 @@ namespace FastGithub.DomainResolve } else { - this.speedTestService.Add(domain); + this.speedTester.Add(domain); await foreach (var address in this.dnsClient.ResolveAsync(domain, cancellationToken)) { yield return address; diff --git a/FastGithub.DomainResolve/DomainSpeedTestHostedService.cs b/FastGithub.DomainResolve/DomainSpeedTestHostedService.cs deleted file mode 100644 index 6699073..0000000 --- a/FastGithub.DomainResolve/DomainSpeedTestHostedService.cs +++ /dev/null @@ -1,61 +0,0 @@ -using Microsoft.Extensions.Hosting; -using System; -using System.Threading; -using System.Threading.Tasks; - -namespace FastGithub.DomainResolve -{ - /// - /// 域名的IP测速后台服务 - /// - sealed class DomainSpeedTestHostedService : BackgroundService - { - private readonly DomainSpeedTestService speedTestService; - private readonly TimeSpan testDueTime = TimeSpan.FromMinutes(1d); - - /// - /// 域名的IP测速后台服务 - /// - /// - public DomainSpeedTestHostedService(DomainSpeedTestService speedTestService) - { - this.speedTestService = speedTestService; - } - - /// - /// 启动时 - /// - /// - /// - public override async Task StartAsync(CancellationToken cancellationToken) - { - await this.speedTestService.LoadDataAsync(cancellationToken); - await base.StartAsync(cancellationToken); - } - - /// - /// 停止时 - /// - /// - /// - public override async Task StopAsync(CancellationToken cancellationToken) - { - await this.speedTestService.SaveDataAsync(); - await base.StopAsync(cancellationToken); - } - - /// - /// 后台测速 - /// - /// - /// - protected override async Task ExecuteAsync(CancellationToken stoppingToken) - { - while (stoppingToken.IsCancellationRequested == false) - { - await this.speedTestService.TestSpeedAsync(stoppingToken); - await Task.Delay(this.testDueTime, stoppingToken); - } - } - } -} diff --git a/FastGithub.DomainResolve/DomainSpeedTestService.cs b/FastGithub.DomainResolve/DomainSpeedTester.cs similarity index 87% rename from FastGithub.DomainResolve/DomainSpeedTestService.cs rename to FastGithub.DomainResolve/DomainSpeedTester.cs index c957ff2..743edf0 100644 --- a/FastGithub.DomainResolve/DomainSpeedTestService.cs +++ b/FastGithub.DomainResolve/DomainSpeedTester.cs @@ -13,9 +13,9 @@ namespace FastGithub.DomainResolve /// /// 域名的IP测速服务 /// - sealed class DomainSpeedTestService + sealed class DomainSpeedTester { - private const string DATA_FILE = "domains.json"; + private const string DOMAINS_JSON_FILE = "domains.json"; private readonly DnsClient dnsClient; private readonly object syncRoot = new(); @@ -25,7 +25,7 @@ namespace FastGithub.DomainResolve /// 域名的IP测速服务 /// /// - public DomainSpeedTestService(DnsClient dnsClient) + public DomainSpeedTester(DnsClient dnsClient) { this.dnsClient = dnsClient; } @@ -61,18 +61,18 @@ namespace FastGithub.DomainResolve } /// - /// 加载数据 + /// 加载域名数据 /// /// /// - public async Task LoadDataAsync(CancellationToken cancellationToken) + public async Task LoadDomainsAsync(CancellationToken cancellationToken) { - if (File.Exists(DATA_FILE) == false) + if (File.Exists(DOMAINS_JSON_FILE) == false) { return; } - using var fileStream = File.OpenRead(DATA_FILE); + using var fileStream = File.OpenRead(DOMAINS_JSON_FILE); var domains = await JsonSerializer.DeserializeAsync(fileStream, cancellationToken: cancellationToken); if (domains == null) { @@ -89,10 +89,10 @@ namespace FastGithub.DomainResolve } /// - /// 保存数据 + /// 保存域名数据 /// /// - public async Task SaveDataAsync() + public async Task SaveDomainsAsync() { var domains = this.domainIPAddressHashSet.Keys .Select(item => new DomainPattern(item)) @@ -102,7 +102,7 @@ namespace FastGithub.DomainResolve try { - using var fileStream = File.OpenWrite(DATA_FILE); + using var fileStream = File.OpenWrite(DOMAINS_JSON_FILE); await JsonSerializer.SerializeAsync(fileStream, domains, new JsonSerializerOptions { WriteIndented = true }); return true; } diff --git a/FastGithub.DomainResolve/ServiceCollectionExtensions.cs b/FastGithub.DomainResolve/ServiceCollectionExtensions.cs index cf646a5..35234a8 100644 --- a/FastGithub.DomainResolve/ServiceCollectionExtensions.cs +++ b/FastGithub.DomainResolve/ServiceCollectionExtensions.cs @@ -18,10 +18,9 @@ namespace FastGithub { services.TryAddSingleton(); services.TryAddSingleton(); - services.TryAddSingleton(); + services.TryAddSingleton(); services.TryAddSingleton(); - services.AddHostedService(); - services.AddHostedService(); + services.AddHostedService(); return services; } } From 60784caa760ad4ec6d535eb121109da218368c4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=9B=BD=E4=BC=9F?= <366193849@qq.com> Date: Tue, 28 Sep 2021 13:37:55 +0800 Subject: [PATCH 5/8] =?UTF-8?q?=E4=BD=BF=E7=94=A8IDispose=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E6=9D=A5=E5=85=B3=E9=97=AD=E6=9C=8D=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FastGithub.DomainResolve/DnsClient.cs | 8 +- FastGithub.DomainResolve/DnscryptProxy.cs | 97 +++++++++----- .../DomainResolveHostedService.cs | 35 +---- FastGithub.DomainResolve/DomainSpeedTester.cs | 125 ++++++++++-------- 4 files changed, 148 insertions(+), 117 deletions(-) diff --git a/FastGithub.DomainResolve/DnsClient.cs b/FastGithub.DomainResolve/DnsClient.cs index 8a29636..fcbd061 100644 --- a/FastGithub.DomainResolve/DnsClient.cs +++ b/FastGithub.DomainResolve/DnsClient.cs @@ -145,10 +145,16 @@ namespace FastGithub.DomainResolve RecursionDesired = true, OperationCode = OperationCode.Query }; + request.Questions.Add(new Question(new Domain(domain), RecordType.A)); var clientRequest = new ClientRequest(resolver, request); var response = await clientRequest.Resolve(cancellationToken); - return response.AnswerRecords.OfType().Select(item => item.IPAddress).ToArray(); + + return response.AnswerRecords + .OfType() + .Where(item => IPAddress.IsLoopback(item.IPAddress) == false) + .Select(item => item.IPAddress) + .ToArray(); } } } diff --git a/FastGithub.DomainResolve/DnscryptProxy.cs b/FastGithub.DomainResolve/DnscryptProxy.cs index e6cbea6..d7784ba 100644 --- a/FastGithub.DomainResolve/DnscryptProxy.cs +++ b/FastGithub.DomainResolve/DnscryptProxy.cs @@ -1,4 +1,5 @@ using FastGithub.Configuration; +using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Diagnostics; @@ -15,11 +16,13 @@ namespace FastGithub.DomainResolve /// /// DnscryptProxy服务 /// - sealed class DnscryptProxy + sealed class DnscryptProxy : IDisposable { private const string PATH = "dnscrypt-proxy"; private const string NAME = "dnscrypt-proxy"; + private readonly ILogger logger; + /// /// 相关进程 /// @@ -30,12 +33,38 @@ namespace FastGithub.DomainResolve /// public IPEndPoint? LocalEndPoint { get; private set; } + /// + /// DnscryptProxy服务 + /// + /// + public DnscryptProxy(ILogger logger) + { + this.logger = logger; + } + /// /// 启动dnscrypt-proxy /// /// /// public async Task StartAsync(CancellationToken cancellationToken) + { + try + { + await this.StartCoreAsync(cancellationToken); + } + catch (Exception ex) + { + this.logger.LogWarning($"{NAME}启动失败:{ex.Message}"); + } + } + + /// + /// 启动dnscrypt-proxy + /// + /// + /// + private async Task StartCoreAsync(CancellationToken cancellationToken) { var tomlPath = Path.Combine(PATH, $"{NAME}.toml"); var port = GetAvailablePort(IPAddress.Loopback.AddressFamily); @@ -70,8 +99,6 @@ namespace FastGithub.DomainResolve } } - - /// /// 获取可用的随机端口 /// @@ -113,35 +140,6 @@ namespace FastGithub.DomainResolve this.LocalEndPoint = null; } - /// - /// 停止dnscrypt-proxy - /// - /// - public bool Stop() - { - try - { - if (OperatingSystem.IsWindows()) - { - StartDnscryptProxy("-service stop")?.WaitForExit(); - StartDnscryptProxy("-service uninstall")?.WaitForExit(); - } - if (this.process != null && this.process.HasExited == false) - { - this.process.Kill(); - } - return true; - } - catch (Exception) - { - return false; - } - finally - { - this.LocalEndPoint = null; - } - } - /// /// 启动DnscryptProxy进程 /// @@ -160,6 +158,41 @@ namespace FastGithub.DomainResolve }); } + /// + /// 释放资源 + /// + public void Dispose() + { + try + { + this.Stop(); + } + catch (Exception ex) + { + this.logger.LogWarning($"{NAME}停止失败:{ex.Message }"); + } + finally + { + this.LocalEndPoint = null; + } + } + + /// + /// 停止服务 + /// + private void Stop() + { + if (OperatingSystem.IsWindows()) + { + StartDnscryptProxy("-service stop")?.WaitForExit(); + StartDnscryptProxy("-service uninstall")?.WaitForExit(); + } + if (this.process != null && this.process.HasExited == false) + { + this.process.Kill(); + } + } + /// /// 转换为字符串 /// diff --git a/FastGithub.DomainResolve/DomainResolveHostedService.cs b/FastGithub.DomainResolve/DomainResolveHostedService.cs index 3e18641..bed0acd 100644 --- a/FastGithub.DomainResolve/DomainResolveHostedService.cs +++ b/FastGithub.DomainResolve/DomainResolveHostedService.cs @@ -1,5 +1,4 @@ using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; using System; using System.Threading; using System.Threading.Tasks; @@ -13,7 +12,6 @@ namespace FastGithub.DomainResolve { private readonly DnscryptProxy dnscryptProxy; private readonly DomainSpeedTester speedTester; - private readonly ILogger logger; private readonly TimeSpan speedTestDueTime = TimeSpan.FromSeconds(10d); private readonly TimeSpan speedTestPeriod = TimeSpan.FromMinutes(2d); @@ -22,29 +20,14 @@ namespace FastGithub.DomainResolve /// 域名解析后台服务 /// /// - /// - /// + /// public DomainResolveHostedService( DnscryptProxy dnscryptProxy, - DomainSpeedTester speedTester, - ILogger logger) + DomainSpeedTester speedTester) { this.dnscryptProxy = dnscryptProxy; this.speedTester = speedTester; - this.logger = logger; - } - - /// - /// 停止时 - /// - /// - /// - public override async Task StopAsync(CancellationToken cancellationToken) - { - await this.speedTester.SaveDomainsAsync(); - this.dnscryptProxy.Stop(); - await base.StopAsync(cancellationToken); - } + } /// /// 后台任务 @@ -53,17 +36,9 @@ namespace FastGithub.DomainResolve /// protected override async Task ExecuteAsync(CancellationToken stoppingToken) { - try - { - await this.dnscryptProxy.StartAsync(stoppingToken); - } - catch (Exception ex) - { - this.logger.LogWarning($"{this.dnscryptProxy}启动失败:{ex.Message}"); - } - + await this.dnscryptProxy.StartAsync(stoppingToken); await Task.Delay(this.speedTestDueTime, stoppingToken); - await this.speedTester.LoadDomainsAsync(stoppingToken); + while (stoppingToken.IsCancellationRequested == false) { await this.speedTester.TestSpeedAsync(stoppingToken); diff --git a/FastGithub.DomainResolve/DomainSpeedTester.cs b/FastGithub.DomainResolve/DomainSpeedTester.cs index 743edf0..a300530 100644 --- a/FastGithub.DomainResolve/DomainSpeedTester.cs +++ b/FastGithub.DomainResolve/DomainSpeedTester.cs @@ -1,4 +1,5 @@ using FastGithub.Configuration; +using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.IO; @@ -13,10 +14,12 @@ namespace FastGithub.DomainResolve /// /// 域名的IP测速服务 /// - sealed class DomainSpeedTester + sealed class DomainSpeedTester : IDisposable { private const string DOMAINS_JSON_FILE = "domains.json"; + private readonly DnsClient dnsClient; + private readonly ILogger logger; private readonly object syncRoot = new(); private readonly Dictionary domainIPAddressHashSet = new(); @@ -25,9 +28,45 @@ namespace FastGithub.DomainResolve /// 域名的IP测速服务 /// /// - public DomainSpeedTester(DnsClient dnsClient) + /// + public DomainSpeedTester( + DnsClient dnsClient, + ILogger logger) { this.dnsClient = dnsClient; + this.logger = logger; + + try + { + this.LoadDomains(); + } + catch (Exception ex) + { + logger.LogWarning($"加载域名数据失败:{ex.Message}"); + } + } + + /// + /// 加载域名数据 + /// + private void LoadDomains() + { + if (File.Exists(DOMAINS_JSON_FILE) == false) + { + return; + } + + var utf8Json = File.ReadAllBytes(DOMAINS_JSON_FILE); + var domains = JsonSerializer.Deserialize(utf8Json); + if (domains == null) + { + return; + } + + foreach (var domain in domains) + { + this.domainIPAddressHashSet.TryAdd(domain, new IPAddressItemHashSet()); + } } /// @@ -60,58 +99,6 @@ namespace FastGithub.DomainResolve } } - /// - /// 加载域名数据 - /// - /// - /// - public async Task LoadDomainsAsync(CancellationToken cancellationToken) - { - if (File.Exists(DOMAINS_JSON_FILE) == false) - { - return; - } - - using var fileStream = File.OpenRead(DOMAINS_JSON_FILE); - var domains = await JsonSerializer.DeserializeAsync(fileStream, cancellationToken: cancellationToken); - if (domains == null) - { - return; - } - - lock (this.syncRoot) - { - foreach (var domain in domains) - { - this.domainIPAddressHashSet.TryAdd(domain, new IPAddressItemHashSet()); - } - } - } - - /// - /// 保存域名数据 - /// - /// - public async Task SaveDomainsAsync() - { - var domains = this.domainIPAddressHashSet.Keys - .Select(item => new DomainPattern(item)) - .OrderBy(item => item) - .Select(item => item.ToString()) - .ToArray(); - - try - { - using var fileStream = File.OpenWrite(DOMAINS_JSON_FILE); - await JsonSerializer.SerializeAsync(fileStream, domains, new JsonSerializerOptions { WriteIndented = true }); - return true; - } - catch (Exception) - { - return false; - } - } - /// /// 进行一轮IP测速 /// @@ -136,5 +123,35 @@ namespace FastGithub.DomainResolve await hashSet.PingAllAsync(); } } + + /// + /// 释放资源 + /// + public void Dispose() + { + try + { + this.SaveDomains(); + } + catch (Exception ex) + { + this.logger.LogWarning($"保存域名数据失败:{ex.Message}"); + } + } + + /// + /// 保存域名 + /// + private void SaveDomains() + { + var domains = this.domainIPAddressHashSet.Keys + .Select(item => new DomainPattern(item)) + .OrderBy(item => item) + .Select(item => item.ToString()) + .ToArray(); + + var utf8Json = JsonSerializer.SerializeToUtf8Bytes(domains, new JsonSerializerOptions { WriteIndented = true }); + File.WriteAllBytes(DOMAINS_JSON_FILE, utf8Json); + } } } From 12d9598a3e1b2b669f99a5cbf4e63d3b09690561 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=9B=BD=E4=BC=9F?= <366193849@qq.com> Date: Tue, 28 Sep 2021 17:03:56 +0800 Subject: [PATCH 6/8] =?UTF-8?q?=E8=87=AA=E5=8A=A8=E4=BF=9D=E5=AD=98?= =?UTF-8?q?=E5=9F=9F=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FastGithub.DomainResolve/DnscryptProxy.cs | 64 ++++++++----------- .../DomainResolveHostedService.cs | 13 +++- FastGithub.DomainResolve/DomainSpeedTester.cs | 62 ++++++++---------- 3 files changed, 68 insertions(+), 71 deletions(-) diff --git a/FastGithub.DomainResolve/DnscryptProxy.cs b/FastGithub.DomainResolve/DnscryptProxy.cs index d7784ba..e00dc0e 100644 --- a/FastGithub.DomainResolve/DnscryptProxy.cs +++ b/FastGithub.DomainResolve/DnscryptProxy.cs @@ -16,7 +16,7 @@ namespace FastGithub.DomainResolve /// /// DnscryptProxy服务 /// - sealed class DnscryptProxy : IDisposable + sealed class DnscryptProxy { private const string PATH = "dnscrypt-proxy"; private const string NAME = "dnscrypt-proxy"; @@ -99,6 +99,33 @@ namespace FastGithub.DomainResolve } } + /// + /// 停止服务 + /// + public void Stop() + { + try + { + if (OperatingSystem.IsWindows()) + { + StartDnscryptProxy("-service stop")?.WaitForExit(); + StartDnscryptProxy("-service uninstall")?.WaitForExit(); + } + if (this.process != null && this.process.HasExited == false) + { + this.process.Kill(); + } + } + catch (Exception ex) + { + this.logger.LogWarning($"{NAME}停止失败:{ex.Message }"); + } + finally + { + this.LocalEndPoint = null; + } + } + /// /// 获取可用的随机端口 /// @@ -158,41 +185,6 @@ namespace FastGithub.DomainResolve }); } - /// - /// 释放资源 - /// - public void Dispose() - { - try - { - this.Stop(); - } - catch (Exception ex) - { - this.logger.LogWarning($"{NAME}停止失败:{ex.Message }"); - } - finally - { - this.LocalEndPoint = null; - } - } - - /// - /// 停止服务 - /// - private void Stop() - { - if (OperatingSystem.IsWindows()) - { - StartDnscryptProxy("-service stop")?.WaitForExit(); - StartDnscryptProxy("-service uninstall")?.WaitForExit(); - } - if (this.process != null && this.process.HasExited == false) - { - this.process.Kill(); - } - } - /// /// 转换为字符串 /// diff --git a/FastGithub.DomainResolve/DomainResolveHostedService.cs b/FastGithub.DomainResolve/DomainResolveHostedService.cs index bed0acd..ba2a4df 100644 --- a/FastGithub.DomainResolve/DomainResolveHostedService.cs +++ b/FastGithub.DomainResolve/DomainResolveHostedService.cs @@ -27,7 +27,7 @@ namespace FastGithub.DomainResolve { this.dnscryptProxy = dnscryptProxy; this.speedTester = speedTester; - } + } /// /// 后台任务 @@ -45,5 +45,16 @@ namespace FastGithub.DomainResolve await Task.Delay(this.speedTestPeriod, stoppingToken); } } + + /// + /// 停止服务 + /// + /// + /// + public override Task StopAsync(CancellationToken cancellationToken) + { + this.dnscryptProxy.Stop(); + return base.StopAsync(cancellationToken); + } } } diff --git a/FastGithub.DomainResolve/DomainSpeedTester.cs b/FastGithub.DomainResolve/DomainSpeedTester.cs index a300530..b832bcd 100644 --- a/FastGithub.DomainResolve/DomainSpeedTester.cs +++ b/FastGithub.DomainResolve/DomainSpeedTester.cs @@ -14,7 +14,7 @@ namespace FastGithub.DomainResolve /// /// 域名的IP测速服务 /// - sealed class DomainSpeedTester : IDisposable + sealed class DomainSpeedTester { private const string DOMAINS_JSON_FILE = "domains.json"; @@ -73,15 +73,39 @@ namespace FastGithub.DomainResolve /// 添加要测速的域名 /// /// - /// - public bool Add(string domain) + public void Add(string domain) { lock (this.syncRoot) { - return this.domainIPAddressHashSet.TryAdd(domain, new IPAddressItemHashSet()); + if (this.domainIPAddressHashSet.TryAdd(domain, new IPAddressItemHashSet())) + { + try + { + this.SaveDomains(); + } + catch (Exception ex) + { + logger.LogWarning($"保存域名数据失败:{ex.Message}"); + } + } } } + /// + /// 保存域名 + /// + private void SaveDomains() + { + var domains = this.domainIPAddressHashSet.Keys + .Select(item => new DomainPattern(item)) + .OrderBy(item => item) + .Select(item => item.ToString()) + .ToArray(); + + var utf8Json = JsonSerializer.SerializeToUtf8Bytes(domains, new JsonSerializerOptions { WriteIndented = true }); + File.WriteAllBytes(DOMAINS_JSON_FILE, utf8Json); + } + /// /// 获取测试后排序的IP /// @@ -123,35 +147,5 @@ namespace FastGithub.DomainResolve await hashSet.PingAllAsync(); } } - - /// - /// 释放资源 - /// - public void Dispose() - { - try - { - this.SaveDomains(); - } - catch (Exception ex) - { - this.logger.LogWarning($"保存域名数据失败:{ex.Message}"); - } - } - - /// - /// 保存域名 - /// - private void SaveDomains() - { - var domains = this.domainIPAddressHashSet.Keys - .Select(item => new DomainPattern(item)) - .OrderBy(item => item) - .Select(item => item.ToString()) - .ToArray(); - - var utf8Json = JsonSerializer.SerializeToUtf8Bytes(domains, new JsonSerializerOptions { WriteIndented = true }); - File.WriteAllBytes(DOMAINS_JSON_FILE, utf8Json); - } } } From efb59f253508c187f98268e74d697bb3e3d19119 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=9B=BD=E4=BC=9F?= <366193849@qq.com> Date: Tue, 28 Sep 2021 17:32:52 +0800 Subject: [PATCH 7/8] =?UTF-8?q?=E4=BF=AE=E6=94=B9dns=E7=BC=93=E5=AD=98?= =?UTF-8?q?=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FastGithub.DomainResolve/DnsClient.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/FastGithub.DomainResolve/DnsClient.cs b/FastGithub.DomainResolve/DnsClient.cs index fcbd061..06116b8 100644 --- a/FastGithub.DomainResolve/DnsClient.cs +++ b/FastGithub.DomainResolve/DnsClient.cs @@ -31,7 +31,7 @@ namespace FastGithub.DomainResolve private readonly ConcurrentDictionary semaphoreSlims = new(); private readonly IMemoryCache dnsCache = new MemoryCache(Options.Create(new MemoryCacheOptions())); - private readonly TimeSpan dnsExpiration = TimeSpan.FromMinutes(2d); + private readonly TimeSpan dnsExpiration = TimeSpan.FromMinutes(1d); private readonly int resolveTimeout = (int)TimeSpan.FromSeconds(2d).TotalMilliseconds; /// @@ -108,6 +108,9 @@ namespace FastGithub.DomainResolve { value = await this.LookupCoreAsync(dns, domain, cancellationToken); this.dnsCache.Set(key, value, this.dnsExpiration); + + var items = string.Join(", ", value.Select(item => item.ToString())); + this.logger.LogInformation($"dns://{dns}:{domain}->[{items}]"); } return value; } From 7bd3bacfcc0077f5fd10938613de29ec7cad63c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=9B=BD=E4=BC=9F?= <366193849@qq.com> Date: Tue, 28 Sep 2021 17:45:06 +0800 Subject: [PATCH 8/8] =?UTF-8?q?cryptDns=E9=87=8D=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FastGithub.DomainResolve/DnsClient.cs | 1 + .../FastGithub.DomainResolve.csproj | 12 ++++++++++ FastGithub.DomainResolve/domains.json | 22 +++++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 FastGithub.DomainResolve/domains.json diff --git a/FastGithub.DomainResolve/DnsClient.cs b/FastGithub.DomainResolve/DnsClient.cs index 06116b8..2751488 100644 --- a/FastGithub.DomainResolve/DnsClient.cs +++ b/FastGithub.DomainResolve/DnsClient.cs @@ -81,6 +81,7 @@ namespace FastGithub.DomainResolve if (cryptDns != null) { yield return cryptDns; + yield return cryptDns; } foreach (var fallbackDns in this.fastGithubConfig.FallbackDns) diff --git a/FastGithub.DomainResolve/FastGithub.DomainResolve.csproj b/FastGithub.DomainResolve/FastGithub.DomainResolve.csproj index 0ad99be..ba4e9a8 100644 --- a/FastGithub.DomainResolve/FastGithub.DomainResolve.csproj +++ b/FastGithub.DomainResolve/FastGithub.DomainResolve.csproj @@ -17,4 +17,16 @@ + + + + + + + PreserveNewest + true + PreserveNewest + + + diff --git a/FastGithub.DomainResolve/domains.json b/FastGithub.DomainResolve/domains.json new file mode 100644 index 0000000..71d5fc7 --- /dev/null +++ b/FastGithub.DomainResolve/domains.json @@ -0,0 +1,22 @@ +[ + "github.com", + "v2ex.com", + "alive.github.com", + "api.github.com", + "collector.githubapp.com", + "github.githubassets.com", + "avatars.githubusercontent.com", + "camo.githubusercontent.com", + "github-releases.githubusercontent.com", + "raw.githubusercontent.com", + "www.gravatar.com", + "onedrive.live.com", + "cdn.v2ex.com", + "microsoft.github.io", + "fonts.geekzu.org", + "gapis.geekzu.org", + "i.stack.imgur.com", + "skyapi.onedrive.live.com", + "codeproject.freetls.fastly.net", + "codeproject.global.ssl.fastly.net" +] \ No newline at end of file