From 11be70d3522fb3c3f8c30e55dfe5f661e1085881 Mon Sep 17 00:00:00 2001 From: ChsBuffer <33744752+chsbuffer@users.noreply.github.com> Date: Sun, 2 Aug 2020 05:58:30 +0800 Subject: [PATCH] =?UTF-8?q?Controller=20=E6=98=93=E7=94=A8=E6=80=A7?= =?UTF-8?q?=E3=80=81=E5=85=BC=E5=AE=B9=E6=80=A7=E6=94=B9=E8=BF=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Netch/Controllers/DNSController.cs | 20 +- .../EncryptedProxy/SSController.cs | 41 +-- .../EncryptedProxy/SSRController.cs | 54 ++-- .../EncryptedProxy/TrojanController.cs | 34 +-- .../EncryptedProxy/VMessController.cs | 36 +-- Netch/Controllers/Interface/Controller.cs | 151 +---------- Netch/Controllers/Interface/Instance.cs | 239 ++++++++++++++++++ Netch/Controllers/Interface/ModeController.cs | 1 + Netch/Controllers/MainController.cs | 8 +- Netch/Controllers/Mode/NFController.cs | 47 ++-- Netch/Controllers/Mode/TUNTAPController.cs | 40 +-- Netch/Controllers/NTTController.cs | 22 +- Netch/Controllers/PrivoxyController.cs | 19 +- Netch/Forms/MainForm.Control.cs | 4 +- Netch/Global.cs | 2 +- Netch/Models/Mode.cs | 14 +- 16 files changed, 333 insertions(+), 399 deletions(-) create mode 100644 Netch/Controllers/Interface/Instance.cs diff --git a/Netch/Controllers/DNSController.cs b/Netch/Controllers/DNSController.cs index 72d7a8ee..0f7b19f7 100644 --- a/Netch/Controllers/DNSController.cs +++ b/Netch/Controllers/DNSController.cs @@ -9,6 +9,7 @@ namespace Netch.Controllers { Name = "DNS Service"; MainFile = "unbound.exe"; + RedirectStd = false; } /// @@ -17,24 +18,7 @@ namespace Netch.Controllers /// public bool Start() { - Instance = GetProcess(); - Instance.StartInfo.Arguments = "-c unbound-service.conf -v"; - - Instance.OutputDataReceived += OnOutputDataReceived; - Instance.ErrorDataReceived += OnOutputDataReceived; - - try - { - Instance.Start(); - Instance.BeginOutputReadLine(); - Instance.BeginErrorReadLine(); - return true; - } - catch (Exception e) - { - Logging.Error("dns-unbound 进程出错:\n" + e); - return false; - } + return StartInstanceAuto("-c unbound-service.conf -v"); } public override void Stop() diff --git a/Netch/Controllers/EncryptedProxy/SSController.cs b/Netch/Controllers/EncryptedProxy/SSController.cs index 794c25a4..7a610e89 100644 --- a/Netch/Controllers/EncryptedProxy/SSController.cs +++ b/Netch/Controllers/EncryptedProxy/SSController.cs @@ -11,14 +11,14 @@ namespace Netch.Controllers { Name = "Shadowsocks"; MainFile = "Shadowsocks.exe"; - StartedKeywords("listening at"); - StoppedKeywords("Invalid config path","usage","plugin service exit unexpectedly"); + StartedKeywords.Add("listening at"); + StoppedKeywords.AddRange(new[] {"Invalid config path", "usage", "plugin service exit unexpectedly"}); } public override bool Start(Server server, Mode mode) { //从DLL启动Shaowsocks - if (Global.Settings.BootShadowsocksFromDLL && (mode.Type == 0 || mode.Type == 1 || mode.Type == 2 || mode.Type == 3)) + if (Global.Settings.BootShadowsocksFromDLL && (mode.Type == 0 || mode.Type == 1 || mode.Type == 2)) { State = State.Starting; var client = Encoding.UTF8.GetBytes($"0.0.0.0:{Global.Settings.Socks5LocalPort}"); @@ -46,38 +46,17 @@ namespace Netch.Controllers return true; } - Instance = GetProcess(); + #region Argument - Instance.StartInfo.Arguments = $"-s {server.Hostname} -p {server.Port} -b {Global.Settings.LocalAddress} -l {Global.Settings.Socks5LocalPort} -m {server.EncryptMethod} -k \"{server.Password}\" -u"; + var argument = new StringBuilder(); + argument.Append($"-s {server.Hostname} -p {server.Port} -b {Global.Settings.LocalAddress} -l {Global.Settings.Socks5LocalPort} -m {server.EncryptMethod} -k \"{server.Password}\" -u"); if (!string.IsNullOrWhiteSpace(server.Plugin) && !string.IsNullOrWhiteSpace(server.PluginOption)) - Instance.StartInfo.Arguments += $" --plugin {server.Plugin} --plugin-opts \"{server.PluginOption}\""; - if (mode.BypassChina) Instance.StartInfo.Arguments += " --acl default.acl"; - Instance.OutputDataReceived += OnOutputDataReceived; - Instance.ErrorDataReceived += OnOutputDataReceived; + argument.Append($" --plugin {server.Plugin} --plugin-opts \"{server.PluginOption}\""); + if (mode.BypassChina) argument.Append(" --acl default.acl"); - State = State.Starting; - Instance.Start(); - Instance.BeginOutputReadLine(); - Instance.BeginErrorReadLine(); + #endregion - for (var i = 0; i < 1000; i++) - { - Thread.Sleep(10); - - if (State == State.Started) return true; - - if (State == State.Stopped) - { - Logging.Error("SS 进程启动失败"); - - Stop(); - return false; - } - } - - Logging.Error("SS 进程启动超时"); - Stop(); - return false; + return StartInstanceAuto(argument.ToString()); } /// diff --git a/Netch/Controllers/EncryptedProxy/SSRController.cs b/Netch/Controllers/EncryptedProxy/SSRController.cs index a93ebf73..b60cac93 100644 --- a/Netch/Controllers/EncryptedProxy/SSRController.cs +++ b/Netch/Controllers/EncryptedProxy/SSRController.cs @@ -1,4 +1,5 @@ -using System.Threading; +using System.Text; +using System.Threading; using Netch.Models; using Netch.Utils; @@ -10,59 +11,34 @@ namespace Netch.Controllers { Name = "ShadowsocksR"; MainFile = "ShadowsocksR.exe"; - StartedKeywords("listening at"); - StoppedKeywords("Invalid config path","usage"); + StartedKeywords.Add("listening at"); + StoppedKeywords.AddRange(new[] {"Invalid config path", "usage"}); } public override bool Start(Server server, Mode mode) { - Instance = GetProcess(); - Instance.OutputDataReceived += OnOutputDataReceived; - Instance.ErrorDataReceived += OnOutputDataReceived; - - Instance.StartInfo.Arguments = $"-s {server.Hostname} -p {server.Port} -k \"{server.Password}\" -m {server.EncryptMethod} -t 120"; + #region Argument + var argument = new StringBuilder(); + argument.Append($"-s {server.Hostname} -p {server.Port} -k \"{server.Password}\" -m {server.EncryptMethod} -t 120"); if (!string.IsNullOrEmpty(server.Protocol)) { - Instance.StartInfo.Arguments += $" -O {server.Protocol}"; - - if (!string.IsNullOrEmpty(server.ProtocolParam)) Instance.StartInfo.Arguments += $" -G \"{server.ProtocolParam}\""; + argument.Append($" -O {server.Protocol}"); + if (!string.IsNullOrEmpty(server.ProtocolParam)) argument.Append($" -G \"{server.ProtocolParam}\""); } if (!string.IsNullOrEmpty(server.OBFS)) { - Instance.StartInfo.Arguments += $" -o {server.OBFS}"; - - if (!string.IsNullOrEmpty(server.OBFSParam)) Instance.StartInfo.Arguments += $" -g \"{server.OBFSParam}\""; + argument.Append($" -o {server.OBFS}"); + if (!string.IsNullOrEmpty(server.OBFSParam)) argument.Append($" -g \"{server.OBFSParam}\""); } - Instance.StartInfo.Arguments += $" -b {Global.Settings.LocalAddress} -l {Global.Settings.Socks5LocalPort} -u"; + argument.Append($" -b {Global.Settings.LocalAddress} -l {Global.Settings.Socks5LocalPort} -u"); + if (mode.BypassChina) argument.Append(" --acl default.acl"); - if (mode.BypassChina) Instance.StartInfo.Arguments += " --acl default.acl"; + #endregion - State = State.Starting; - Instance.Start(); - Instance.BeginOutputReadLine(); - Instance.BeginErrorReadLine(); - - for (var i = 0; i < 1000; i++) - { - Thread.Sleep(10); - - if (State == State.Started) return true; - - if (State == State.Stopped) - { - Logging.Error("SSR 进程启动失败"); - - Stop(); - return false; - } - } - - Logging.Error("SSR 进程启动超时"); - Stop(); - return false; + return StartInstanceAuto(argument.ToString()); } public override void Stop() diff --git a/Netch/Controllers/EncryptedProxy/TrojanController.cs b/Netch/Controllers/EncryptedProxy/TrojanController.cs index 9589884e..4b289b2e 100644 --- a/Netch/Controllers/EncryptedProxy/TrojanController.cs +++ b/Netch/Controllers/EncryptedProxy/TrojanController.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.IO; +using System.Text; using System.Threading; using Netch.Models; using Netch.Utils; @@ -13,13 +14,12 @@ namespace Netch.Controllers { Name = "Trojan"; MainFile = "Trojan.exe"; - StartedKeywords("started"); - StoppedKeywords("exiting"); + StartedKeywords.Add("started"); + StoppedKeywords.Add("exiting"); } public override bool Start(Server server, Mode mode) { - File.WriteAllText("data\\last.json", JsonConvert.SerializeObject(new Trojan { local_addr = Global.Settings.LocalAddress, @@ -32,33 +32,7 @@ namespace Netch.Controllers } })); - Instance = GetProcess(); - Instance.StartInfo.Arguments = "-c ..\\data\\last.json"; - Instance.OutputDataReceived += OnOutputDataReceived; - Instance.ErrorDataReceived += OnOutputDataReceived; - - State = State.Starting; - Instance.Start(); - Instance.BeginOutputReadLine(); - Instance.BeginErrorReadLine(); - for (var i = 0; i < 1000; i++) - { - Thread.Sleep(10); - - if (State == State.Started) return true; - - if (State == State.Stopped) - { - Logging.Error("Trojan 进程启动失败"); - - Stop(); - return false; - } - } - - Logging.Error("Trojan 进程启动超时"); - Stop(); - return false; + return StartInstanceAuto("-c ..\\data\\last.json"); } public override void Stop() diff --git a/Netch/Controllers/EncryptedProxy/VMessController.cs b/Netch/Controllers/EncryptedProxy/VMessController.cs index 12834995..a72f60c5 100644 --- a/Netch/Controllers/EncryptedProxy/VMessController.cs +++ b/Netch/Controllers/EncryptedProxy/VMessController.cs @@ -14,8 +14,8 @@ namespace Netch.Controllers { Name = "V2Ray"; MainFile = "v2ray.exe"; - StartedKeywords("started"); - StoppedKeywords("config file not readable", "failed to"); + StartedKeywords.Add("started"); + StoppedKeywords.AddRange(new[] {"config file not readable", "failed to"}); } public override bool Start(Server server, Mode mode) @@ -168,38 +168,12 @@ namespace Netch.Controllers } })); - Instance = GetProcess(); - Instance.StartInfo.Arguments = "-config ..\\data\\last.json"; - - Instance.OutputDataReceived += OnOutputDataReceived; - Instance.ErrorDataReceived += OnOutputDataReceived; - - State = State.Starting; - Instance.Start(); - Instance.BeginOutputReadLine(); - Instance.BeginErrorReadLine(); - for (var i = 0; i < 1000; i++) + if (StartInstanceAuto("-config ..\\data\\last.json")) { - Thread.Sleep(10); - - if (State == State.Started) - { - if (File.Exists("data\\last.json")) File.Delete("data\\last.json"); - - return true; - } - - if (State == State.Stopped) - { - Logging.Error("V2Ray 进程启动失败"); - - Stop(); - return false; - } + if (File.Exists("data\\last.json")) File.Delete("data\\last.json"); + return true; } - Logging.Error("V2Ray 进程启动超时"); - Stop(); return false; } diff --git a/Netch/Controllers/Interface/Controller.cs b/Netch/Controllers/Interface/Controller.cs index 31468936..8e3b11d7 100644 --- a/Netch/Controllers/Interface/Controller.cs +++ b/Netch/Controllers/Interface/Controller.cs @@ -1,163 +1,22 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Netch.Models; -using Netch.Utils; +using Netch.Models; namespace Netch.Controllers { - public abstract class Controller + public abstract partial class Controller { /// /// 控制器名 /// - public string Name; - - /// - /// 进程实例 - /// - public Process Instance; - - /// - /// 主程序名(不含扩展名) - /// - public string MainFile; - - private List _startedKeywords = new List(); - - private List _stoppedKeywords = new List(); - - protected bool RedirectStd = true; - - protected void StartedKeywords(params string[] texts) - { - foreach (var text in texts) - { - _startedKeywords.Add(text); - } - } - - - protected void StoppedKeywords(params string[] texts) - { - foreach (var text in texts) - { - _stoppedKeywords.Add(text); - } - } - + public string Name { get; protected set; } /// /// 当前状态 /// - protected State State = State.Waiting; - - public abstract void Stop(); + public State State { get; set; } = State.Waiting; /// /// 停止 /// - protected void StopInstance() - { - try - { - if (Instance == null || Instance.HasExited) return; - Instance.Kill(); - Instance.WaitForExit(); - } - catch (Win32Exception e) - { - Logging.Error($"停止 {MainFile} 错误:\n" + e); - } - catch - { - // ignored - } - } - - - public void ClearLog() - { - try - { - if (File.Exists($"logging\\{Name}.log")) File.Delete($"logging\\{Name}.log"); - } - catch (Exception) - { - // ignored - } - } - - /// - /// 写日志 - /// - /// - /// 是否为空 - protected bool Write(string s) - { - if (string.IsNullOrWhiteSpace(s)) return false; - try - { - File.AppendAllText($"logging\\{Name}.log", s + Global.EOF); - } - catch (Exception e) - { - Logging.Error($"写入{Name}日志错误:\n" + e); - } - - return true; - } - - public Process GetProcess() - { - var p = new Process - { - StartInfo = - { - FileName = Path.GetFullPath($"bin\\{MainFile}"), - WorkingDirectory = $"{Global.NetchDir}\\bin", - CreateNoWindow = true, - RedirectStandardError = RedirectStd, - RedirectStandardInput = RedirectStd, - RedirectStandardOutput = RedirectStd, - UseShellExecute = false - }, - EnableRaisingEvents = true - }; - return p; - } - - /// - /// 接收输出数据 - /// - /// 发送者 - /// 数据 - protected void OnOutputDataReceived(object sender, DataReceivedEventArgs e) - { - // 程序结束接收到 null - if (e.Data == null) - { - State = State.Stopped; - return; - } - - var str = Encoding.UTF8.GetString(Encoding.GetEncoding("gbk").GetBytes(e.Data ?? string.Empty)); - // 写入日志 - Task.Run(() => Write(str)); - - // 检查启动 - if (State == State.Starting) - { - if (_startedKeywords.Any(s => str.Contains(s))) - State = State.Started; - else if (_stoppedKeywords.Any(s => str.Contains(s))) - State = State.Stopped; - } - } + public abstract void Stop(); } } \ No newline at end of file diff --git a/Netch/Controllers/Interface/Instance.cs b/Netch/Controllers/Interface/Instance.cs new file mode 100644 index 00000000..d264b081 --- /dev/null +++ b/Netch/Controllers/Interface/Instance.cs @@ -0,0 +1,239 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Timers; +using Netch.Models; +using Netch.Utils; + +namespace Netch.Controllers +{ + abstract partial class Controller + { + /// + /// 主程序名 + /// + public string MainFile { get; protected set; } + + /// + /// 成功启动关键词 + /// + protected readonly List StartedKeywords = new List(); + + /// + /// 启动失败关键词 + /// + protected readonly List StoppedKeywords = new List(); + + /// + /// 进程是否可以重定向输出 + /// + protected bool RedirectStd { get; set; } = true; + + /// + /// 进程实例 + /// + public Process Instance { get; private set; } + + /// + /// 日志文件(重定向输出文件) + /// + private string _logPath; + + private FileStream _logFileStream; + + /// + /// 程序输出的编码, + /// 调用于基类的 + /// + protected string InstanceOutputEncoding { get; set; } = "gbk"; + + /// + /// 停止进程 + /// + protected void StopInstance() + { + try + { + if (Instance == null || Instance.HasExited) return; + Instance.Kill(); + Instance.WaitForExit(); + } + catch (Win32Exception e) + { + Logging.Error($"停止 {MainFile} 错误:\n" + e); + } + catch + { + // ignored + } + } + + /// + /// 仅初始化 ,不设定事件处理方法 + /// + /// + protected void InitInstance(string argument) + { + Instance = new Process + { + StartInfo = + { + FileName = Path.GetFullPath($"bin\\{MainFile}"), + WorkingDirectory = $"{Global.NetchDir}\\bin", + Arguments = argument, + CreateNoWindow = true, + RedirectStandardError = RedirectStd, + RedirectStandardInput = RedirectStd, + RedirectStandardOutput = RedirectStd, + UseShellExecute = !RedirectStd, + WindowStyle = ProcessWindowStyle.Hidden + }, + EnableRaisingEvents = true + }; + } + + + /// + /// 默认行为启动主程序 + /// + /// 主程序启动参数 + /// 进程优先级 + /// 是否成功启动 + protected bool StartInstanceAuto(string argument, ProcessPriorityClass priority = ProcessPriorityClass.Normal) + { + State = State.Starting; + try + { + // 初始化程序 + InitInstance(argument); + if (RedirectStd) + { + // 清理日志 + _logPath ??= Path.Combine(Global.NetchDir, $"logging\\{Name}.log"); + if (_logFileStream == null && File.Exists(_logPath)) + File.Delete(_logPath); + _logFileStream = new FileStream(_logPath, FileMode.Create, FileAccess.Write); + + Instance.OutputDataReceived += OnOutputDataReceived; + Instance.ErrorDataReceived += OnOutputDataReceived; + } + + Instance.Exited += OnExited; + + // 启动程序 + Instance.Start(); + Instance.PriorityClass = priority; + if (!RedirectStd || StartedKeywords.Count == 0) return true; + // 启动日志重定向 + Instance.BeginOutputReadLine(); + Instance.BeginErrorReadLine(); + _writeStreamTimer = new System.Timers.Timer(300); + _writeStreamTimer.Elapsed += SaveStreamTimerEvent; + _writeStreamTimer.AutoReset = true; + _writeStreamTimer.Enabled = true; + // 等待启动 + for (var i = 0; i < 1000; i++) + { + Thread.Sleep(10); + switch (State) + { + case State.Started: + return true; + case State.Stopped: + Logging.Error($"{Name} 控制器启动失败"); + Stop(); + return false; + } + } + + Logging.Error($"{Name} 控制器启动超时"); + Stop(); + return false; + } + catch (Exception e) + { + Logging.Error($"{Name} 控制器启动失败:\n {e}"); + return false; + } + } + + private static System.Timers.Timer _writeStreamTimer; + + private void OnExited(object sender, EventArgs e) + { + State = State.Stopped; + if (!RedirectStd) return; + Thread.Sleep(500); // 等待 SaveStreamTimerEvent 写入日志 + _logFileStream.Close(); + _logFileStream = null; + } + + /// + /// 接收输出数据 + /// + /// 发送者 + /// 数据 + protected async void OnOutputDataReceived(object sender, DataReceivedEventArgs e) + { + // 程序结束, 接收到 null + if (e.Data == null) + return; + + var info = Encoding.GetEncoding(InstanceOutputEncoding).GetBytes(e.Data + Global.EOF); + await Write(info); + var str = Encoding.UTF8.GetString(info); + // 检查启动 + if (State == State.Starting) + { + if (StartedKeywords.Any(s => str.Contains(s))) + State = State.Started; + else if (StoppedKeywords.Any(s => str.Contains(s))) + State = State.Stopped; + } + } + + /// + /// 计时器存储日志 + /// + /// + /// + private async void SaveStreamTimerEvent(object sender, EventArgs e) + { + if (_logFileStream == null) return; + try + { + await _logFileStream.FlushAsync(); + } + catch + { + // ignored + } + } + + /// + /// 写入日志文件流 + /// + /// + /// 转码后的字符串 + private async Task Write(byte[] info) + { + if (info == null) + return; + + try + { + await _logFileStream.WriteAsync(info, 0, info.Length); + } + catch (Exception e) + { + Logging.Error($"写入 {Name} 日志错误:\n" + e.Message); + } + } + } +} \ No newline at end of file diff --git a/Netch/Controllers/Interface/ModeController.cs b/Netch/Controllers/Interface/ModeController.cs index 696320af..8dd5e632 100644 --- a/Netch/Controllers/Interface/ModeController.cs +++ b/Netch/Controllers/Interface/ModeController.cs @@ -1,3 +1,4 @@ +using System.Threading.Tasks; using Netch.Models; namespace Netch.Controllers diff --git a/Netch/Controllers/MainController.cs b/Netch/Controllers/MainController.cs index 22252295..1367d6ec 100644 --- a/Netch/Controllers/MainController.cs +++ b/Netch/Controllers/MainController.cs @@ -41,7 +41,7 @@ namespace Netch.Controllers Logging.Info($"启动主控制器: {server.Type} [{mode.Type}]{mode.Remark}"); FlushDNSResolverCache(); - var result = false; + bool result; if (server.Type == "Socks5") { result = mode.Type != 4; @@ -86,7 +86,6 @@ namespace Netch.Controllers } Global.MainForm.StatusText(i18N.Translate("Starting ", pEncryptedProxyController.Name)); - pEncryptedProxyController.ClearLog(); result = pEncryptedProxyController.Start(server, mode); } @@ -113,7 +112,6 @@ namespace Netch.Controllers if (pModeController != null) { Global.MainForm.StatusText(i18N.Translate("Starting ", pModeController.Name)); - pModeController.ClearLog(); result = pModeController.Start(server, mode); } @@ -142,7 +140,7 @@ namespace Netch.Controllers { Logging.Error("主控制器启动失败"); Stop(); - } + } return result; } @@ -172,7 +170,7 @@ namespace Netch.Controllers } catch (Win32Exception e) { - Logging.Error($"结束进程 {name} 错误:\n" + e); + Logging.Error($"结束进程 {name} 错误:" + e.Message); } catch (Exception) { diff --git a/Netch/Controllers/Mode/NFController.cs b/Netch/Controllers/Mode/NFController.cs index 56663cd1..9c2dbcdd 100644 --- a/Netch/Controllers/Mode/NFController.cs +++ b/Netch/Controllers/Mode/NFController.cs @@ -2,6 +2,7 @@ using System.Diagnostics; using System.IO; using System.ServiceProcess; +using System.Text; using System.Threading; using System.Threading.Tasks; using Netch.Models; @@ -45,8 +46,8 @@ namespace Netch.Controllers { Name = "Redirector"; MainFile = "Redirector.exe"; - StartedKeywords("Started"); - StoppedKeywords("Failed", "Unable"); + StartedKeywords.Add("Started"); + StoppedKeywords.AddRange(new[] {"Failed", "Unable"}); } public override bool Start(Server server, Mode mode) @@ -70,10 +71,10 @@ namespace Netch.Controllers processList += proc + ","; processList += "NTT.exe"; - Instance = GetProcess(); + var argument = new StringBuilder(); if (server.Type != "Socks5") { - Instance.StartInfo.Arguments += $"-r 127.0.0.1:{Global.Settings.Socks5LocalPort} -p \"{processList}\""; + argument.Append($"-r 127.0.0.1:{Global.Settings.Socks5LocalPort} -p \"{processList}\""); } else @@ -85,42 +86,26 @@ namespace Netch.Controllers return false; } - Instance.StartInfo.Arguments += $"-r {result}:{server.Port} -p \"{processList}\""; - if (!string.IsNullOrWhiteSpace(server.Username) && !string.IsNullOrWhiteSpace(server.Password)) Instance.StartInfo.Arguments += $" -username \"{server.Username}\" -password \"{server.Password}\""; + argument.Append($"-r {result}:{server.Port} -p \"{processList}\""); + if (!string.IsNullOrWhiteSpace(server.Username) && !string.IsNullOrWhiteSpace(server.Password)) + argument.Append($" -username \"{server.Username}\" -password \"{server.Password}\""); } - Instance.StartInfo.Arguments += $" -t {Global.Settings.RedirectorTCPPort}"; - Instance.OutputDataReceived += OnOutputDataReceived; - Instance.ErrorDataReceived += OnOutputDataReceived; + argument.Append($" -t {Global.Settings.RedirectorTCPPort}"); for (var i = 0; i < 2; i++) { State = State.Starting; - Instance.Start(); - Instance.BeginOutputReadLine(); - Instance.BeginErrorReadLine(); - - for (var j = 0; j < 40; j++) + if (!StartInstanceAuto(argument.ToString())) continue; + if (Global.Settings.ModifySystemDNS) { - Thread.Sleep(250); - - if (State == State.Started) - { - if (Global.Settings.ModifySystemDNS) - { - //备份并替换系统DNS - _sysDns = DNS.getSystemDns(); - string[] dns = {"1.1.1.1", "8.8.8.8"}; - DNS.SetDNS(dns); - } - - return true; - } + //备份并替换系统DNS + _sysDns = DNS.getSystemDns(); + string[] dns = {"1.1.1.1", "8.8.8.8"}; + DNS.SetDNS(dns); } - Logging.Error(Name + " 启动超时"); - Stop(); - if (!RestartService()) return false; + return true; } return false; diff --git a/Netch/Controllers/Mode/TUNTAPController.cs b/Netch/Controllers/Mode/TUNTAPController.cs index a8ec092a..2c6faeea 100644 --- a/Netch/Controllers/Mode/TUNTAPController.cs +++ b/Netch/Controllers/Mode/TUNTAPController.cs @@ -35,10 +35,10 @@ namespace Netch.Controllers public TUNTAPController() { - Name = "Tap"; + Name = "tun2socks"; MainFile = "tun2socks.exe"; - StartedKeywords("Running"); - StoppedKeywords("failed", "invalid vconfig file"); + StartedKeywords.Add("Running"); + StoppedKeywords.AddRange(new[] {"failed", "invalid vconfig file"}); } /// @@ -190,8 +190,6 @@ namespace Netch.Controllers public override bool Start(Server server, Mode mode) { - Global.MainForm.StatusText(i18N.Translate("Starting Tap")); - _savedMode = mode; _savedServer = server; @@ -199,8 +197,6 @@ namespace Netch.Controllers SetupRouteTable(); - Instance = GetProcess(); - var adapterName = TUNTAP.GetName(Global.TUNTAP.ComponentID); string dns; @@ -226,35 +222,17 @@ namespace Netch.Controllers if (Global.Settings.TUNTAP.UseFakeDNS) dns += " -fakeDns"; + var argument = new StringBuilder(); if (server.Type == "Socks5") - Instance.StartInfo.Arguments = $"-proxyServer {server.Hostname}:{server.Port} -tunAddr {Global.Settings.TUNTAP.Address} -tunMask {Global.Settings.TUNTAP.Netmask} -tunGw {Global.Settings.TUNTAP.Gateway} -tunDns {dns} -tunName \"{adapterName}\""; + argument.Append($"-proxyServer {server.Hostname}:{server.Port} "); else - Instance.StartInfo.Arguments = $"-proxyServer 127.0.0.1:{Global.Settings.Socks5LocalPort} -tunAddr {Global.Settings.TUNTAP.Address} -tunMask {Global.Settings.TUNTAP.Netmask} -tunGw {Global.Settings.TUNTAP.Gateway} -tunDns {dns} -tunName \"{adapterName}\""; + argument.Append($"-proxyServer 127.0.0.1:{Global.Settings.Socks5LocalPort} "); - Instance.ErrorDataReceived += OnOutputDataReceived; - Instance.OutputDataReceived += OnOutputDataReceived; + argument.Append($"-tunAddr {Global.Settings.TUNTAP.Address} -tunMask {Global.Settings.TUNTAP.Netmask} -tunGw {Global.Settings.TUNTAP.Gateway} -tunDns {dns} -tunName \"{adapterName}\""); State = State.Starting; - Instance.Start(); - Instance.BeginErrorReadLine(); - Instance.BeginOutputReadLine(); - Instance.PriorityClass = ProcessPriorityClass.RealTime; - - for (var i = 0; i < 1000; i++) - { - Thread.Sleep(10); - - switch (State) - { - case State.Started: - return true; - case State.Stopped: - Stop(); - return false; - } - } - - return false; + if (!StartInstanceAuto(argument.ToString(), ProcessPriorityClass.RealTime)) return false; + return true; } /// diff --git a/Netch/Controllers/NTTController.cs b/Netch/Controllers/NTTController.cs index 4389e7e3..59baac62 100644 --- a/Netch/Controllers/NTTController.cs +++ b/Netch/Controllers/NTTController.cs @@ -1,7 +1,6 @@ using System; using System.ComponentModel; using System.Diagnostics; -using Netch.Models; using Netch.Utils; namespace Netch.Controllers @@ -24,14 +23,9 @@ namespace Netch.Controllers { try { - Instance = GetProcess(); - - Instance.StartInfo.Arguments = $" {Global.Settings.STUN_Server} {Global.Settings.STUN_Server_Port}"; - + InitInstance($" {Global.Settings.STUN_Server} {Global.Settings.STUN_Server_Port}"); Instance.OutputDataReceived += OnOutputDataReceived; Instance.ErrorDataReceived += OnOutputDataReceived; - - State = State.Starting; Instance.Start(); Instance.BeginOutputReadLine(); Instance.BeginErrorReadLine(); @@ -44,10 +38,18 @@ namespace Netch.Controllers return (true, natType, localEnd, publicEnd); } - catch (Win32Exception e) + catch (Exception e) { - Logging.Error("NTT 进程出错\n" + e); - Stop(); + Logging.Error($"{Name} 控制器出错:\n" + e); + try + { + Stop(); + } + catch + { + // ignored + } + return (false, null, null, null); } } diff --git a/Netch/Controllers/PrivoxyController.cs b/Netch/Controllers/PrivoxyController.cs index dde33995..7f6ecf84 100644 --- a/Netch/Controllers/PrivoxyController.cs +++ b/Netch/Controllers/PrivoxyController.cs @@ -1,6 +1,4 @@ -using System; -using System.Diagnostics; -using System.IO; +using System.IO; using Netch.Models; namespace Netch.Controllers @@ -26,20 +24,7 @@ namespace Netch.Controllers text = text.Replace("/ 127.0.0.1", $"/ {server.Hostname}"); File.WriteAllText("data\\privoxy.conf", text); - Instance = GetProcess(); - Instance.StartInfo.Arguments = "..\\data\\privoxy.conf"; - Instance.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; - Instance.StartInfo.UseShellExecute = true; - try - { - Instance.Start(); - } - catch (Exception) - { - return false; - } - - return true; + return StartInstanceAuto("..\\data\\privoxy.conf"); } public override void Stop() diff --git a/Netch/Forms/MainForm.Control.cs b/Netch/Forms/MainForm.Control.cs index 21545582..83dd68df 100644 --- a/Netch/Forms/MainForm.Control.cs +++ b/Netch/Forms/MainForm.Control.cs @@ -116,14 +116,14 @@ namespace Netch.Forms } else { + State = State.Stopping; Task.Run(() => { // 停止 - State = State.Stopping; _mainController.Stop(); State = State.Stopped; + Task.Run(TestServer); }); - Task.Run(TestServer); } } diff --git a/Netch/Global.cs b/Netch/Global.cs index 59029627..feaf4336 100644 --- a/Netch/Global.cs +++ b/Netch/Global.cs @@ -13,7 +13,7 @@ namespace Netch /// public const string EOF = "\r\n"; - public static readonly string NetchDir = (AppDomain.CurrentDomain.BaseDirectory).TrimEnd(); + public static readonly string NetchDir = AppDomain.CurrentDomain.BaseDirectory.TrimEnd(); /// /// 主窗体的静态实例 diff --git a/Netch/Models/Mode.cs b/Netch/Models/Mode.cs index 4100f794..42ed1d09 100644 --- a/Netch/Models/Mode.cs +++ b/Netch/Models/Mode.cs @@ -16,13 +16,13 @@ namespace Netch.Models public string FileName; /// - /// 类型 - /// 0. 进程加速 - /// 1. TUN/TAP 规则内 IP CIDR 加速 - /// 2. TUN/TAP 全局,绕过规则内 IP CIDR - /// 3. HTTP 代理(自动设置到系统代理) - /// 4. Socks5 代理(不自动设置到系统代理) - /// 5. Socks5 + HTTP 代理(不自动设置到系统代理) + /// 类型 + /// 0. 进程加速 + /// 1. TUN/TAP 规则内 IP CIDR 加速 + /// 2. TUN/TAP 全局,绕过规则内 IP CIDR + /// 3. HTTP 代理(自动设置到系统代理) + /// 4. Socks5 代理(不自动设置到系统代理) + /// 5. Socks5 + HTTP 代理(不自动设置到系统代理) /// public int Type = 0;