diff --git a/Netch/Controllers/DNSController.cs b/Netch/Controllers/DNSController.cs index 03125753..53e3f40a 100644 --- a/Netch/Controllers/DNSController.cs +++ b/Netch/Controllers/DNSController.cs @@ -1,4 +1,5 @@ -using System.IO; +using System; +using System.IO; using System.Runtime.InteropServices; using System.Text; @@ -8,11 +9,16 @@ namespace Netch.Controllers { public string Name { get; } = "DNS Service"; + public void Stop() + { + aiodns_free(); + } + /// /// 启动DNS服务 /// /// - public bool Start() + public void Start() { aiodns_dial((int) NameList.TYPE_REST, null); aiodns_dial((int) NameList.TYPE_ADDR, Encoding.UTF8.GetBytes($"{Global.Settings.LocalAddress}:53")); @@ -21,12 +27,8 @@ namespace Netch.Controllers aiodns_dial((int) NameList.TYPE_ODNS, Encoding.UTF8.GetBytes($"{Global.Settings.AioDNS.OtherDNS}:53")); aiodns_dial((int) NameList.TYPE_METH, Encoding.UTF8.GetBytes(Global.Settings.AioDNS.Protocol)); - return aiodns_init(); - } - - public void Stop() - { - aiodns_free(); + if (aiodns_init()) + throw new Exception("AioDNS start failed"); } #region NativeMethods @@ -40,7 +42,7 @@ namespace Netch.Controllers [DllImport("aiodns.bin", CallingConvention = CallingConvention.Cdecl)] public static extern void aiodns_free(); - enum NameList : int + private enum NameList { TYPE_REST, TYPE_ADDR, diff --git a/Netch/Controllers/Guard.cs b/Netch/Controllers/Guard.cs index 71f23ac4..bae37183 100644 --- a/Netch/Controllers/Guard.cs +++ b/Netch/Controllers/Guard.cs @@ -14,6 +14,24 @@ namespace Netch.Controllers { public abstract class Guard { + private static readonly Timer SaveBufferTimer = new(300) {AutoReset = true}; + + private readonly StringBuilder _logBuffer = new(); + + /// + /// 成功启动关键词 + /// + protected readonly List StartedKeywords = new(); + + /// + /// 启动失败关键词 + /// + protected readonly List StoppedKeywords = new(); + + /// + /// 日志文件(重定向输出文件) + /// + private string _logPath; public virtual string Name { get; } /// @@ -23,18 +41,6 @@ namespace Netch.Controllers protected State State { get; set; } = State.Waiting; - public abstract void Stop(); - - /// - /// 成功启动关键词 - /// - protected readonly List StartedKeywords = new List(); - - /// - /// 启动失败关键词 - /// - protected readonly List StoppedKeywords = new List(); - /// /// 进程是否可以重定向输出 /// @@ -45,19 +51,14 @@ namespace Netch.Controllers /// public Process Instance { get; private set; } - /// - /// 日志文件(重定向输出文件) - /// - private string _logPath; - - private readonly StringBuilder _logBuffer = new StringBuilder(); - /// /// 程序输出的编码, - /// 调用于基类的 + /// 调用于基类的 /// protected Encoding InstanceOutputEncoding { get; set; } = Encoding.GetEncoding("gbk"); + public abstract void Stop(); + /// /// 停止进程 /// @@ -80,7 +81,7 @@ namespace Netch.Controllers } /// - /// 仅初始化 ,不设定事件处理方法 + /// 仅初始化 ,不设定事件处理方法 /// /// protected virtual void InitInstance(string argument) @@ -109,72 +110,59 @@ namespace Netch.Controllers /// 主程序启动参数 /// 进程优先级 /// 是否成功启动 - protected bool StartInstanceAuto(string argument, ProcessPriorityClass priority = ProcessPriorityClass.Normal) + protected void StartInstanceAuto(string argument, ProcessPriorityClass priority = ProcessPriorityClass.Normal) { State = State.Starting; - try + // 初始化程序 + InitInstance(argument); + Instance.EnableRaisingEvents = true; + if (RedirectStd) { - // 初始化程序 - InitInstance(argument); - Instance.EnableRaisingEvents = true; - if (RedirectStd) - { - // 清理日志 - _logPath ??= Path.Combine(Global.NetchDir, $"logging\\{Name}.log"); - if (File.Exists(_logPath)) - File.Delete(_logPath); + // 清理日志 + _logPath ??= Path.Combine(Global.NetchDir, $"logging\\{Name}.log"); + if (File.Exists(_logPath)) + File.Delete(_logPath); - Instance.OutputDataReceived += OnOutputDataReceived; - Instance.ErrorDataReceived += OnOutputDataReceived; - } - - Instance.Exited += OnExited; - - // 启动程序 - Instance.Start(); - if (priority != ProcessPriorityClass.Normal) - Instance.PriorityClass = priority; - if (!RedirectStd) return true; - // 启动日志重定向 - Instance.BeginOutputReadLine(); - Instance.BeginErrorReadLine(); - SaveBufferTimer.Elapsed += SaveBufferTimerEvent; - SaveBufferTimer.Enabled = true; - if (StartedKeywords.Count == 0) return 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; + Instance.OutputDataReceived += OnOutputDataReceived; + Instance.ErrorDataReceived += OnOutputDataReceived; } - catch (Exception e) + + Instance.Exited += OnExited; + + // 启动程序 + Instance.Start(); + if (priority != ProcessPriorityClass.Normal) + Instance.PriorityClass = priority; + if (!RedirectStd) return; + // 启动日志重定向 + Instance.BeginOutputReadLine(); + Instance.BeginErrorReadLine(); + SaveBufferTimer.Elapsed += SaveBufferTimerEvent; + SaveBufferTimer.Enabled = true; + if (StartedKeywords.Count == 0) return; + // 等待启动 + for (var i = 0; i < 1000; i++) { - Logging.Error($"{Name} 控制器启动失败:\n {e}"); - return false; + Thread.Sleep(10); + switch (State) + { + case State.Started: + return; + case State.Stopped: + Stop(); + Utils.Utils.Open(_logPath); + throw new Exception($"{Name} 控制器启动失败"); + } } + + Stop(); + throw new Exception($"{Name} 控制器启动超时"); } - private static readonly Timer SaveBufferTimer = new Timer(300) {AutoReset = true}; - private void OnExited(object sender, EventArgs e) { if (RedirectStd) - { SaveBufferTimer.Enabled = false; - } SaveBufferTimerEvent(null, null); @@ -204,7 +192,7 @@ namespace Netch.Controllers } /// - /// 计时器存储日志 + /// 计时器存储日志 /// /// /// diff --git a/Netch/Controllers/HTTPController.cs b/Netch/Controllers/HTTPController.cs index 676ba190..36a9283e 100644 --- a/Netch/Controllers/HTTPController.cs +++ b/Netch/Controllers/HTTPController.cs @@ -1,10 +1,7 @@ using System; -using System.Diagnostics; using System.Threading.Tasks; -using System.Windows.Forms; using WindowsProxy; using Microsoft.Win32; -using Netch.Forms; using Netch.Models; using Netch.Servers.Socks5; using Netch.Servers.Trojan; @@ -27,42 +24,30 @@ namespace Netch.Controllers /// /// 模式 /// 是否启动成功 - public bool Start(in Mode mode) + public void Start(in Mode mode) { RecordPrevious(); - try - { - if (pPrivoxyController.Start(MainController.Server, mode)) - Global.Job.AddProcess(pPrivoxyController.Instance); + pPrivoxyController.Start(MainController.Server); + Global.Job.AddProcess(pPrivoxyController.Instance); - if (mode.Type == 3) + if (mode.Type == 3) + { + if (MainController.Server is Socks5 or Trojan && mode.BypassChina) { - if (MainController.Server is Socks5 or Trojan && mode.BypassChina) + //启动PAC服务器 + PACServerHandle.InitPACServer("127.0.0.1"); + } + else + { + using var service = new ProxyService { - //启动PAC服务器 - PACServerHandle.InitPACServer("127.0.0.1"); - } - else - { - using var service = new ProxyService - { - Server = $"127.0.0.1:{Global.Settings.HTTPLocalPort}", - Bypass = string.Join(";", ProxyService.LanIp) - }; - service.Global(); - } + Server = $"127.0.0.1:{Global.Settings.HTTPLocalPort}", + Bypass = string.Join(";", ProxyService.LanIp) + }; + service.Global(); } } - catch (Exception e) - { - if (MessageBoxX.Show(i18N.Translate("Failed to set the system proxy, it may be caused by the lack of dependent programs. Do you want to jump to Netch's official website to download dependent programs?"), confirm: true) == DialogResult.OK) Process.Start("https://netch.org/#/?id=%e4%be%9d%e8%b5%96"); - - Logging.Error("设置系统代理失败" + e); - return false; - } - - return true; } /// diff --git a/Netch/Controllers/IModeController.cs b/Netch/Controllers/IModeController.cs index 5fc5e2e0..3760597b 100644 --- a/Netch/Controllers/IModeController.cs +++ b/Netch/Controllers/IModeController.cs @@ -9,6 +9,6 @@ namespace Netch.Controllers /// /// 模式 /// 是否成功 - public abstract bool Start(in Mode mode); + public abstract void Start(in Mode mode); } } \ No newline at end of file diff --git a/Netch/Controllers/IServerController.cs b/Netch/Controllers/IServerController.cs index 62dceee2..8b135026 100644 --- a/Netch/Controllers/IServerController.cs +++ b/Netch/Controllers/IServerController.cs @@ -14,7 +14,7 @@ namespace Netch.Controllers /// 服务器 /// 模式 /// 是否启动成功 - public abstract bool Start(in Server s, in Mode mode); + public abstract void Start(in Server s, in Mode mode); } public static class ServerControllerExtension diff --git a/Netch/Controllers/MainController.cs b/Netch/Controllers/MainController.cs index 930086b8..0b1c1458 100644 --- a/Netch/Controllers/MainController.cs +++ b/Netch/Controllers/MainController.cs @@ -3,11 +3,9 @@ using System.IO; using System.Net; using System.Threading; using System.Threading.Tasks; -using Netch.Forms; using Netch.Models; using Netch.Servers.Socks5; using Netch.Utils; -using static Netch.Forms.MainForm; using static Netch.Utils.PortHelper; namespace Netch.Controllers @@ -51,14 +49,15 @@ namespace Netch.Controllers /// 服务器 /// 模式 /// 是否启动成功 - public static async Task Start(Server server, Mode mode) + /// + public static async Task Start(Server server, Mode mode) { Logging.Info($"启动主控制器: {server.Type} [{mode.Type}]{mode.Remark}"); Server = server; Mode = mode; if (server is Socks5 && mode.Type == 4) - return false; + throw new MessageException("Already Socks5 Server"); // 刷新DNS缓存 NativeMethods.FlushDNSResolverCache(); @@ -69,15 +68,11 @@ namespace Netch.Controllers } catch (Exception) { - MessageBoxX.Show("No internet connection"); - return false; + throw new MessageException(i18N.Translate("No internet connection")); } if (Global.Settings.ResolveServerHostname && DNS.Lookup(server.Hostname) == null) - { - MessageBoxX.Show("Lookup Server hostname failed"); - return false; - } + throw new MessageException(i18N.Translate("Lookup Server hostname failed")); // 添加Netch到防火墙 _ = Task.Run(Firewall.AddNetchFwRules); @@ -86,32 +81,15 @@ namespace Netch.Controllers { if (!ModeHelper.SkipServerController(server, mode)) { - if (!await Task.Run(() => StartServer(server, mode, ref _serverController))) - throw new StartFailedException(); + await Task.Run(() => StartServer(server, mode, out _serverController)); StatusPortInfoText.UpdateShareLan(); } - if (!await StartMode(mode)) - throw new StartFailedException(); - - return true; + await Task.Run(() => StartMode(mode)); } catch (Exception e) { - switch (e) - { - case DllNotFoundException _: - case FileNotFoundException _: - MessageBoxX.Show(e.Message + "\n\n" + i18N.Translate("Missing File or runtime components"), owner: Global.MainForm); - break; - case StartFailedException _: - break; - default: - Logging.Error($"主控制器未处理异常: {e}"); - break; - } - try { await Stop(); @@ -121,69 +99,66 @@ namespace Netch.Controllers // ignored } - return false; + switch (e) + { + case DllNotFoundException: + case FileNotFoundException: + throw new Exception(e.Message + "\n\n" + i18N.Translate("Missing File or runtime components")); + case MessageException: + throw; + default: + Logging.Error(e.ToString()); + Utils.Utils.Open(Logging.LogFile); + throw new MessageException($"未处理异常\n{e.Message}"); + } } } - private static bool StartServer(Server server, Mode mode, ref IServerController controller) + private static void StartServer(Server server, Mode mode, out IServerController controller) { controller = ServerHelper.GetUtilByTypeName(server.Type).GetController(); if (controller is Guard instanceController) Utils.Utils.KillProcessByName(instanceController.MainFile); - if (!PortCheckAndShowMessageBox(controller.Socks5LocalPort(), "Socks5")) - return false; + PortCheck(controller.Socks5LocalPort(), "Socks5"); Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", controller.Name)); - if (controller.Start(in server, mode)) + + controller.Start(in server, mode); + if (controller is Guard {Instance: { }} guard) + Task.Run(() => + { + Thread.Sleep(1000); + Global.Job.AddProcess(guard.Instance); + }); + + if (server is Socks5 socks5) { - if (controller is Guard guard) - if (guard.Instance != null) - Task.Run(() => - { - Thread.Sleep(1000); - Global.Job.AddProcess(guard.Instance); - }); - - if (server is Socks5 socks5) - { - if (socks5.Auth()) - StatusPortInfoText.Socks5Port = controller.Socks5LocalPort(); - } - else - { + if (socks5.Auth()) StatusPortInfoText.Socks5Port = controller.Socks5LocalPort(); - } - - return true; } - - return false; + else + { + StatusPortInfoText.Socks5Port = controller.Socks5LocalPort(); + } } - private static async Task StartMode(Mode mode) + private static void StartMode(Mode mode) { ModeController = ModeHelper.GetModeControllerByType(mode.Type, out var port, out var portName, out var portType); if (ModeController == null) - return true; + throw new MessageException("未知模式类型"); if (port != null) - if (!PortCheckAndShowMessageBox((ushort) port, portName, portType)) - return false; + PortCheck((ushort) port, portName, portType); Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ModeController.Name)); - if (await Task.Run(() => ModeController.Start(mode))) - { - if (ModeController is Guard guard) - if (guard.Instance != null) - Global.Job.AddProcess(guard.Instance); - return true; - } - - return false; + ModeController.Start(mode); + if (ModeController is Guard {Instance: { }} guard) + Global.Job.AddProcess(guard.Instance); } /// @@ -205,31 +180,31 @@ namespace Netch.Controllers ServerController = null; } - /// - /// 检查端口是否被占用, - /// 被占用则弹窗提示, 确认后抛出异常 - /// - public static bool PortCheckAndShowMessageBox(ushort port, string portName, PortType portType = PortType.Both) + public static void PortCheck(ushort port, string portName, PortType portType = PortType.Both) { try { CheckPort(port, portType); - return true; } catch (PortInUseException) { - MessageBoxX.Show(i18N.TranslateFormat("The {0} port is in use.", $"{portName} ({port})")); - return false; + throw new MessageException(i18N.TranslateFormat("The {0} port is in use.", $"{portName} ({port})")); } catch (PortReservedException) { - MessageBoxX.Show(i18N.TranslateFormat("The {0} port is reserved by system.", $"{portName} ({port})")); - return false; + throw new MessageException(i18N.TranslateFormat("The {0} port is reserved by system.", $"{portName} ({port})")); } } } - public class StartFailedException : Exception + public class MessageException : Exception { + public MessageException() + { + } + + public MessageException(string message) : base(message) + { + } } } \ No newline at end of file diff --git a/Netch/Controllers/NFController.cs b/Netch/Controllers/NFController.cs index 0439b8f3..0ea38af8 100644 --- a/Netch/Controllers/NFController.cs +++ b/Netch/Controllers/NFController.cs @@ -48,10 +48,9 @@ namespace Netch.Controllers public string Name { get; } = "Redirector"; - public bool Start(in Mode mode) + public void Start(in Mode mode) { - if (!CheckDriver()) - return false; + CheckDriver(); #region aio_dial @@ -85,10 +84,7 @@ namespace Netch.Controllers } if (!CheckRule(mode.FullRule, out var list)) - { - MessageBoxX.Show($"\"{string.Join("", list.Select(s => s + "\n"))}\" does not conform to C++ regular expression syntax"); - return false; - } + throw new MessageException($"\"{string.Join("", list.Select(s => s + "\n"))}\" does not conform to C++ regular expression syntax"); SetName(mode); @@ -103,7 +99,8 @@ namespace Netch.Controllers DNS.OutboundDNS = Global.Settings.ModifiedDNS; } - return aio_init(); + if (!aio_init()) + throw new MessageException("Redirector Start failed, run Netch with \"-console\" argument"); } public void Stop() @@ -150,7 +147,7 @@ namespace Netch.Controllers } } - private static bool CheckDriver() + private static void CheckDriver() { var binFileVersion = Utils.Utils.GetFileVersion(BinDriver); var systemFileVersion = Utils.Utils.GetFileVersion(SystemDriver); @@ -158,50 +155,33 @@ namespace Netch.Controllers Logging.Info("内置驱动版本: " + binFileVersion); Logging.Info("系统驱动版本: " + systemFileVersion); - if (!File.Exists(BinDriver)) + if (!File.Exists(SystemDriver)) { - Logging.Warning("内置驱动不存在"); - if (File.Exists(SystemDriver)) - { - Logging.Warning("使用系统驱动"); - return true; - } - - Logging.Error("未安装驱动"); - return false; + InstallDriver(); + return; } - if (!File.Exists(SystemDriver)) - return InstallDriver(); - - var updateFlag = false; - + var reinstallFlag = false; if (Version.TryParse(binFileVersion, out var binResult) && Version.TryParse(systemFileVersion, out var systemResult)) { if (binResult.CompareTo(systemResult) > 0) - { // Bin greater than Installed - updateFlag = true; - } - else - { - // Installed greater than Bin - if (systemResult.Major != binResult.Major) - // API breaking changes - updateFlag = true; - } + reinstallFlag = true; + else if (systemResult.Major != binResult.Major) + // Installed greater than Bin but Major Version Difference (has breaking changes), do downgrade + reinstallFlag = true; } else { if (!systemFileVersion.Equals(binFileVersion)) - updateFlag = true; + reinstallFlag = true; } - if (!updateFlag) return true; + if (!reinstallFlag) return; Logging.Info("更新驱动"); UninstallDriver(); - return InstallDriver(); + InstallDriver(); } private void SetServer(in PortType portType) @@ -321,9 +301,13 @@ namespace Netch.Controllers /// 安装 NF 驱动 /// /// 驱动是否安装成功 - public static bool InstallDriver() + public static void InstallDriver() { Logging.Info("安装 NF 驱动"); + + if (!File.Exists(BinDriver)) + throw new MessageException(i18N.Translate("builtin driver files missing, can't install NF driver")); + try { File.Copy(BinDriver, SystemDriver); @@ -331,7 +315,7 @@ namespace Netch.Controllers catch (Exception e) { Logging.Error("驱动复制失败\n" + e); - return false; + throw new MessageException($"Copy NF driver file failed\n{e.Message}"); } Global.MainForm.StatusText(i18N.Translate("Register driver")); @@ -344,10 +328,8 @@ namespace Netch.Controllers else { Logging.Error($"注册驱动失败,返回值:{result}"); - return false; + throw new MessageException($"Register NF driver failed\n{result}"); } - - return true; } /// diff --git a/Netch/Controllers/PrivoxyController.cs b/Netch/Controllers/PrivoxyController.cs index a9634c77..296eaac3 100644 --- a/Netch/Controllers/PrivoxyController.cs +++ b/Netch/Controllers/PrivoxyController.cs @@ -12,11 +12,16 @@ namespace Netch.Controllers RedirectStd = false; } - public override string Name { get; } = "Privoxy"; - public override string MainFile { get; protected set; } = "Privoxy.exe"; - public bool Start(Server server, Mode mode) + public override string Name { get; } = "Privoxy"; + + public override void Stop() + { + StopInstance(); + } + + public void Start(Server server) { var text = new StringBuilder(File.ReadAllText("bin\\default.conf")); @@ -34,12 +39,7 @@ namespace Netch.Controllers File.WriteAllText("data\\privoxy.conf", text.ToString()); - return StartInstanceAuto("..\\data\\privoxy.conf"); - } - - public override void Stop() - { - StopInstance(); + StartInstanceAuto("..\\data\\privoxy.conf"); } } } \ No newline at end of file diff --git a/Netch/Controllers/TUNTAPController.cs b/Netch/Controllers/TUNTAPController.cs index 0994e95a..5bb5f9f1 100644 --- a/Netch/Controllers/TUNTAPController.cs +++ b/Netch/Controllers/TUNTAPController.cs @@ -37,28 +37,19 @@ namespace Netch.Controllers public override string Name { get; } = "tun2socks"; - public bool Start(in Mode mode) + public void Start(in Mode mode) { var server = MainController.Server; // 查询服务器 IP 地址 _serverAddresses = DNS.Lookup(server.Hostname); // 查找出口适配器 - if (!Utils.Utils.SearchOutboundAdapter()) - return false; + Utils.Utils.SearchOutboundAdapter(); // 查找并安装 TAP 适配器 - if (!SearchTapAdapter()) - { - if (!AddTap()) - { - Logging.Error("Tap 适配器安装失败"); - return false; - } - - SearchTapAdapter(); - } - + if (string.IsNullOrEmpty(TUNTAP.GetComponentID())) + AddTap(); + SearchTapAdapter(); SetupRouteTable(mode); @@ -79,14 +70,9 @@ namespace Netch.Controllers } else { - if (!MainController.PortCheckAndShowMessageBox(53, "DNS")) - return false; + MainController.PortCheck(53, "DNS"); - if (!DNSController.Start()) - { - Logging.Error("AioDNS 启动失败"); - return false; - } + DNSController.Start(); dns = "127.0.0.1"; } @@ -103,7 +89,7 @@ namespace Netch.Controllers if (Global.Settings.TUNTAP.UseFakeDNS && Global.Flags.SupportFakeDns) argument.Append("-fakeDns "); - return StartInstanceAuto(argument.ToString(), ProcessPriorityClass.RealTime); + StartInstanceAuto(argument.ToString(), ProcessPriorityClass.RealTime); } /// @@ -235,7 +221,7 @@ namespace Netch.Controllers /// /// 搜索出口和TUNTAP适配器 /// - public static bool SearchTapAdapter() + public static void SearchTapAdapter() { Global.TUNTAP.Adapter = null; Global.TUNTAP.Index = -1; @@ -244,31 +230,16 @@ namespace Netch.Controllers // 搜索 TUN/TAP 适配器的索引 if (string.IsNullOrEmpty(Global.TUNTAP.ComponentID)) { - Logging.Info("TAP 适配器未安装"); - return false; + const string s = "TAP 适配器未安装"; + Logging.Info(s); + throw new Exception(s); } // 根据 ComponentID 寻找 Tap适配器 - try - { - var adapter = NetworkInterface.GetAllNetworkInterfaces().First(_ => _.Id == Global.TUNTAP.ComponentID); - Global.TUNTAP.Adapter = adapter; - Global.TUNTAP.Index = adapter.GetIPProperties().GetIPv4Properties().Index; - Logging.Info( - $"TAP 适配器:{adapter.Name} {adapter.Id} {adapter.Description}, index: {Global.TUNTAP.Index}"); - return true; - } - catch (Exception e) - { - var msg = e switch - { - InvalidOperationException _ => $"找不到标识符为 {Global.TUNTAP.ComponentID} 的 TAP 适配器: {e.Message}", - NetworkInformationException _ => $"获取 Tap 适配器信息错误: {e.Message}", - _ => $"Tap 适配器其他异常: {e}" - }; - Logging.Error(msg); - return false; - } + var adapter = NetworkInterface.GetAllNetworkInterfaces().First(_ => _.Id == Global.TUNTAP.ComponentID); + Global.TUNTAP.Adapter = adapter; + Global.TUNTAP.Index = adapter.GetIPProperties().GetIPv4Properties().Index; + Logging.Info($"TAP 适配器:{adapter.Name} {adapter.Id} {adapter.Description}, index: {Global.TUNTAP.Index}"); } private static bool AddTap() @@ -278,8 +249,9 @@ namespace Netch.Controllers Thread.Sleep(1000); if (string.IsNullOrEmpty(Global.TUNTAP.ComponentID = TUNTAP.GetComponentID())) { - Logging.Error("找不到 TAP 适配器,驱动可能安装失败"); - return false; + const string s = "TAP 驱动安装失败,找不到 ComponentID 注册表项"; + Logging.Error(s); + throw new Exception(s); } return true; diff --git a/Netch/Forms/MainForm.cs b/Netch/Forms/MainForm.cs index 908f85ad..aee9f13d 100644 --- a/Netch/Forms/MainForm.cs +++ b/Netch/Forms/MainForm.cs @@ -333,9 +333,10 @@ namespace Netch.Forms Configuration.Save(); StatusText(i18N.Translate("Subscription updated")); } - catch (Exception) + catch (Exception e) { - // ignored + NotifyTip(i18N.Translate("update servers failed") + "\n" + e.Message, info: false); + Logging.Error("更新服务器 失败!" + e); } finally { @@ -453,9 +454,7 @@ namespace Netch.Forms finally { if (useProxy) - { await MainController.Stop(); - } StatusText(); Enabled = true; @@ -595,10 +594,15 @@ namespace Netch.Forms State = State.Starting; - if (!await MainController.Start(server, mode)) + try + { + await MainController.Start(server, mode); + } + catch (Exception exception) { State = State.Stopped; StatusText(i18N.Translate("Start failed")); + MessageBoxX.Show(exception.Message); return; } @@ -1117,52 +1121,6 @@ namespace Netch.Forms return state == State.Waiting || state == State.Stopped; } - public static class StatusPortInfoText - { - private static ushort? _socks5Port; - private static ushort? _httpPort; - private static bool _shareLan; - - public static ushort HttpPort - { - set => _httpPort = value; - } - - public static ushort Socks5Port - { - set => _socks5Port = value; - } - - public static string Value - { - get - { - var strings = new List(); - - if (_socks5Port != null) - strings.Add($"Socks5 {i18N.Translate("Local Port", ": ")}{_socks5Port}"); - - if (_httpPort != null) - strings.Add($"HTTP {i18N.Translate("Local Port", ": ")}{_httpPort}"); - - if (!strings.Any()) - return string.Empty; - - return $" ({(_shareLan ? i18N.Translate("Allow other Devices to connect") + " " : "")}{string.Join(" | ", strings)})"; - } - } - - public static void UpdateShareLan() - { - _shareLan = Global.Settings.LocalAddress != "127.0.0.1"; - } - - public static void Reset() - { - _httpPort = _socks5Port = null; - } - } - /// /// 更新状态栏文本 /// diff --git a/Netch/Models/StatusText.cs b/Netch/Models/StatusText.cs new file mode 100644 index 00000000..3a80f417 --- /dev/null +++ b/Netch/Models/StatusText.cs @@ -0,0 +1,52 @@ +using System.Collections.Generic; +using System.Linq; +using Netch.Utils; + +namespace Netch.Models +{ + public static class StatusPortInfoText + { + private static ushort? _socks5Port; + private static ushort? _httpPort; + private static bool _shareLan; + + public static ushort HttpPort + { + set => _httpPort = value; + } + + public static ushort Socks5Port + { + set => _socks5Port = value; + } + + public static string Value + { + get + { + var strings = new List(); + + if (_socks5Port != null) + strings.Add($"Socks5 {i18N.Translate("Local Port", ": ")}{_socks5Port}"); + + if (_httpPort != null) + strings.Add($"HTTP {i18N.Translate("Local Port", ": ")}{_httpPort}"); + + if (!strings.Any()) + return string.Empty; + + return $" ({(_shareLan ? i18N.Translate("Allow other Devices to connect") + " " : "")}{string.Join(" | ", strings)})"; + } + } + + public static void UpdateShareLan() + { + _shareLan = Global.Settings.LocalAddress != "127.0.0.1"; + } + + public static void Reset() + { + _httpPort = _socks5Port = null; + } + } +} \ No newline at end of file diff --git a/Netch/Servers/Shadowsocks/SSController.cs b/Netch/Servers/Shadowsocks/SSController.cs index 550eb85f..87a659b6 100644 --- a/Netch/Servers/Shadowsocks/SSController.cs +++ b/Netch/Servers/Shadowsocks/SSController.cs @@ -8,15 +8,14 @@ namespace Netch.Servers.Shadowsocks { public class SSController : Guard, IServerController { - public override string Name { get; } = "Shadowsocks"; + public bool DllFlag; public override string MainFile { get; protected set; } = "Shadowsocks.exe"; + public override string Name { get; } = "Shadowsocks"; public ushort? Socks5LocalPort { get; set; } public string LocalAddress { get; set; } - public bool DllFlag; - - public bool Start(in Server s, in Mode mode) + public void Start(in Server s, in Mode mode) { var server = (Shadowsocks) s; @@ -33,8 +32,7 @@ namespace Netch.Servers.Shadowsocks if (!ShadowsocksDLL.Info(client, remote, passwd, method)) { State = State.Stopped; - Logging.Error("DLL SS INFO 设置失败!"); - return false; + throw new MessageException("DLL SS INFO 设置失败!"); } Logging.Info("DLL SS INFO 设置成功!"); @@ -42,13 +40,12 @@ namespace Netch.Servers.Shadowsocks if (!ShadowsocksDLL.Start()) { State = State.Stopped; - Logging.Error("DLL SS 启动失败!"); - return false; + throw new MessageException("DLL SS 启动失败!"); } Logging.Info("DLL SS 启动成功!"); State = State.Started; - return true; + return; } #region Argument @@ -70,7 +67,7 @@ namespace Netch.Servers.Shadowsocks #endregion - return StartInstanceAuto(argument.ToString()); + StartInstanceAuto(argument.ToString()); } public override void Stop() diff --git a/Netch/Servers/ShadowsocksR/SSRController.cs b/Netch/Servers/ShadowsocksR/SSRController.cs index ab2c91f0..73138748 100644 --- a/Netch/Servers/ShadowsocksR/SSRController.cs +++ b/Netch/Servers/ShadowsocksR/SSRController.cs @@ -13,7 +13,7 @@ namespace Netch.Servers.ShadowsocksR public ushort? Socks5LocalPort { get; set; } public string LocalAddress { get; set; } - public bool Start(in Server s, in Mode mode) + public void Start(in Server s, in Mode mode) { var server = (ShadowsocksR) s; @@ -38,7 +38,7 @@ namespace Netch.Servers.ShadowsocksR #endregion - return StartInstanceAuto(argument.ToString()); + StartInstanceAuto(argument.ToString()); } public override void Stop() diff --git a/Netch/Servers/Socks5/S5Controller.cs b/Netch/Servers/Socks5/S5Controller.cs index c3e31819..e2d04916 100644 --- a/Netch/Servers/Socks5/S5Controller.cs +++ b/Netch/Servers/Socks5/S5Controller.cs @@ -7,13 +7,11 @@ namespace Netch.Servers.Socks5 { public override string Name { get; } = "Socks5"; - public override bool Start(in Server s, in Mode mode) + public override void Start(in Server s, in Mode mode) { var server = (Socks5) s; if (server.Auth()) - return base.Start(s, mode); - - return true; + base.Start(s, mode); } } } \ No newline at end of file diff --git a/Netch/Servers/Trojan/TrojanController.cs b/Netch/Servers/Trojan/TrojanController.cs index a4d00e70..5a7b9564 100644 --- a/Netch/Servers/Trojan/TrojanController.cs +++ b/Netch/Servers/Trojan/TrojanController.cs @@ -20,7 +20,7 @@ namespace Netch.Servers.Trojan public ushort? Socks5LocalPort { get; set; } public string LocalAddress { get; set; } - public bool Start(in Server s, in Mode mode) + public void Start(in Server s, in Mode mode) { var server = (Trojan) s; var trojanConfig = new TrojanConfig @@ -42,7 +42,7 @@ namespace Netch.Servers.Trojan { NullValueHandling = NullValueHandling.Ignore })); - return StartInstanceAuto("-c ..\\data\\last.json"); + StartInstanceAuto("-c ..\\data\\last.json"); } public override void Stop() diff --git a/Netch/Servers/V2ray/V2rayController.cs b/Netch/Servers/V2ray/V2rayController.cs index 9bccf93e..0725425d 100644 --- a/Netch/Servers/V2ray/V2rayController.cs +++ b/Netch/Servers/V2ray/V2rayController.cs @@ -17,10 +17,10 @@ namespace Netch.Servers.V2ray public override string Name { get; } = "Xray"; public ushort? Socks5LocalPort { get; set; } public string LocalAddress { get; set; } - public virtual bool Start(in Server s, in Mode mode) + public virtual void Start(in Server s, in Mode mode) { File.WriteAllText("data\\last.json", V2rayConfigUtils.GenerateClientConfig(s, mode)); - return StartInstanceAuto("-config ..\\data\\last.json"); + StartInstanceAuto("-config ..\\data\\last.json"); } public override void Stop() diff --git a/Netch/Updater/Updater.cs b/Netch/Updater/Updater.cs index 4ee34456..b358655a 100644 --- a/Netch/Updater/Updater.cs +++ b/Netch/Updater/Updater.cs @@ -4,7 +4,6 @@ using System.Diagnostics; using System.IO; using System.Linq; using System.Text; -using System.Windows.Forms; using Netch.Forms; using Netch.Properties; diff --git a/Netch/Utils/ModeHelper.cs b/Netch/Utils/ModeHelper.cs index a751e077..6950ce83 100644 --- a/Netch/Utils/ModeHelper.cs +++ b/Netch/Utils/ModeHelper.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; using Netch.Controllers; -using Netch.Forms; using Netch.Models; using Netch.Servers.Shadowsocks; using Netch.Servers.Socks5; @@ -161,14 +160,14 @@ namespace Netch.Utils port = Global.Settings.HTTPLocalPort; portName = "HTTP"; portType = PortType.TCP; - MainForm.StatusPortInfoText.HttpPort = (ushort) port; + StatusPortInfoText.HttpPort = (ushort) port; break; case 4: modeController = null; break; default: Logging.Error("未知模式类型"); - throw new StartFailedException(); + throw new MessageException(); } return modeController; diff --git a/Netch/Utils/PortHelper.cs b/Netch/Utils/PortHelper.cs index 442657c1..75937c84 100644 --- a/Netch/Utils/PortHelper.cs +++ b/Netch/Utils/PortHelper.cs @@ -163,8 +163,20 @@ namespace Netch.Utils public class PortInUseException : Exception { + public PortInUseException(string message) : base(message) + { + } + public PortInUseException() + { + } } public class PortReservedException : Exception { + public PortReservedException(string message) : base(message) + { + } + public PortReservedException() + { + } } } \ No newline at end of file diff --git a/Netch/Utils/Utils.cs b/Netch/Utils/Utils.cs index 048a88ef..b267348b 100644 --- a/Netch/Utils/Utils.cs +++ b/Netch/Utils/Utils.cs @@ -13,6 +13,7 @@ using System.Threading.Tasks; using System.Windows.Forms; using MaxMind.GeoIP2; using Microsoft.Win32.TaskScheduler; +using Vanara.PInvoke; using Task = System.Threading.Tasks.Task; namespace Netch.Utils @@ -136,46 +137,37 @@ namespace Netch.Utils return File.Exists(file) ? FileVersionInfo.GetVersionInfo(file).FileVersion : string.Empty; } - public static bool SearchOutboundAdapter(bool logging = true) + public static void SearchOutboundAdapter(bool logging = true) { // 寻找出口适配器 - if (Vanara.PInvoke.IpHlpApi.GetBestRoute(BitConverter.ToUInt32(IPAddress.Parse("114.114.114.114").GetAddressBytes(), 0), + if (IpHlpApi.GetBestRoute(BitConverter.ToUInt32(IPAddress.Parse("114.114.114.114").GetAddressBytes(), 0), 0, out var pRoute) != 0) { Logging.Error("GetBestRoute 搜索失败"); - return false; + throw new Exception("GetBestRoute 搜索失败"); } Global.Outbound.Index = (int) pRoute.dwForwardIfIndex; // 根据 IP Index 寻找 出口适配器 - try + var adapter = NetworkInterface.GetAllNetworkInterfaces().First(_ => { - var adapter = NetworkInterface.GetAllNetworkInterfaces().First(_ => + try { - try - { - return _.GetIPProperties().GetIPv4Properties().Index == Global.Outbound.Index; - } - catch - { - return false; - } - }); - Global.Outbound.Adapter = adapter; - Global.Outbound.Gateway = new IPAddress(pRoute.dwForwardNextHop.S_un_b); - if (logging) - { - Logging.Info($"出口 IPv4 地址:{Global.Outbound.Address}"); - Logging.Info($"出口 网关 地址:{Global.Outbound.Gateway}"); - Logging.Info($"出口适配器:{adapter.Name} {adapter.Id} {adapter.Description}, index: {Global.Outbound.Index}"); + return _.GetIPProperties().GetIPv4Properties().Index == Global.Outbound.Index; } + catch + { + return false; + } + }); + Global.Outbound.Adapter = adapter; + Global.Outbound.Gateway = new IPAddress(pRoute.dwForwardNextHop.S_un_b); - return true; - } - catch (Exception e) + if (logging) { - Logging.Error($"找不到出口IP所在网卡: {e}"); - return false; + Logging.Info($"出口 IPv4 地址:{Global.Outbound.Address}"); + Logging.Info($"出口 网关 地址:{Global.Outbound.Gateway}"); + Logging.Info($"出口适配器:{adapter.Name} {adapter.Id} {adapter.Description}, index: {Global.Outbound.Index}"); } }