DnscryptProxy.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. using FastGithub.Configuration;
  2. using System;
  3. using System.Diagnostics;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Net;
  7. using System.Threading;
  8. using System.Threading.Tasks;
  9. namespace FastGithub.DomainResolve
  10. {
  11. /// <summary>
  12. /// DnscryptProxy服务
  13. /// </summary>
  14. sealed class DnscryptProxy
  15. {
  16. private const string PATH = "dnscryptproxy";
  17. private const string NAME = "dnscrypt-proxy";
  18. /// <summary>
  19. /// 相关进程
  20. /// </summary>
  21. private Process? process;
  22. /// <summary>
  23. /// 获取监听的节点
  24. /// </summary>
  25. public IPEndPoint? LocalEndPoint { get; private set; }
  26. /// <summary>
  27. /// 启动dnscrypt-proxy
  28. /// </summary>
  29. /// <param name="cancellationToken"></param>
  30. /// <returns></returns>
  31. public async Task StartAsync(CancellationToken cancellationToken)
  32. {
  33. var tomlPath = Path.Combine(PATH, $"{NAME}.toml");
  34. var port = LocalMachine.GetAvailablePort(IPAddress.Loopback.AddressFamily, min: 5533);
  35. var localEndPoint = new IPEndPoint(IPAddress.Loopback, port);
  36. await TomlUtil.SetListensAsync(tomlPath, localEndPoint, cancellationToken);
  37. foreach (var process in Process.GetProcessesByName(NAME))
  38. {
  39. process.Kill();
  40. process.WaitForExit();
  41. }
  42. if (OperatingSystem.IsWindows())
  43. {
  44. StartDnscryptProxy("-service uninstall")?.WaitForExit();
  45. StartDnscryptProxy("-service install")?.WaitForExit();
  46. StartDnscryptProxy("-service start")?.WaitForExit();
  47. this.process = Process.GetProcessesByName(NAME).FirstOrDefault(item => item.SessionId == 0);
  48. }
  49. else
  50. {
  51. this.process = StartDnscryptProxy(string.Empty);
  52. }
  53. if (this.process != null)
  54. {
  55. this.LocalEndPoint = localEndPoint;
  56. this.process.EnableRaisingEvents = true;
  57. this.process.Exited += Process_Exited;
  58. }
  59. }
  60. /// <summary>
  61. /// 进程退出时
  62. /// </summary>
  63. /// <param name="sender"></param>
  64. /// <param name="e"></param>
  65. private void Process_Exited(object? sender, EventArgs e)
  66. {
  67. this.LocalEndPoint = null;
  68. }
  69. /// <summary>
  70. /// 停止dnscrypt-proxy
  71. /// </summary>
  72. public void Stop()
  73. {
  74. if (OperatingSystem.IsWindows())
  75. {
  76. StartDnscryptProxy("-service stop")?.WaitForExit();
  77. StartDnscryptProxy("-service uninstall")?.WaitForExit();
  78. }
  79. if (this.process != null && this.process.HasExited == false)
  80. {
  81. this.process.Kill();
  82. }
  83. this.LocalEndPoint = null;
  84. }
  85. /// <summary>
  86. /// 启动DnscryptProxy进程
  87. /// </summary>
  88. /// <param name="arguments"></param>
  89. private static Process? StartDnscryptProxy(string arguments)
  90. {
  91. var fileName = OperatingSystem.IsWindows() ? $"{NAME}.exe" : NAME;
  92. return Process.Start(new ProcessStartInfo
  93. {
  94. FileName = Path.Combine(PATH, fileName),
  95. Arguments = arguments,
  96. WorkingDirectory = PATH,
  97. UseShellExecute = false,
  98. CreateNoWindow = true,
  99. WindowStyle = ProcessWindowStyle.Hidden
  100. });
  101. }
  102. /// <summary>
  103. /// 转换为字符串
  104. /// </summary>
  105. /// <returns></returns>
  106. public override string ToString()
  107. {
  108. return NAME;
  109. }
  110. }
  111. }