DnscryptProxyHostedService.cs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. using Microsoft.Extensions.Hosting;
  2. using Microsoft.Extensions.Logging;
  3. using System;
  4. using System.Threading;
  5. using System.Threading.Tasks;
  6. namespace FastGithub.DnscryptProxy
  7. {
  8. /// <summary>
  9. /// DnscryptProxy后台服务
  10. /// </summary>
  11. sealed class DnscryptProxyHostedService : IHostedService
  12. {
  13. private readonly DnscryptProxyService dnscryptProxyService;
  14. private readonly ILogger<DnscryptProxyHostedService> logger;
  15. private readonly TimeSpan dnsOKTimeout = TimeSpan.FromSeconds(60d);
  16. /// <summary>
  17. /// DnscryptProxy后台服务
  18. /// </summary>
  19. /// <param name="dnscryptProxyService"></param>
  20. /// <param name="logger"></param>
  21. public DnscryptProxyHostedService(
  22. DnscryptProxyService dnscryptProxyService,
  23. ILogger<DnscryptProxyHostedService> logger)
  24. {
  25. this.dnscryptProxyService = dnscryptProxyService;
  26. this.logger = logger;
  27. }
  28. /// <summary>
  29. /// 启动dnscrypt-proxy
  30. /// </summary>
  31. /// <param name="cancellationToken"></param>
  32. /// <returns></returns>
  33. public async Task StartAsync(CancellationToken cancellationToken)
  34. {
  35. try
  36. {
  37. await this.dnscryptProxyService.StartAsync(cancellationToken);
  38. this.logger.LogInformation($"{this.dnscryptProxyService}启动成功");
  39. // 监听意外退出
  40. var process = this.dnscryptProxyService.Process;
  41. if (process == null)
  42. {
  43. this.OnProcessExit(null, new EventArgs());
  44. }
  45. else
  46. {
  47. process.EnableRaisingEvents = true;
  48. process.Exited += this.OnProcessExit;
  49. await this.WaitForDnsOKAsync(cancellationToken);
  50. }
  51. }
  52. catch (Exception ex)
  53. {
  54. this.logger.LogWarning($"{this.dnscryptProxyService}启动失败:{ex.Message}");
  55. }
  56. }
  57. /// <summary>
  58. /// 等待dns服务初始化
  59. /// </summary>
  60. /// <param name="cancellationToken"></param>
  61. /// <returns></returns>
  62. private async Task WaitForDnsOKAsync(CancellationToken cancellationToken)
  63. {
  64. this.logger.LogInformation($"{this.dnscryptProxyService}正在初始化");
  65. using var timeoutTokenSource = new CancellationTokenSource(this.dnsOKTimeout);
  66. try
  67. {
  68. using var linkeTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutTokenSource.Token);
  69. await this.dnscryptProxyService.WaitForDnsOKAsync(linkeTokenSource.Token);
  70. this.logger.LogInformation($"{this.dnscryptProxyService}初始化完成");
  71. }
  72. catch (Exception)
  73. {
  74. if (timeoutTokenSource.IsCancellationRequested)
  75. {
  76. this.logger.LogWarning($"{this.dnscryptProxyService}在{this.dnsOKTimeout.TotalSeconds}秒内未能初始化完成");
  77. }
  78. }
  79. }
  80. /// <summary>
  81. /// 进程退出时
  82. /// </summary>
  83. /// <param name="sender"></param>
  84. /// <param name="e"></param>
  85. private void OnProcessExit(object? sender, EventArgs e)
  86. {
  87. if (this.dnscryptProxyService.ControllState != ControllState.Stopped)
  88. {
  89. this.logger.LogCritical($"{this.dnscryptProxyService}已意外停止,{nameof(FastGithub)}将无法解析域名。你可以把配置文件的{nameof(FastGithubOptions.PureDns)}修改为其它可用的DNS以临时使用。");
  90. }
  91. }
  92. /// <summary>
  93. /// 停止dnscrypt-proxy
  94. /// </summary>
  95. /// <param name="cancellationToken"></param>
  96. /// <returns></returns>
  97. public Task StopAsync(CancellationToken cancellationToken)
  98. {
  99. try
  100. {
  101. this.dnscryptProxyService.Stop();
  102. this.logger.LogInformation($"{this.dnscryptProxyService}已停止");
  103. }
  104. catch (Exception ex)
  105. {
  106. this.logger.LogWarning($"{this.dnscryptProxyService}停止失败:{ex.Message}");
  107. }
  108. return Task.CompletedTask;
  109. }
  110. }
  111. }