diff --git a/FastGithub.DomainResolve/DnscryptProxy.cs b/FastGithub.DomainResolve/DnscryptProxy.cs index a8f47c7..21889b8 100644 --- a/FastGithub.DomainResolve/DnscryptProxy.cs +++ b/FastGithub.DomainResolve/DnscryptProxy.cs @@ -25,16 +25,7 @@ namespace FastGithub.DomainResolve /// /// 获取监听的节点 /// - public IPEndPoint EndPoint { get; } - - /// - /// DnscryptProxy服务 - /// - public DnscryptProxy() - { - var port = LocalMachine.GetAvailablePort(IPAddress.Loopback.AddressFamily, min: 5353); - this.EndPoint = new IPEndPoint(IPAddress.Loopback, port); - } + public IPEndPoint? LocalEndPoint { get; private set; } /// /// 启动dnscrypt-proxy @@ -44,7 +35,10 @@ namespace FastGithub.DomainResolve public async Task StartAsync(CancellationToken cancellationToken) { var tomlPath = Path.Combine(PATH, $"{NAME}.toml"); - await TomlUtil.SetListensAsync(tomlPath, this.EndPoint, cancellationToken); + var port = LocalMachine.GetAvailablePort(IPAddress.Loopback.AddressFamily, min: 5353); + var localEndPoint = new IPEndPoint(IPAddress.Loopback, port); + + await TomlUtil.SetListensAsync(tomlPath, localEndPoint, cancellationToken); await TomlUtil.SetEdnsClientSubnetAsync(tomlPath, cancellationToken); foreach (var process in Process.GetProcessesByName(NAME)) @@ -64,6 +58,23 @@ namespace FastGithub.DomainResolve { this.process = StartDnscryptProxy(string.Empty); } + + if (this.process != null) + { + this.LocalEndPoint = localEndPoint; + this.process.EnableRaisingEvents = true; + this.process.Exited += Process_Exited; + } + } + + /// + /// 进程退出时 + /// + /// + /// + private void Process_Exited(object? sender, EventArgs e) + { + this.LocalEndPoint = null; } /// @@ -81,6 +92,7 @@ namespace FastGithub.DomainResolve { this.process.Kill(); } + this.LocalEndPoint = null; } /// diff --git a/FastGithub.DomainResolve/DomainResolver.cs b/FastGithub.DomainResolve/DomainResolver.cs index 60fdc06..2601817 100644 --- a/FastGithub.DomainResolve/DomainResolver.cs +++ b/FastGithub.DomainResolve/DomainResolver.cs @@ -53,16 +53,16 @@ namespace FastGithub.DomainResolve /// /// 解析域名 /// - /// + /// /// /// - public async Task ResolveAsync(DnsEndPoint endPoint, CancellationToken cancellationToken = default) + public async Task ResolveAsync(DnsEndPoint domain, CancellationToken cancellationToken = default) { - var semaphore = this.semaphoreSlims.GetOrAdd(endPoint, _ => new SemaphoreSlim(1, 1)); + var semaphore = this.semaphoreSlims.GetOrAdd(domain, _ => new SemaphoreSlim(1, 1)); try { await semaphore.WaitAsync(cancellationToken); - return await this.LookupAsync(endPoint, cancellationToken); + return await this.LookupAsync(domain, cancellationToken); } finally { @@ -73,28 +73,31 @@ namespace FastGithub.DomainResolve /// /// 查找ip /// - /// + /// /// /// - private async Task LookupAsync(DnsEndPoint target, CancellationToken cancellationToken) + private async Task LookupAsync(DnsEndPoint domain, CancellationToken cancellationToken) { - if (this.memoryCache.TryGetValue(target, out var address)) + if (this.memoryCache.TryGetValue(domain, out var address)) { return address; } var expiration = this.dnscryptExpiration; - address = await this.LookupCoreAsync(this.dnscryptProxy.EndPoint, target, cancellationToken); - - if (address == null) + if (this.dnscryptProxy.LocalEndPoint != null) { - expiration = this.fallbackExpiration; - address = await this.FallbackLookupAsync(target, cancellationToken); + address = await this.LookupCoreAsync(this.dnscryptProxy.LocalEndPoint, domain, cancellationToken); } if (address == null) { - throw new FastGithubException($"当前解析不到{target.Host}可用的ip,请刷新重试"); + expiration = this.fallbackExpiration; + address = await this.FallbackLookupAsync(domain, cancellationToken); + } + + if (address == null) + { + throw new FastGithubException($"当前解析不到{domain.Host}可用的ip,请刷新重试"); } // 往往是被污染的dns @@ -103,22 +106,22 @@ namespace FastGithub.DomainResolve expiration = this.loopbackExpiration; } - this.logger.LogInformation($"[{target.Host}->{address}]"); - this.memoryCache.Set(target, address, expiration); + this.logger.LogInformation($"[{domain.Host}->{address}]"); + this.memoryCache.Set(domain, address, expiration); return address; } /// /// 回退查找ip /// - /// + /// /// /// - private async Task FallbackLookupAsync(DnsEndPoint target, CancellationToken cancellationToken) + private async Task FallbackLookupAsync(DnsEndPoint domain, CancellationToken cancellationToken) { foreach (var dns in this.fastGithubConfig.FallbackDns) { - var address = await this.LookupCoreAsync(dns, target, cancellationToken); + var address = await this.LookupCoreAsync(dns, domain, cancellationToken); if (address != null) { return address; @@ -132,22 +135,22 @@ namespace FastGithub.DomainResolve /// 查找ip /// /// - /// + /// /// /// - private async Task LookupCoreAsync(IPEndPoint dns, DnsEndPoint target, CancellationToken cancellationToken) + private async Task LookupCoreAsync(IPEndPoint dns, DnsEndPoint domain, CancellationToken cancellationToken) { try { var dnsClient = new DnsClient(dns); using var timeoutTokenSource = new CancellationTokenSource(this.lookupTimeout); using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutTokenSource.Token); - var addresses = await dnsClient.Lookup(target.Host, RecordType.A, linkedTokenSource.Token); - return await this.FindFastValueAsync(addresses, target.Port, cancellationToken); + var addresses = await dnsClient.Lookup(domain.Host, RecordType.A, linkedTokenSource.Token); + return await this.FindFastValueAsync(addresses, domain.Port, cancellationToken); } catch (Exception ex) { - this.logger.LogWarning($"dns({dns})无法解析{target.Host}:{ex.Message}"); + this.logger.LogWarning($"dns({dns})无法解析{domain.Host}:{ex.Message}"); return default; } } diff --git a/FastGithub.DomainResolve/IDomainResolver.cs b/FastGithub.DomainResolve/IDomainResolver.cs index 5e5a257..801a187 100644 --- a/FastGithub.DomainResolve/IDomainResolver.cs +++ b/FastGithub.DomainResolve/IDomainResolver.cs @@ -12,9 +12,9 @@ namespace FastGithub.DomainResolve /// /// 解析域名 /// - /// + /// /// /// - Task ResolveAsync(DnsEndPoint target, CancellationToken cancellationToken = default); + Task ResolveAsync(DnsEndPoint domain, CancellationToken cancellationToken = default); } } \ No newline at end of file