using FastGithub.Configuration; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.Net; using System.Threading; using System.Threading.Tasks; namespace FastGithub.Dns { /// /// dns后台服务 /// sealed class DnsOverUdpHostedService : BackgroundService { private readonly DnsOverUdpServer dnsOverUdpServer; private readonly IEnumerable conflictValidators; private readonly IOptionsMonitor options; private readonly ILogger logger; /// /// dns后台服务 /// /// /// /// /// public DnsOverUdpHostedService( DnsOverUdpServer dnsOverUdpServer, IEnumerable conflictValidators, IOptionsMonitor options, ILogger logger) { this.dnsOverUdpServer = dnsOverUdpServer; this.conflictValidators = conflictValidators; this.options = options; this.logger = logger; options.OnChange(opt => SystemDnsUtil.FlushResolverCache()); } /// /// 启动dns /// /// /// public override async Task StartAsync(CancellationToken cancellationToken) { var dnsPort = this.options.CurrentValue.Listen.DnsPort; this.dnsOverUdpServer.Bind(IPAddress.Any, dnsPort); this.logger.LogInformation($"已监听udp端口{dnsPort},DNS服务启动完成"); const int STANDARD_DNS_PORT = 53; if (dnsPort == STANDARD_DNS_PORT) { try { SystemDnsUtil.SetAsPrimitiveDns(); SystemDnsUtil.FlushResolverCache(); } catch (Exception ex) { this.logger.LogWarning(ex.Message); } } else { this.logger.LogWarning($"由于使用了非标准DNS端口{dnsPort},你需要将{nameof(FastGithub)}设置为标准DNS的上游"); } foreach (var item in this.conflictValidators) { await item.ValidateAsync(); } await base.StartAsync(cancellationToken); } /// /// dns后台 /// /// /// protected override Task ExecuteAsync(CancellationToken stoppingToken) { return this.dnsOverUdpServer.HandleAsync(stoppingToken); } /// /// 停止dns服务 /// /// /// public override Task StopAsync(CancellationToken cancellationToken) { this.dnsOverUdpServer.Dispose(); this.logger.LogInformation("DNS服务已停止"); try { SystemDnsUtil.RemoveFromPrimitiveDns(); } catch (Exception ex) { this.logger.LogWarning(ex.Message); } finally { SystemDnsUtil.FlushResolverCache(); } return base.StopAsync(cancellationToken); } } }