diff --git a/Netch/Controllers/MainController.cs b/Netch/Controllers/MainController.cs index d6dc5486..035baa12 100644 --- a/Netch/Controllers/MainController.cs +++ b/Netch/Controllers/MainController.cs @@ -51,25 +51,30 @@ namespace Netch.Controllers /// public TUNTAPController pTUNTAPController; + /// + /// NTT 控制器 + /// + public NTTController pNTTController; + /// /// 启动 /// /// 服务器 /// 模式 /// 是否启动成功 - public bool Start(Models.Server server, Models.Mode mode) + public (bool, string) Start(Models.Server server, Models.Mode mode) { - var result = false; + var result = (false, ""); switch (server.Type) { case "Socks5": if (mode.Type == 4) { - result = false; + result = (false, null); } else { - result = true; + result = (true, null); } break; case "SS": @@ -78,7 +83,7 @@ namespace Netch.Controllers { pSSController = new SSController(); } - result = pSSController.Start(server, mode); + result = (pSSController.Start(server, mode), null); break; case "SSR": KillProcess("ShadowsocksR"); @@ -86,7 +91,7 @@ namespace Netch.Controllers { pSSRController = new SSRController(); } - result = pSSRController.Start(server, mode); + result = (pSSRController.Start(server, mode), null); break; case "VMess": KillProcess("v2ray"); @@ -94,11 +99,11 @@ namespace Netch.Controllers { pVMessController = new VMessController(); } - result = pVMessController.Start(server, mode); + result = (pVMessController.Start(server, mode), null); break; } - if (result) + if (result.Item1) { if (mode.Type == 0) { @@ -106,8 +111,12 @@ namespace Netch.Controllers { pNFController = new NFController(); } + if (pNTTController == null) + { + pNTTController = new NTTController(); + } // 进程代理模式,启动 NF 控制器 - result = pNFController.Start(server, mode); + result = (pNFController.Start(server, mode), pNTTController.Start().Item2); } else if (mode.Type == 1) { @@ -115,8 +124,12 @@ namespace Netch.Controllers { pTUNTAPController = new TUNTAPController(); } + if (pNTTController == null) + { + pNTTController = new NTTController(); + } // TUN/TAP 黑名单代理模式,启动 TUN/TAP 控制器 - result = pTUNTAPController.Start(server, mode); + result = (pTUNTAPController.Start(server, mode), pNTTController.Start().Item2); } else if (mode.Type == 2) { @@ -124,8 +137,12 @@ namespace Netch.Controllers { pTUNTAPController = new TUNTAPController(); } + if (pNTTController == null) + { + pNTTController = new NTTController(); + } // TUN/TAP 白名单代理模式,启动 TUN/TAP 控制器 - result = pTUNTAPController.Start(server, mode); + result = (pTUNTAPController.Start(server, mode), pNTTController.Start().Item2); } else if (mode.Type == 3 || mode.Type == 5) { @@ -134,7 +151,7 @@ namespace Netch.Controllers pHTTPController = new HTTPController(); } // HTTP 系统代理和 Socks5 和 HTTP 代理模式,启动 HTTP 控制器 - result = pHTTPController.Start(server, mode); + result = (pHTTPController.Start(server, mode), null); } else if (mode.Type == 4) { @@ -142,11 +159,11 @@ namespace Netch.Controllers } else { - result = false; + result = (false, null); } } - if (!result) + if (!result.Item1) { Stop(); } @@ -171,7 +188,7 @@ namespace Netch.Controllers { pVMessController.Stop(); } - + if (pNFController != null) { pNFController.Stop(); @@ -184,10 +201,15 @@ namespace Netch.Controllers { pHTTPController.Stop(); } - + + if (pNTTController != null) + { + pNTTController.Stop(); + } } - public void KillProcess(string name) { + public void KillProcess(string name) + { var processes = Process.GetProcessesByName(name); foreach (var p in processes) { @@ -198,7 +220,7 @@ namespace Netch.Controllers } } - private static bool IsChildProcess(Process process,string name) + private static bool IsChildProcess(Process process, string name) { bool result; try diff --git a/Netch/Controllers/NFController.cs b/Netch/Controllers/NFController.cs index f12a5c8c..ea5c1399 100644 --- a/Netch/Controllers/NFController.cs +++ b/Netch/Controllers/NFController.cs @@ -114,6 +114,8 @@ namespace Netch.Controllers } var processes = ""; + + mode.Rule.Add("NTT.exe"); foreach (var proc in mode.Rule) { processes += proc; diff --git a/Netch/Controllers/NTTController.cs b/Netch/Controllers/NTTController.cs new file mode 100644 index 00000000..07214ec4 --- /dev/null +++ b/Netch/Controllers/NTTController.cs @@ -0,0 +1,93 @@ +using Netch.Forms; +using System; +using System.Diagnostics; +using System.IO; +using System.Threading; + +namespace Netch.Controllers +{ + public class NTTController + { + /// + /// 进程实例 + /// + public Process Instance; + + /// + /// 当前状态 + /// + public Models.State State = Models.State.Waiting; + + /// + /// 启动NatTypeTester + /// + /// + public (bool, string, string, string) Start() + { + try + { + if (!File.Exists("bin\\NTT.exe")) + { + return (false, null, null, null); + } + + Instance = MainController.GetProcess(); + Instance.StartInfo.FileName = "bin\\NTT.exe"; + + Instance.StartInfo.Arguments = $" {Global.Settings.STUN_Server} {Global.Settings.STUN_Server_Port}"; + + Instance.OutputDataReceived += OnOutputDataReceived; + Instance.ErrorDataReceived += OnOutputDataReceived; + + State = Models.State.Starting; + Instance.Start(); + Instance.BeginOutputReadLine(); + Instance.BeginErrorReadLine(); + Instance.WaitForExit(); + + string[] result = File.ReadAllText("logging\\NTT.log").ToString().Split('#'); + var natType = result[0]; + var localEnd = result[1]; + var publicEnd = result[2]; + + return (true, natType, localEnd, publicEnd); + } + catch (Exception) + { + Utils.Logging.Info("NTT 进程出错"); + Stop(); + return (false, null, null, null); + } + } + + /// + /// 停止 + /// + public void Stop() + { + try + { + if (Instance != null && !Instance.HasExited) + { + Instance.Kill(); + } + } + catch (Exception e) + { + Utils.Logging.Info(e.ToString()); + } + } + + public void OnOutputDataReceived(object sender, DataReceivedEventArgs e) + { + if (!string.IsNullOrWhiteSpace(e.Data)) + { + if (File.Exists("logging\\NTT.log")) + { + File.Delete("logging\\NTT.log"); + } + File.AppendAllText("logging\\NTT.log", $"{e.Data}\r\n"); + } + } + } +} diff --git a/Netch/Forms/MainForm.Designer.cs b/Netch/Forms/MainForm.Designer.cs index 90655895..e829e695 100644 --- a/Netch/Forms/MainForm.Designer.cs +++ b/Netch/Forms/MainForm.Designer.cs @@ -78,6 +78,7 @@ namespace Netch.Forms this.SettingsButton = new System.Windows.Forms.Button(); this.ProfileGroupBox = new System.Windows.Forms.GroupBox(); this.ProfileTable = new System.Windows.Forms.TableLayoutPanel(); + this.NatTypeStatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); this.MenuStrip.SuspendLayout(); this.ConfigurationGroupBox.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.CopyLinkPictureBox)).BeginInit(); @@ -421,7 +422,8 @@ namespace Netch.Forms this.StatusLabel, this.UsedBandwidthLabel, this.DownloadSpeedLabel, - this.UploadSpeedLabel}); + this.UploadSpeedLabel, + this.NatTypeStatusLabel}); this.StatusStrip.Location = new System.Drawing.Point(0, 254); this.StatusStrip.Name = "StatusStrip"; this.StatusStrip.Size = new System.Drawing.Size(629, 22); @@ -534,6 +536,12 @@ namespace Netch.Forms this.ProfileTable.Size = new System.Drawing.Size(599, 43); this.ProfileTable.TabIndex = 0; // + // NatTypeStatusLabel + // + this.NatTypeStatusLabel.Name = "NatTypeStatusLabel"; + this.NatTypeStatusLabel.Size = new System.Drawing.Size(109, 17); + this.NatTypeStatusLabel.Text = ""; + // // MainForm // this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); @@ -623,5 +631,6 @@ namespace Netch.Forms private System.Windows.Forms.PictureBox EditModePictureBox; private System.Windows.Forms.PictureBox DeleteModePictureBox; private System.Windows.Forms.PictureBox CopyLinkPictureBox; + private System.Windows.Forms.ToolStripStatusLabel NatTypeStatusLabel; } } \ No newline at end of file diff --git a/Netch/Forms/MainForm.cs b/Netch/Forms/MainForm.cs index 558571e2..1f0bcf3c 100644 --- a/Netch/Forms/MainForm.cs +++ b/Netch/Forms/MainForm.cs @@ -556,6 +556,7 @@ namespace Netch.Forms MenuStrip.Enabled = ConfigurationGroupBox.Enabled = ControlButton.Enabled = SettingsButton.Enabled = true; ControlButton.Text = Utils.i18N.Translate("Start"); MainController.Stop(); + NatTypeStatusLabel.Text = ""; } Utils.Configuration.Save(); }).ContinueWith(task => @@ -786,7 +787,18 @@ namespace Netch.Forms var mode = ModeComboBox.SelectedItem as Models.Mode; MainController = new MainController(); - if (MainController.Start(server, mode)) + + var startResult = MainController.Start(server, mode);//item1是否启动成功,item2nat类型 + if (startResult.Item2 != null) + { + NatTypeStatusLabel.Text = "NatType:" + startResult.Item2; + } + else + { + NatTypeStatusLabel.Text = ""; + } + + if (startResult.Item1) { // UsedBandwidthLabel.Visible = UploadSpeedLabel.Visible = DownloadSpeedLabel.Visible = true; // MainController.pNFController.OnBandwidthUpdated += OnBandwidthUpdated; @@ -883,6 +895,7 @@ namespace Netch.Forms var mode = ModeComboBox.SelectedItem as Models.Mode; MainController.Stop(); + NatTypeStatusLabel.Text = ""; // LastUploadBandwidth = 0; // LastDownloadBandwidth = 0; diff --git a/Netch/Forms/SettingForm.Designer.cs b/Netch/Forms/SettingForm.Designer.cs index 5e23daee..004e0217 100644 --- a/Netch/Forms/SettingForm.Designer.cs +++ b/Netch/Forms/SettingForm.Designer.cs @@ -58,6 +58,10 @@ this.StartWhenOpenedCheckBox = new System.Windows.Forms.CheckBox(); this.StopWhenExitedCheckBox = new System.Windows.Forms.CheckBox(); this.ExitWhenClosedCheckBox = new System.Windows.Forms.CheckBox(); + this.label1 = new System.Windows.Forms.Label(); + this.STUN_ServerTextBox = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.STUN_ServerPortTextBox = new System.Windows.Forms.TextBox(); this.PortGroupBox.SuspendLayout(); this.TUNTAPGroupBox.SuspendLayout(); this.BehaviorGroupBox.SuspendLayout(); @@ -241,7 +245,7 @@ // ControlButton // this.ControlButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.ControlButton.Location = new System.Drawing.Point(357, 549); + this.ControlButton.Location = new System.Drawing.Point(357, 648); this.ControlButton.Name = "ControlButton"; this.ControlButton.Size = new System.Drawing.Size(75, 23); this.ControlButton.TabIndex = 11; @@ -252,7 +256,7 @@ // GlobalBypassIPsButton // this.GlobalBypassIPsButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.GlobalBypassIPsButton.Location = new System.Drawing.Point(12, 549); + this.GlobalBypassIPsButton.Location = new System.Drawing.Point(12, 648); this.GlobalBypassIPsButton.Name = "GlobalBypassIPsButton"; this.GlobalBypassIPsButton.Size = new System.Drawing.Size(128, 23); this.GlobalBypassIPsButton.TabIndex = 10; @@ -262,7 +266,11 @@ // // BehaviorGroupBox // + this.BehaviorGroupBox.Controls.Add(this.STUN_ServerPortTextBox); + this.BehaviorGroupBox.Controls.Add(this.label2); + this.BehaviorGroupBox.Controls.Add(this.label1); this.BehaviorGroupBox.Controls.Add(this.RunAtStartup); + this.BehaviorGroupBox.Controls.Add(this.STUN_ServerTextBox); this.BehaviorGroupBox.Controls.Add(this.MinimizeWhenStartedCheckBox); this.BehaviorGroupBox.Controls.Add(this.ProfileCount_Label); this.BehaviorGroupBox.Controls.Add(this.ProfileCount_TextBox); @@ -272,7 +280,7 @@ this.BehaviorGroupBox.Controls.Add(this.ExitWhenClosedCheckBox); this.BehaviorGroupBox.Location = new System.Drawing.Point(12, 330); this.BehaviorGroupBox.Name = "BehaviorGroupBox"; - this.BehaviorGroupBox.Size = new System.Drawing.Size(420, 213); + this.BehaviorGroupBox.Size = new System.Drawing.Size(420, 312); this.BehaviorGroupBox.TabIndex = 8; this.BehaviorGroupBox.TabStop = false; this.BehaviorGroupBox.Text = "Behavior"; @@ -358,11 +366,45 @@ this.ExitWhenClosedCheckBox.TextAlign = System.Drawing.ContentAlignment.MiddleRight; this.ExitWhenClosedCheckBox.UseVisualStyleBackColor = true; // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(9, 214); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(82, 17); + this.label1.TabIndex = 10; + this.label1.Text = "STUN Server"; + // + // STUN_ServerTextBox + // + this.STUN_ServerTextBox.Location = new System.Drawing.Point(120, 211); + this.STUN_ServerTextBox.Name = "STUN_ServerTextBox"; + this.STUN_ServerTextBox.Size = new System.Drawing.Size(294, 23); + this.STUN_ServerTextBox.TabIndex = 11; + this.STUN_ServerTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(9, 243); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(110, 17); + this.label2.TabIndex = 12; + this.label2.Text = "STUN Server Port"; + // + // STUN_ServerPortTextBox + // + this.STUN_ServerPortTextBox.Location = new System.Drawing.Point(120, 237); + this.STUN_ServerPortTextBox.Name = "STUN_ServerPortTextBox"; + this.STUN_ServerPortTextBox.Size = new System.Drawing.Size(294, 23); + this.STUN_ServerPortTextBox.TabIndex = 8; + this.STUN_ServerPortTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + // // SettingForm // this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; - this.ClientSize = new System.Drawing.Size(444, 583); + this.ClientSize = new System.Drawing.Size(444, 682); this.Controls.Add(this.BehaviorGroupBox); this.Controls.Add(this.PortGroupBox); this.Controls.Add(this.GlobalBypassIPsButton); @@ -419,5 +461,9 @@ private System.Windows.Forms.TextBox ProfileCount_TextBox; private System.Windows.Forms.CheckBox MinimizeWhenStartedCheckBox; private System.Windows.Forms.CheckBox RunAtStartup; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox STUN_ServerTextBox; + private System.Windows.Forms.TextBox STUN_ServerPortTextBox; } } \ No newline at end of file diff --git a/Netch/Forms/SettingForm.cs b/Netch/Forms/SettingForm.cs index d1350af6..4fa1f4e5 100644 --- a/Netch/Forms/SettingForm.cs +++ b/Netch/Forms/SettingForm.cs @@ -82,6 +82,8 @@ namespace Netch.Forms ProfileCount_Label.Text = Utils.i18N.Translate(ProfileCount_Label.Text); ProfileCount_TextBox.Text = Global.Settings.ProfileCount.ToString(); + STUN_ServerTextBox.Text = Global.Settings.STUN_Server.ToString(); + STUN_ServerPortTextBox.Text = Global.Settings.STUN_Server_Port.ToString(); if (Global.Settings.TUNTAP.DNS.Count > 0) { @@ -289,7 +291,7 @@ namespace Netch.Forms { var ProfileCount = int.Parse(ProfileCount_TextBox.Text); - if (ProfileCount>0) + if (ProfileCount > 0) { Global.Settings.ProfileCount = ProfileCount; } @@ -305,6 +307,29 @@ namespace Netch.Forms return; } + try + { + var STUN_Server = STUN_ServerTextBox.Text; + Global.Settings.STUN_Server = STUN_Server; + + var STUN_ServerPort = int.Parse(STUN_ServerPortTextBox.Text); + + if (STUN_ServerPort > 0) + { + Global.Settings.STUN_Server_Port = STUN_ServerPort; + } + else + { + throw new FormatException(); + } + } + catch (FormatException) + { + ProfileCount_TextBox.Text = Global.Settings.ProfileCount.ToString(); + MessageBox.Show(Utils.i18N.Translate("STUN_ServerPort value illegal. Try again."), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information); + + return; + } Global.Settings.TUNTAP.Address = TUNTAPAddressTextBox.Text; Global.Settings.TUNTAP.Netmask = TUNTAPNetmaskTextBox.Text; diff --git a/Netch/Models/Setting.cs b/Netch/Models/Setting.cs index 4488f0bc..d43284fb 100644 --- a/Netch/Models/Setting.cs +++ b/Netch/Models/Setting.cs @@ -138,5 +138,15 @@ namespace Netch.Models /// 快捷配置数量 /// public int ProfileCount = 4; + + /// + /// STUN测试服务器 + /// + public string STUN_Server = "stun.stunprotocol.org"; + + /// + /// STUN测试服务器 + /// + public int STUN_Server_Port = 3478; } } diff --git a/Netch/Resources/zh-CN b/Netch/Resources/zh-CN index 701284ae..f1a53d82 100644 --- a/Netch/Resources/zh-CN +++ b/Netch/Resources/zh-CN @@ -134,6 +134,7 @@ "Check update when opened": "打开软件时检查更新", "ProfileCount": "快捷配置数量(重启软件生效)", "ProfileCount value illegal. Try again.": "快捷配置数值非法。请重试。", + "STUN_ServerPort value illegal. Try again.": "STUN端口数值非法。请重试。", "TUN/TAP driver is not detected. Is it installed now?": "未检测到TUN/TAP驱动,是否现在安装?", "Profile": "配置名",