using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using Netch.Forms; using Netch.Models; using Netch.Utils; namespace Netch.Controllers { public class MainController { /// /// 记录当前使用的端口 /// /// public static readonly List UsingPorts = new List(); public EncryptedProxy pEncryptedProxyController { get; private set; } public ModeController pModeController { get; private set; } private Server _savedServer; private Mode _savedMode; public string PortInfo { get { if (_savedMode == null || _savedServer == null) return string.Empty; if (_savedServer.Type == "Socks5" && _savedMode.Type != 3 && _savedMode.Type != 5) // 不可控Socks5, 不可控HTTP return string.Empty; var text = new StringBuilder(); if (_localAddress == "0.0.0.0") text.Append(i18N.Translate("Allow other Devices to connect") + " "); if (_savedServer.Type != "Socks5") // 可控Socks5 text.Append($"Socks5 {i18N.Translate("Local Port", ": ")}{_socks5Port}"); if (_savedMode.Type == 3 || _savedMode.Type == 5) // 有HTTP text.Append($" | HTTP {i18N.Translate("Local Port", ": ")}{_httpPort}"); return $" ({text})"; } } /// /// NTT 控制器 /// public NTTController pNTTController = new NTTController(); private string _localAddress; private int _redirectorTCPPort; private int _httpPort; private int _socks5Port; [DllImport("dnsapi", EntryPoint = "DnsFlushResolverCache")] public static extern uint FlushDNSResolverCache(); /// /// 启动 /// /// 服务器 /// 模式 /// 是否启动成功 public async Task Start(Server server, Mode mode) { Logging.Info($"启动主控制器: {server.Type} [{mode.Type}]{mode.Remark}"); #region Record Settings _httpPort = Global.Settings.HTTPLocalPort; _socks5Port = Global.Settings.Socks5LocalPort; _redirectorTCPPort = Global.Settings.RedirectorTCPPort; _localAddress = Global.Settings.LocalAddress; _savedServer = server; _savedMode = mode; #endregion FlushDNSResolverCache(); _ = Task.Run(Firewall.AddNetchFwRules); bool result; if (server.Type == "Socks5") { result = mode.Type != 4; } else { pEncryptedProxyController = server.Type switch { "SS" => new SSController(), "SSR" => new SSRController(), "VMess" => new VMessController(), "Trojan" => new TrojanController(), _ => pEncryptedProxyController }; KillProcessByName(pEncryptedProxyController.MainFile); // 检查端口是否被占用 var isPortNotAvailable = false; if (_savedServer.Type != "Socks5") { isPortNotAvailable |= PortCheckAndShowMessageBox(_socks5Port, "Socks5"); } switch (_savedMode.Type) { case 0: isPortNotAvailable |= PortCheckAndShowMessageBox(_redirectorTCPPort, "Redirector TCP"); break; case 3: case 5: isPortNotAvailable |= PortCheckAndShowMessageBox(_httpPort, "HTTP"); break; } if (isPortNotAvailable) { Logging.Error("主控制器启动失败: 端口被占用"); return false; } Global.MainForm.StatusText(i18N.Translate("Starting ", pEncryptedProxyController.Name)); result = await Task.Run(() => pEncryptedProxyController.Start(server, mode)); } if (result) { // 加密代理成功启动 UsingPorts.Add(Global.Settings.Socks5LocalPort); // 记录Socks5使用端口 switch (mode.Type) { case 0: // 进程代理模式 pModeController = new NFController(); break; case 1: // TUN/TAP 黑名单代理模式 case 2: // TUN/TAP 白名单代理模式 pModeController = new TUNTAPController(); break; case 3: case 5: pModeController = new HTTPController(); break; case 4: // Socks5 代理模式,不需要启动额外的Server result = true; break; } if (pModeController != null) { Global.MainForm.StatusText(i18N.Translate("Starting ", pModeController.Name)); result = await Task.Run(() => pModeController.Start(server, mode)); } if (result) { // 成功启动 switch (mode.Type) // 记录使用端口 { case 0: UsingPorts.Add(_redirectorTCPPort); break; case 3: case 5: UsingPorts.Add(_httpPort); break; } switch (mode.Type) { case 0: case 1: case 2: _ = Task.Run(() => { Global.MainForm.NatTypeStatusText(i18N.Translate("Starting NatTester")); // Thread.Sleep(1000); var (nttResult, natType, localEnd, publicEnd) = pNTTController.Start(); var country = Utils.Utils.GetCityCode(publicEnd); if (nttResult) Global.MainForm.NatTypeStatusText(natType, country); }); break; } } } if (!result) { Logging.Error("主控制器启动失败"); await Stop(); } return result; } /// /// 停止 /// public async Task Stop() { var tasks = new Task[] { Task.Run(() => pEncryptedProxyController?.Stop()), Task.Run(() => UsingPorts.Clear()), Task.Run(() => pModeController?.Stop()), Task.Run(() => pNTTController.Stop()) }; await Task.WhenAll(tasks); } public static void KillProcessByName(string name) { try { foreach (var p in Process.GetProcessesByName(name)) if (p.MainModule != null && p.MainModule.FileName.StartsWith(Global.NetchDir)) p.Kill(); } catch (Win32Exception e) { Logging.Error($"结束进程 {name} 错误:" + e.Message); } catch (Exception) { // ignored } } /// /// /// /// /// /// /// 端口是否被占用 private static bool PortCheckAndShowMessageBox(int port, string portName, PortType portType = PortType.Both) { if (!PortHelper.PortInUse(port, portType)) return false; MessageBoxX.Show(i18N.TranslateFormat("The {0} port is in use.", portName)); return true; } } }