类型重命名

This commit is contained in:
老九 2021-10-01 00:13:01 +08:00
parent 255c44af9c
commit 34d3402f0b
6 changed files with 171 additions and 127 deletions

View File

@ -2,10 +2,8 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
@ -18,7 +16,7 @@ namespace FastGithub.DomainResolve
sealed class DomainResolver : IDomainResolver
{
private readonly DnsClient dnsClient;
private readonly ConcurrentDictionary<DnsEndPoint, IPAddressTestResult> dnsEndPointAddressTestResult = new();
private readonly ConcurrentDictionary<DnsEndPoint, IPAddressElapsedCollection> dnsEndPointAddressElapseds = new();
/// <summary>
/// 域名解析器
@ -35,72 +33,9 @@ namespace FastGithub.DomainResolve
/// <param name="domain">域名</param>
public void Prefetch(string domain)
{
var endPoint = new DnsEndPoint(domain, 443);
this.dnsEndPointAddressTestResult.TryAdd(endPoint, IPAddressTestResult.Empty);
}
/// <summary>
/// 对所有节点进行测速
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task TestAllEndPointsAsync(CancellationToken cancellationToken)
{
foreach (var keyValue in this.dnsEndPointAddressTestResult)
{
if (keyValue.Value.IsEmpty || keyValue.Value.IsExpired)
{
var dnsEndPoint = keyValue.Key;
var addresses = new List<IPAddress>();
await foreach (var adddress in this.dnsClient.ResolveAsync(dnsEndPoint.Host, cancellationToken))
{
addresses.Add(adddress);
}
var addressTestResult = IPAddressTestResult.Empty;
if (addresses.Count == 1)
{
var addressElapseds = new[] { new IPAddressElapsed(addresses[0], TimeSpan.Zero) };
addressTestResult = new IPAddressTestResult(addressElapseds);
}
else if (addresses.Count > 1)
{
var tasks = addresses.Select(item => GetIPAddressElapsedAsync(item, dnsEndPoint.Port, cancellationToken));
var addressElapseds = await Task.WhenAll(tasks);
addressTestResult = new IPAddressTestResult(addressElapseds);
}
this.dnsEndPointAddressTestResult[dnsEndPoint] = addressTestResult;
}
}
}
/// <summary>
/// 获取连接耗时
/// </summary>
/// <param name="address"></param>
/// <param name="port"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
private static async Task<IPAddressElapsed> GetIPAddressElapsedAsync(IPAddress address, int port, CancellationToken cancellationToken)
{
var stopWatch = Stopwatch.StartNew();
try
{
using var timeoutTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(10d));
using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutTokenSource.Token);
using var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
await socket.ConnectAsync(address, port, linkedTokenSource.Token);
return new IPAddressElapsed(address, stopWatch.Elapsed);
}
catch (Exception)
{
cancellationToken.ThrowIfCancellationRequested();
return new IPAddressElapsed(address, TimeSpan.MaxValue);
}
finally
{
stopWatch.Stop();
}
const int HTTPS_PORT = 443;
var dnsEndPoint = new DnsEndPoint(domain, HTTPS_PORT);
this.dnsEndPointAddressElapseds.TryAdd(dnsEndPoint, IPAddressElapsedCollection.Empty);
}
/// <summary>
@ -126,21 +61,55 @@ namespace FastGithub.DomainResolve
/// <returns></returns>
public async IAsyncEnumerable<IPAddress> ResolveAllAsync(DnsEndPoint endPoint, [EnumeratorCancellation] CancellationToken cancellationToken)
{
if (this.dnsEndPointAddressTestResult.TryGetValue(endPoint, out var speedTestResult) && speedTestResult.IsEmpty == false)
if (this.dnsEndPointAddressElapseds.TryGetValue(endPoint, out var addressElapseds) && addressElapseds.IsEmpty == false)
{
foreach (var addressElapsed in speedTestResult.AddressElapseds)
foreach (var addressElapsed in addressElapseds)
{
yield return addressElapsed.Adddress;
}
}
else
{
this.dnsEndPointAddressTestResult.TryAdd(endPoint, IPAddressTestResult.Empty);
this.dnsEndPointAddressElapseds.TryAdd(endPoint, IPAddressElapsedCollection.Empty);
await foreach (var adddress in this.dnsClient.ResolveAsync(endPoint.Host, cancellationToken))
{
yield return adddress;
}
}
}
/// <summary>
/// 对所有节点进行测速
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task TestAllEndPointsAsync(CancellationToken cancellationToken)
{
foreach (var keyValue in this.dnsEndPointAddressElapseds)
{
if (keyValue.Value.IsEmpty || keyValue.Value.IsExpired)
{
var dnsEndPoint = keyValue.Key;
var addresses = new List<IPAddress>();
await foreach (var adddress in this.dnsClient.ResolveAsync(dnsEndPoint.Host, cancellationToken))
{
addresses.Add(adddress);
}
var addressElapseds = IPAddressElapsedCollection.Empty;
if (addresses.Count == 1)
{
var addressElapsed = new IPAddressElapsed(addresses[0], TimeSpan.Zero);
addressElapseds = new IPAddressElapsedCollection(addressElapsed);
}
else if (addresses.Count > 1)
{
var tasks = addresses.Select(address => IPAddressElapsed.ParseAsync(address, dnsEndPoint.Port, cancellationToken));
addressElapseds = new IPAddressElapsedCollection(await Task.WhenAll(tasks));
}
this.dnsEndPointAddressElapseds[dnsEndPoint] = addressElapseds;
}
}
}
}
}

View File

@ -16,13 +16,6 @@ namespace FastGithub.DomainResolve
/// <param name="domain">域名</param>
void Prefetch(string domain);
/// <summary>
/// 对所有节点进行测速
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task TestAllEndPointsAsync(CancellationToken cancellationToken);
/// <summary>
/// 解析ip
/// </summary>
@ -38,5 +31,12 @@ namespace FastGithub.DomainResolve
/// <param name="cancellationToken"></param>
/// <returns></returns>
IAsyncEnumerable<IPAddress> ResolveAllAsync(DnsEndPoint endPoint, CancellationToken cancellationToken = default);
/// <summary>
/// 对所有节点进行测速
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task TestAllEndPointsAsync(CancellationToken cancellationToken = default);
}
}

View File

@ -1,27 +1,32 @@
using System;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
namespace FastGithub.DomainResolve
{
/// <summary>
/// IP连接耗
/// IP
/// </summary>
[DebuggerDisplay("Adddress={Adddress} Elapsed={Elapsed}")]
struct IPAddressElapsed
{
private static readonly TimeSpan connectTimeout = TimeSpan.FromSeconds(10d);
/// <summary>
/// 获取IP地址
/// </summary>
public IPAddress Adddress { get; }
/// <summary>
/// 获取连接耗
/// 获取
/// </summary>
public TimeSpan Elapsed { get; }
/// <summary>
/// IP连接耗
/// IP
/// </summary>
/// <param name="adddress"></param>
/// <param name="elapsed"></param>
@ -30,5 +35,34 @@ namespace FastGithub.DomainResolve
this.Adddress = adddress;
this.Elapsed = elapsed;
}
/// <summary>
/// 获取连接耗时
/// </summary>
/// <param name="address"></param>
/// <param name="port"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<IPAddressElapsed> ParseAsync(IPAddress address, int port, CancellationToken cancellationToken)
{
var stopWatch = Stopwatch.StartNew();
try
{
using var timeoutTokenSource = new CancellationTokenSource(connectTimeout);
using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutTokenSource.Token);
using var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
await socket.ConnectAsync(address, port, linkedTokenSource.Token);
return new IPAddressElapsed(address, stopWatch.Elapsed);
}
catch (Exception)
{
cancellationToken.ThrowIfCancellationRequested();
return new IPAddressElapsed(address, TimeSpan.MaxValue);
}
finally
{
stopWatch.Stop();
}
}
}
}

View File

@ -0,0 +1,80 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace FastGithub.DomainResolve
{
/// <summary>
/// IP延时集合
/// </summary>
[DebuggerDisplay("Count={Count} IsExpired={IsExpired}")]
sealed class IPAddressElapsedCollection : IEnumerable<IPAddressElapsed>
{
private readonly List<IPAddressElapsed> addressElapseds;
private readonly int creationTickCount = Environment.TickCount;
private static readonly int maxLifeTime = 60 * 1000;
/// <summary>
/// 获取空的
/// </summary>
public static IPAddressElapsedCollection Empty = new();
/// <summary>
/// 获取数量
/// </summary>
public int Count => this.addressElapseds.Count;
/// <summary>
/// 获取是否为空
/// </summary>
public bool IsEmpty => this.addressElapseds.Count == 0;
/// <summary>
/// 获取是否已过期
/// </summary>
public bool IsExpired => Environment.TickCount - this.creationTickCount > maxLifeTime;
/// <summary>
/// IP延时集合
/// </summary>
private IPAddressElapsedCollection()
{
this.addressElapseds = new List<IPAddressElapsed>();
this.creationTickCount = 0;
}
/// <summary>
/// IP延时集合
/// </summary>
/// <param name="addressElapsed"></param>
public IPAddressElapsedCollection(IPAddressElapsed addressElapsed)
{
this.addressElapseds = new List<IPAddressElapsed> { addressElapsed };
}
/// <summary>
/// IP延时集合
/// </summary>
/// <param name="addressElapseds"></param>
public IPAddressElapsedCollection(IEnumerable<IPAddressElapsed> addressElapseds)
{
this.addressElapseds = addressElapseds.OrderBy(item => item.Elapsed).ToList();
}
/// <summary>
/// 获取迭代器
/// </summary>
/// <returns></returns>
public IEnumerator<IPAddressElapsed> GetEnumerator()
{
return this.addressElapseds.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.addressElapseds.GetEnumerator();
}
}
}

View File

@ -1,44 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace FastGithub.DomainResolve
{
/// <summary>
/// IP测速结果
/// </summary>
sealed class IPAddressTestResult
{
private static readonly TimeSpan lifeTime = TimeSpan.FromMinutes(2d);
private readonly int creationTickCount = Environment.TickCount;
/// <summary>
/// 获取空的
/// </summary>
public static IPAddressTestResult Empty = new(Array.Empty<IPAddressElapsed>());
/// <summary>
/// 获取是否为空
/// </summary>
public bool IsEmpty => this.AddressElapseds.Length == 0;
/// <summary>
/// 获取是否已过期
/// </summary>
public bool IsExpired => lifeTime < TimeSpan.FromMilliseconds(Environment.TickCount - this.creationTickCount);
/// <summary>
/// 获取测速结果
/// </summary>
public IPAddressElapsed[] AddressElapseds { get; }
/// <summary>
/// 测速结果
/// </summary>
/// <param name="result"></param>
public IPAddressTestResult(IEnumerable<IPAddressElapsed> addressElapseds)
{
this.AddressElapseds = addressElapseds.OrderBy(item => item.Elapsed).ToArray();
}
}
}

View File

@ -1,4 +1,5 @@
using Microsoft.Extensions.Hosting;
using FastGithub.WinDiverts;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
@ -45,6 +46,10 @@ namespace FastGithub.PacketIntercept
/// <returns></returns>
public override async Task StartAsync(CancellationToken cancellationToken)
{
// 首次加载驱动往往有异常,所以要提前加载
var handle = WinDivert.WinDivertOpen("true", WinDivertLayer.Network, 0, WinDivertOpenFlags.None);
WinDivert.WinDivertClose(handle);
foreach (var solver in this.conflictSolvers)
{
await solver.SolveAsync(cancellationToken);