using FastGithub.Configuration; using Microsoft.Extensions.Logging; using System; using System.IO; using System.Runtime.Versioning; using System.Text; using System.Threading; using System.Threading.Tasks; namespace FastGithub.PacketIntercept.Dns { /// /// host文件冲解决者 /// [SupportedOSPlatform("windows")] sealed class HostsConflictSolver : IDnsConflictSolver { private readonly FastGithubConfig fastGithubConfig; private readonly ILogger logger; /// /// host文件冲解决者 /// /// /// public HostsConflictSolver( FastGithubConfig fastGithubConfig, ILogger logger) { this.fastGithubConfig = fastGithubConfig; this.logger = logger; } /// /// 解决冲突 /// /// /// public async Task SolveAsync(CancellationToken cancellationToken) { var hostsPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "drivers/etc/hosts"); if (File.Exists(hostsPath) == false) { return; } Encoding hostsEncoding; var hasConflicting = false; var hostsBuilder = new StringBuilder(); using (var fileStream = new FileStream(hostsPath, FileMode.Open, FileAccess.Read)) { using var streamReader = new StreamReader(fileStream); while (streamReader.EndOfStream == false) { var line = await streamReader.ReadLineAsync(cancellationToken); if (this.IsConflictingLine(line)) { hasConflicting = true; hostsBuilder.AppendLine($"# {line}"); } else { hostsBuilder.AppendLine(line); } } hostsEncoding = streamReader.CurrentEncoding; } if (hasConflicting == true) { try { await File.WriteAllTextAsync(hostsPath, hostsBuilder.ToString(), hostsEncoding, cancellationToken); } catch (Exception ex) { this.logger.LogWarning($"无法解决hosts文件冲突:{ex.Message}"); } } } /// /// 恢复冲突 /// /// /// public Task RestoreAsync(CancellationToken cancellationToken) { return Task.CompletedTask; } /// /// 是否为冲突的行 /// /// /// private bool IsConflictingLine(string? line) { if (line == null || line.TrimStart().StartsWith("#")) { return false; } var items = line.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); if (items.Length < 2) { return false; } var domain = items[1]; return this.fastGithubConfig.IsMatch(domain); } } }