diff --git a/.editorconfig b/.editorconfig index df3f71f7..d2e5b066 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,7 +1,7 @@ +root = true # http://editorconfig.org/ # top-most EditorConfig file -root = true # all files [*] @@ -32,6 +32,7 @@ resharper_csharp_blank_lines_around_field = 0 resharper_csharp_blank_lines_around_invocable = 0 resharper_csharp_blank_lines_around_type = 0 resharper_csharp_int_align_comments = true +resharper_csharp_keep_blank_lines_in_declarations = 1 resharper_csharp_max_line_length = 368 resharper_csharp_wrap_lines = false resharper_place_expr_accessor_on_single_line = true diff --git a/Netch/Controllers/MainController.cs b/Netch/Controllers/MainController.cs index 533fb891..7334709a 100644 --- a/Netch/Controllers/MainController.cs +++ b/Netch/Controllers/MainController.cs @@ -97,8 +97,8 @@ namespace Netch.Controllers if (!await StartMode(mode)) throw new StartFailedException(); - if (mode.TestNatRequired()) - NatTest(); + _ = Task.Run(Bandwidth.NetTraffic); + _ = Task.Run(NatTest); return true; } @@ -210,7 +210,6 @@ namespace Netch.Controllers ServerController = null; } - /// /// 检查端口是否被占用, /// 被占用则弹窗提示, 确认后抛出异常 @@ -239,6 +238,8 @@ namespace Netch.Controllers /// public static void NatTest() { + if (!Mode.TestNatRequired()) + return; NttTested = false; Task.Run(() => { diff --git a/Netch/Forms/MainForm.Control.cs b/Netch/Forms/MainForm.Control.cs deleted file mode 100644 index 68c3f7bc..00000000 --- a/Netch/Forms/MainForm.Control.cs +++ /dev/null @@ -1,124 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using System.Windows.Forms; -using Netch.Controllers; -using Netch.Models; -using Netch.Utils; - -namespace Netch.Forms -{ - public partial class Dummy - { - } - - partial class MainForm - { - private bool _isFirstCloseWindow = true; - - /// - /// 上一次下载的流量 - /// - public ulong LastDownloadBandwidth; - - /// - /// 上一次上传的流量 - /// - public ulong LastUploadBandwidth; - - private async void ControlFun() - { - Configuration.Save(); - if (State == State.Waiting || State == State.Stopped) - { - // 服务器、模式 需选择 - if (!(ServerComboBox.SelectedItem is Server server)) - { - MessageBoxX.Show(i18N.Translate("Please select a server first")); - return; - } - - if (!(ModeComboBox.SelectedItem is Models.Mode mode)) - { - MessageBoxX.Show(i18N.Translate("Please select a mode first")); - return; - } - - // 清除模式搜索框文本选择 - ModeComboBox.Select(0, 0); - - State = State.Starting; - - if (await MainController.Start(server, mode)) - { - State = State.Started; - _ = Task.Run(() => { Bandwidth.NetTraffic(); }); - // 如果勾选启动后最小化 - if (Global.Settings.MinimizeWhenStarted) - { - WindowState = FormWindowState.Minimized; - - if (_isFirstCloseWindow) - { - // 显示提示语 - NotifyTip(i18N.Translate("Netch is now minimized to the notification bar, double click this icon to restore.")); - _isFirstCloseWindow = false; - } - - Hide(); - } - - if (Global.Settings.StartedTcping) - // 自动检测延迟 - _ = Task.Run(() => - { - while (State == State.Started) - { - server.Test(); - // 重绘 ServerComboBox - ServerComboBox.Invalidate(); - - Thread.Sleep(Global.Settings.StartedTcping_Interval * 1000); - } - }); - } - else - { - State = State.Stopped; - StatusText(i18N.Translate("Start failed")); - } - } - else - { - // 停止 - State = State.Stopping; - await MainController.Stop(); - State = State.Stopped; - } - } - - public void OnBandwidthUpdated(ulong download) - { - if (InvokeRequired) - { - BeginInvoke(new Action(OnBandwidthUpdated), download); - return; - } - - try - { - UsedBandwidthLabel.Text = $"{i18N.Translate("Used", ": ")}{Bandwidth.Compute(download)}"; - //UploadSpeedLabel.Text = $"↑: {Utils.Bandwidth.Compute(upload - LastUploadBandwidth)}/s"; - DownloadSpeedLabel.Text = $"↑↓: {Bandwidth.Compute(download - LastDownloadBandwidth)}/s"; - - //LastUploadBandwidth = upload; - LastDownloadBandwidth = download; - Refresh(); - } - catch - { - // ignored - } - } - } -} \ No newline at end of file diff --git a/Netch/Forms/MainForm.MenuStrip.cs b/Netch/Forms/MainForm.MenuStrip.cs deleted file mode 100644 index 93599f55..00000000 --- a/Netch/Forms/MainForm.MenuStrip.cs +++ /dev/null @@ -1,375 +0,0 @@ -using System; -using System.IO; -using System.Net; -using System.Threading.Tasks; -using System.Windows.Forms; -using Netch.Controllers; -using Netch.Forms.Mode; -using Netch.Models; -using Netch.Utils; - -namespace Netch.Forms -{ - partial class Dummy - { - } - - partial class MainForm - { - #region MenuStrip - - #region 服务器 - - private void ImportServersFromClipboardToolStripMenuItem_Click(object sender, EventArgs e) - { - var texts = Clipboard.GetText(); - if (!string.IsNullOrWhiteSpace(texts)) - { - var servers = ShareLink.ParseText(texts); - Global.Settings.Server.AddRange(servers); - NotifyTip(i18N.TranslateFormat("Import {0} server(s) form Clipboard", servers.Count)); - - InitServer(); - Configuration.Save(); - } - } - - private void AddServerToolStripMenuItem_Click(object sender, EventArgs e) - { - var s = ((ToolStripMenuItem) sender).Text; - - var start = s.IndexOf("[", StringComparison.Ordinal) + 1; - var end = s.IndexOf("]", start, StringComparison.Ordinal); - var result = s.Substring(start, end - start); - - Hide(); - ServerHelper.GetUtilByFullName(result).Create(); - - InitServer(); - Configuration.Save(); - Show(); - } - - #endregion - - #region 模式 - - private void CreateProcessModeToolStripButton_Click(object sender, EventArgs e) - { - Hide(); - new Process().ShowDialog(); - Show(); - } - - private void ReloadModesToolStripMenuItem_Click(object sender, EventArgs e) - { - Enabled = false; - try - { - ModeHelper.Load(); - InitMode(); - NotifyTip(i18N.Translate("Modes have been reload")); - } - catch (Exception) - { - // ignored - } - finally - { - Enabled = true; - } - } - - #endregion - - #region 订阅 - - private void ManageSubscribeLinksToolStripMenuItem_Click(object sender, EventArgs e) - { - Hide(); - new SubscribeForm().ShowDialog(); - InitServer(); - Show(); - } - - private async void UpdateServersFromSubscribeLinksToolStripMenuItem_Click(object sender, EventArgs e) - { - Global.Settings.UseProxyToUpdateSubscription = false; - await UpdateServersFromSubscribe(); - } - - private async void UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem_Click(object sender, EventArgs e) - { - Global.Settings.UseProxyToUpdateSubscription = true; - await UpdateServersFromSubscribe(true); - } - - private async Task UpdateServersFromSubscribe(bool useProxy = false) - { - void DisableItems(bool v) - { - MenuStrip.Enabled = ConfigurationGroupBox.Enabled = ProfileGroupBox.Enabled = ControlButton.Enabled = v; - } - - if (useProxy && ServerComboBox.SelectedIndex == -1) - { - MessageBoxX.Show(i18N.Translate("Please select a server first")); - return; - } - - if (Global.Settings.SubscribeLink.Count <= 0) - { - MessageBoxX.Show(i18N.Translate("No subscription link")); - return; - } - - StatusText(i18N.Translate("Starting update subscription")); - DisableItems(false); - try - { - string proxyServer = null; - if (useProxy) - { - var mode = new Models.Mode - { - Remark = "ProxyUpdate", - Type = 5 - }; - await MainController.Start(ServerComboBox.SelectedItem as Server, mode); - proxyServer = $"http://127.0.0.1:{Global.Settings.HTTPLocalPort}"; - } - - await Subscription.UpdateServersAsync(proxyServer); - - InitServer(); - Configuration.Save(); - StatusText(i18N.Translate("Subscription updated")); - } - catch (Exception) - { - // ignored - } - finally - { - if (useProxy) - try - { - await MainController.Stop(); - } - catch - { - // ignored - } - - DisableItems(true); - } - } - - #endregion - - #region 选项 - - private void CheckForUpdatesToolStripMenuItem_Click(object sender, EventArgs e) - { - Task.Run(() => - { - void OnNewVersionNotFound(object o, EventArgs args) - { - UpdateChecker.NewVersionNotFound -= OnNewVersionNotFound; - NotifyTip(i18N.Translate("Already latest version")); - } - - void OnNewVersionFoundFailed(object o, EventArgs args) - { - UpdateChecker.NewVersionFoundFailed -= OnNewVersionFoundFailed; - NotifyTip(i18N.Translate("New version found failed"), info: false); - } - - UpdateChecker.NewVersionNotFound += OnNewVersionNotFound; - UpdateChecker.NewVersionFoundFailed += OnNewVersionFoundFailed; - CheckUpdate(); - }); - } - - private void OpenDirectoryToolStripMenuItem_Click(object sender, EventArgs e) - { - Utils.Utils.Open(".\\"); - } - - private async void CleanDNSCacheToolStripMenuItem_Click(object sender, EventArgs e) - { - try - { - await Task.Run(() => - { - NativeMethods.FlushDNSResolverCache(); - DNS.Cache.Clear(); - }); - - NotifyTip(i18N.Translate("DNS cache cleanup succeeded")); - } - catch (Exception) - { - // ignored - } - finally - { - StatusText(); - } - } - - private void updateACLWithProxyToolStripMenuItem_Click(object sender, EventArgs e) - { - UpdateACL(true); - } - - private void updateACLToolStripMenuItem_Click(object sender, EventArgs e) - { - UpdateACL(false); - } - - private async void UpdateACL(bool useProxy) - { - if (useProxy && ServerComboBox.SelectedIndex == -1) - { - MessageBoxX.Show(i18N.Translate("Please select a server first")); - return; - } - - Enabled = false; - StatusText(i18N.TranslateFormat("Updating {0}", "ACL")); - try - { - if (useProxy) - { - var mode = new Models.Mode - { - Remark = "ProxyUpdate", - Type = 5 - }; - State = State.Starting; - await MainController.Start(ServerComboBox.SelectedItem as Server, mode); - } - - var req = WebUtil.CreateRequest(Global.Settings.ACL); - if (useProxy) - req.Proxy = new WebProxy($"http://127.0.0.1:{Global.Settings.HTTPLocalPort}"); - - await WebUtil.DownloadFileAsync(req, Path.Combine(Global.NetchDir, "bin\\default.acl")); - NotifyTip(i18N.Translate("ACL updated successfully")); - } - catch (Exception e) - { - NotifyTip(i18N.Translate("ACL update failed") + "\n" + e.Message, info: false); - Logging.Error("更新 ACL 失败!" + e); - } - finally - { - if (useProxy) - { - await MainController.Stop(); - State = State.Stopped; - } - - StatusText(); - Enabled = true; - } - } - - private async void updatePACToolStripMenuItem_Click(object sender, EventArgs eventArgs) - { - Enabled = false; - - StatusText(i18N.TranslateFormat("Updating {0}", "PAC")); - try - { - var req = WebUtil.CreateRequest(Global.Settings.PAC); - - var pac = Path.Combine(Global.NetchDir, "bin\\pac.txt"); - - await WebUtil.DownloadFileAsync(req, pac); - - NotifyTip(i18N.Translate("PAC updated successfully")); - } - catch (Exception e) - { - NotifyTip(i18N.Translate("PAC update failed") + "\n" + e.Message, info: false); - Logging.Error("更新 PAC 失败!" + e); - } - finally - { - StatusText(); - Enabled = true; - } - } - - private async void UninstallServiceToolStripMenuItem_Click(object sender, EventArgs e) - { - Enabled = false; - StatusText(i18N.TranslateFormat("Uninstalling {0}", "NF Service")); - try - { - await Task.Run(() => - { - if (NFController.UninstallDriver()) - NotifyTip(i18N.TranslateFormat("{0} has been uninstalled", "NF Service")); - }); - } - finally - { - StatusText(); - Enabled = true; - } - } - - private async void UninstallTapDriverToolStripMenuItem_Click(object sender, EventArgs e) - { - Enabled = false; - StatusText(i18N.TranslateFormat("Uninstalling {0}", "TUN/TAP driver")); - try - { - await Task.Run(TUNTAP.deltapall); - NotifyTip(i18N.TranslateFormat("{0} has been uninstalled", "TUN/TAP driver")); - } - catch (Exception exception) - { - Logging.Error($"卸载 TUN/TAP 适配器失败: {exception}"); - } - finally - { - StatusText(); - Enabled = true; - } - } - - #endregion - - - /// - /// 菜单栏强制退出 - /// - private void exitToolStripMenuItem_Click(object sender, EventArgs e) - { - Exit(true); - } - - private void VersionLabel_Click(object sender, EventArgs e) - { - Utils.Utils.Open($"https://github.com/{UpdateChecker.Owner}/{UpdateChecker.Repo}/releases"); - } - - private void AboutToolStripButton_Click(object sender, EventArgs e) - { - Hide(); - new AboutForm().ShowDialog(); - Show(); - } - - private void fAQToolStripMenuItem_Click(object sender, EventArgs e) - { - Utils.Utils.Open("https://netch.org/#/docs/zh-CN/faq"); - } - - #endregion - } -} \ No newline at end of file diff --git a/Netch/Forms/MainForm.Misc.cs b/Netch/Forms/MainForm.Misc.cs deleted file mode 100644 index 346841cf..00000000 --- a/Netch/Forms/MainForm.Misc.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Linq; -using System.Net; -using System.Windows.Forms; -using Netch.Controllers; -using Netch.Utils; - -namespace Netch.Forms -{ - partial class MainForm - { - private void CheckUpdate() - { - UpdateChecker.NewVersionFound += (_, _) => - { - NotifyTip($"{i18N.Translate(@"New version available", ": ")}{UpdateChecker.LatestVersionNumber}"); - NewVersionLabel.Visible = true; - }; - UpdateChecker.Check(Global.Settings.CheckBetaUpdate); - } - - private async void NewVersionLabel_Click(object sender, EventArgs e) - { - if (!UpdateChecker.LatestRelease.assets.Any()) - { - Utils.Utils.Open(UpdateChecker.LatestVersionUrl); - return; - } - - if (MessageBoxX.Show(i18N.Translate("Download and install now?"), confirm: true) != DialogResult.OK) - return; - NotifyTip(i18N.Translate("Start downloading new version")); - - NewVersionLabel.Enabled = false; - NewVersionLabel.Text = "..."; - try - { - void OnDownloadProgressChanged(object o1, DownloadProgressChangedEventArgs args) - { - BeginInvoke(new Action(() => { NewVersionLabel.Text = $"{args.ProgressPercentage}%"; })); - } - - await UpdateChecker.UpdateNetch(OnDownloadProgressChanged); - } - catch (Exception exception) - { - Logging.Error(exception.Message); - NotifyTip(exception.Message); - } - } - } -} \ No newline at end of file diff --git a/Netch/Forms/MainForm.Profile.cs b/Netch/Forms/MainForm.Profile.cs deleted file mode 100644 index 4b82baf8..00000000 --- a/Netch/Forms/MainForm.Profile.cs +++ /dev/null @@ -1,187 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using System.Threading.Tasks; -using System.Windows.Forms; -using Netch.Models; -using Netch.Utils; - -namespace Netch.Forms -{ - public partial class Dummy - { - } - - partial class MainForm - { - private int _configurationGroupBoxHeight; - private int _profileConfigurationHeight; - - private void InitProfile() - { - // Clear - foreach (var button in ProfileButtons) - button.Dispose(); - - ProfileButtons.Clear(); - ProfileTable.ColumnStyles.Clear(); - ProfileTable.RowStyles.Clear(); - - var numProfile = Global.Settings.ProfileCount; - if (numProfile == 0) - { - // Hide Profile GroupBox, Change window size - configLayoutPanel.RowStyles[2].SizeType = SizeType.Percent; - configLayoutPanel.RowStyles[2].Height = 0; - ProfileGroupBox.Visible = false; - - ConfigurationGroupBox.Size = new Size(ConfigurationGroupBox.Size.Width, _configurationGroupBoxHeight - _profileConfigurationHeight); - } - else - { - // Load Profiles - ProfileTable.ColumnCount = numProfile; - - while (Global.Settings.Profiles.Count < numProfile) - { - Global.Settings.Profiles.Add(new Profile()); - } - - for (var i = 0; i < numProfile; ++i) - { - var b = new Button(); - b.Click += ProfileButton_Click; - b.Dock = DockStyle.Fill; - b.Text = !Global.Settings.Profiles[i].IsDummy ? Global.Settings.Profiles[i].ProfileName : i18N.Translate("None"); - - ProfileTable.Controls.Add(b, i, 0); - ProfileButtons.Add(b); - } - - // equal column - for (var i = 1; i <= ProfileTable.RowCount; i++) - { - ProfileTable.RowStyles.Add(new RowStyle(SizeType.Percent, 1)); - } - - for (var i = 1; i <= ProfileTable.ColumnCount; i++) - { - ProfileTable.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 1)); - } - - configLayoutPanel.RowStyles[2].SizeType = SizeType.AutoSize; - ProfileGroupBox.Visible = true; - ConfigurationGroupBox.Size = new Size(ConfigurationGroupBox.Size.Width, _configurationGroupBoxHeight); - } - } - - private void LoadProfile(int index) - { - var p = Global.Settings.Profiles[index]; - ProfileNameText.Text = p.ProfileName; - ModeComboBox.ResetCompletionList(); - - if (p.IsDummy) - throw new Exception("Profile not found."); - - var server = ServerComboBox.Items.Cast().FirstOrDefault(s => s.Remark.Equals(p.ServerRemark)); - var mode = ModeComboBox.Items.Cast().FirstOrDefault(m => m.Remark.Equals(p.ModeRemark)); - - if (server == null) - { - throw new Exception("Server not found."); - } - - if (mode == null) - { - throw new Exception("Mode not found."); - } - - ServerComboBox.SelectedItem = server; - ModeComboBox.SelectedItem = mode; - } - - private void SaveProfile(int index) - { - var selectedServer = (Server) ServerComboBox.SelectedItem; - var selectedMode = (Models.Mode) ModeComboBox.SelectedItem; - var name = ProfileNameText.Text; - - Global.Settings.Profiles[index] = new Profile(selectedServer, selectedMode, name); - } - - private void RemoveProfile(int index) - { - Global.Settings.Profiles[index] = new Profile(); - } - - - private List