[Features] Json Format Mode

New ModeEditForm
Refactors and Cleanup
Update nuget packages
This commit is contained in:
ChsBuffer
2021-11-04 17:43:33 +08:00
parent 5826d1a1a6
commit 2d295a1449
49 changed files with 2017 additions and 1160 deletions

View File

@@ -23,5 +23,9 @@
}
public const string WintunDllFile = "bin\\wintun.dll";
public const string DisableModeDirectoryFileName = "disabled";
public const string DefaultPrimaryDNS = "1.1.1.1:53";
public const string DefaultCNPrimaryDNS = "223.5.5.5:53";
}
}

View File

@@ -4,10 +4,11 @@ using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.Threading;
using Netch.Enums;
using Netch.Interfaces;
using Netch.Models;
using Netch.Models.Modes;
using Netch.Servers;
using Netch.Services;
using Netch.Utils;
using Serilog;
@@ -25,8 +26,6 @@ namespace Netch.Controllers
public static IModeController? ModeController { get; private set; }
public static ModeFeature ModeFeatures { get; private set; }
private static readonly AsyncSemaphore Lock = new(1);
public static async Task StartAsync(Server server, Mode mode)
@@ -49,12 +48,12 @@ namespace Netch.Controllers
try
{
(ModeController, ModeFeatures) = ModeHelper.GetModeControllerByType(mode.Type, out var modePort, out var portName);
ModeController = ModeService.GetModeControllerByType(mode.Type, out var modePort, out var portName);
if (modePort != null)
TryReleaseTcpPort((ushort)modePort, portName);
if (Server is Socks5Server socks5 && (!socks5.Auth() || ModeFeatures.HasFlag(ModeFeature.SupportSocks5Auth)))
if (Server is Socks5Server socks5 && (!socks5.Auth() || ModeController.Features.HasFlag(ModeFeature.SupportSocks5Auth)))
{
Socks5Server = socks5;
}
@@ -75,6 +74,7 @@ namespace Netch.Controllers
// Start Mode Controller
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ModeController.Name));
await ModeController.StartAsync(Socks5Server, mode);
}
catch (Exception e)
@@ -130,7 +130,6 @@ namespace Netch.Controllers
ServerController = null;
ModeController = null;
ModeFeatures = 0;
}
public static void PortCheck(ushort port, string portName, PortType portType = PortType.Both)

View File

@@ -2,11 +2,13 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.ServiceProcess;
using System.Threading.Tasks;
using Netch.Interfaces;
using Netch.Interops;
using Netch.Models;
using Netch.Models.Modes;
using Netch.Models.Modes.ProcessMode;
using Netch.Servers;
using Netch.Utils;
using Serilog;
@@ -17,7 +19,7 @@ namespace Netch.Controllers
public class NFController : IModeController
{
private Server? _server;
private Mode? _mode;
private Redirector _mode = null!;
private RedirectorConfig _rdrConfig = null!;
private static readonly ServiceController NFService = new("netfilter2");
@@ -26,41 +28,55 @@ namespace Netch.Controllers
public string Name => "Redirector";
public ModeFeature Features => ModeFeature.SupportIPv6 | ModeFeature.SupportSocks5Auth;
public async Task StartAsync(Socks5Server server, Mode mode)
{
if (mode is not Redirector processMode)
throw new InvalidOperationException();
_server = server;
_mode = mode;
_mode = processMode;
_rdrConfig = Global.Settings.Redirector;
CheckDriver();
Dial(NameList.AIO_FILTERLOOPBACK, "false");
Dial(NameList.AIO_FILTERINTRANET, "true");
Dial(NameList.AIO_FILTERPARENT, _rdrConfig.ChildProcessHandle.ToString().ToLower());
Dial(NameList.AIO_FILTERICMP, _rdrConfig.FilterICMP.ToString().ToLower());
Dial(NameList.AIO_ICMPING, _rdrConfig.ICMPDelay.ToString());
Dial(NameList.AIO_FILTERLOOPBACK, _mode.FilterLoopback);
Dial(NameList.AIO_FILTERINTRANET, _mode.FilterIntranet);
Dial(NameList.AIO_FILTERPARENT, _mode.FilterParent ?? _rdrConfig.HandleOnlyDNS);
Dial(NameList.AIO_FILTERICMP, _mode.FilterICMP ?? _rdrConfig.FilterICMP);
if (_mode.FilterICMP ?? _rdrConfig.FilterICMP)
Dial(NameList.AIO_ICMPING, (_mode.FilterICMP != null ? _mode.ICMPDelay ?? 10 : _rdrConfig.ICMPDelay).ToString());
Dial(NameList.AIO_FILTERTCP, _mode.FilterTCP ?? _rdrConfig.FilterTCP);
Dial(NameList.AIO_FILTERUDP, _mode.FilterUDP ?? _rdrConfig.FilterUDP);
// DNS
Dial(NameList.AIO_FILTERDNS, _mode.FilterDNS ?? _rdrConfig.FilterDNS);
Dial(NameList.AIO_DNSONLY, _mode.HandleOnlyDNS ?? _rdrConfig.HandleOnlyDNS);
Dial(NameList.AIO_DNSPROX, _mode.DNSProxy ?? _rdrConfig.DNSProxy);
if (_mode.FilterDNS ?? _rdrConfig.FilterDNS)
{
var dnsStr = _mode.FilterDNS != null ? _mode.DNSHost : _rdrConfig.DNSHost;
dnsStr = dnsStr.ValueOrDefault() ?? Constants.DefaultPrimaryDNS;
var dns = IPEndPoint.Parse(dnsStr);
if (dns.Port == 0)
dns.Port = 53;
Dial(NameList.AIO_DNSHOST, dns.Address.ToString());
Dial(NameList.AIO_DNSPORT, dns.Port.ToString());
}
// Server
Dial(NameList.AIO_FILTERUDP, _rdrConfig.FilterProtocol.HasFlag(PortType.UDP).ToString().ToLower());
Dial(NameList.AIO_FILTERTCP, _rdrConfig.FilterProtocol.HasFlag(PortType.TCP).ToString().ToLower());
Dial(NameList.AIO_TGTHOST, await server.AutoResolveHostnameAsync());
Dial(NameList.AIO_TGTPORT, server.Port.ToString());
Dial(NameList.AIO_TGTUSER, server.Username ?? string.Empty);
Dial(NameList.AIO_TGTPASS, server.Password ?? string.Empty);
// Mode Rule
DialRule(_mode);
// DNS
Dial(NameList.AIO_FILTERDNS, _rdrConfig.DNSHijack.ToString().ToLower());
Dial(NameList.AIO_DNSONLY, "false");
Dial(NameList.AIO_DNSPROX, "true");
if (_rdrConfig.DNSHijack)
{
var dns = new Uri(DnsUtils.AppendScheme(DnsUtils.AppendPort(_rdrConfig.DNSHijackHost), "udp"));
Dial(NameList.AIO_DNSHOST, dns.Host);
Dial(NameList.AIO_DNSPORT, dns.Port.ToString());
}
DialRule();
if (!await InitAsync())
throw new MessageException("Redirector start failed.");
@@ -113,20 +129,18 @@ namespace Netch.Controllers
#endregion
private void DialRule(Mode mode)
private void DialRule()
{
Dial(NameList.AIO_CLRNAME, "");
var invalidList = new List<string>();
foreach (var s in mode.GetRules())
foreach (var s in _mode.Bypass)
{
if (s.StartsWith("!"))
{
if (!Dial(NameList.AIO_BYPNAME, s.Substring(1)))
invalidList.Add(s);
continue;
}
if (!Dial(NameList.AIO_BYPNAME, s))
invalidList.Add(s);
}
foreach (var s in _mode.Handle)
{
if (!Dial(NameList.AIO_ADDNAME, s))
invalidList.Add(s);
}
@@ -204,7 +218,7 @@ namespace Netch.Controllers
}
// 注册驱动文件
if (Redirector.aio_register("netfilter2"))
if (Interops.Redirector.aio_register("netfilter2"))
{
Log.Information("Install netfilter2 driver finished");
}
@@ -237,7 +251,7 @@ namespace Netch.Controllers
if (!File.Exists(SystemDriver))
return true;
Redirector.aio_unregister("netfilter2");
Interops.Redirector.aio_unregister("netfilter2");
File.Delete(SystemDriver);
return true;

View File

@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@@ -10,6 +8,8 @@ using Microsoft.VisualStudio.Threading;
using Netch.Forms;
using Netch.Interfaces;
using Netch.Models;
using Netch.Models.Modes;
using Netch.Models.Modes.ShareMode;
using Netch.Servers;
using Netch.Utils;
@@ -18,8 +18,8 @@ namespace Netch.Controllers
public class PcapController : Guard, IModeController
{
private readonly LogForm _form;
private Mode? _mode;
private Server? _server;
private ShareMode _mode = null!;
private Socks5Server _server = null!;
public PcapController() : base("pcap2socks.exe", encoding: Encoding.UTF8)
{
@@ -31,20 +31,25 @@ namespace Netch.Controllers
public override string Name => "pcap2socks";
public ModeFeature Features => 0;
public async Task StartAsync(Socks5Server server, Mode mode)
{
if (mode is not ShareMode shareMode)
throw new InvalidOperationException();
_server = server;
_mode = mode;
_mode = shareMode;
var outboundNetworkInterface = NetworkInterfaceUtils.GetBest();
var argument = new StringBuilder($@"-i \Device\NPF_{outboundNetworkInterface.Id}");
if (_server is Socks5Server socks5 && !socks5.Auth())
argument.Append($" --destination {await socks5.AutoResolveHostnameAsync()}:{socks5.Port}");
if (!_server.Auth())
argument.Append($" --destination {await _server.AutoResolveHostnameAsync()}:{_server.Port}");
else
Trace.Assert(false);
throw new InvalidOperationException();
argument.Append($" {_mode.GetRules().FirstOrDefault() ?? "-P n"}");
argument.Append($" {_mode.Argument}");
await StartGuardAsync(argument.ToString());
}

View File

@@ -1,13 +1,13 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using Netch.Enums;
using Netch.Interfaces;
using Netch.Interops;
using Netch.Models;
using Netch.Models.Modes;
using Netch.Models.Modes.TunMode;
using Netch.Servers;
using Netch.Utils;
using Serilog;
@@ -21,7 +21,7 @@ namespace Netch.Controllers
private readonly DNSController _aioDnsController = new();
private Mode _mode = null!;
private TunMode _mode = null!;
private IPAddress? _serverRemoteAddress;
private TUNConfig _tunConfig = null!;
@@ -30,9 +30,14 @@ namespace Netch.Controllers
public string Name => "tun2socks";
public ModeFeature Features => ModeFeature.SupportSocks5Auth;
public async Task StartAsync(Socks5Server server, Mode mode)
{
_mode = mode;
if (mode is not TunMode tunMode)
throw new InvalidOperationException();
_mode = tunMode;
_tunConfig = Global.Settings.TUNTAP;
if (server is Socks5LocalServer socks5Bridge)
@@ -58,24 +63,17 @@ namespace Netch.Controllers
Dial(NameList.TYPE_UDPREST, "");
Dial(NameList.TYPE_UDPTYPE, "Socks5");
if (server is Socks5Server socks5)
Dial(NameList.TYPE_TCPHOST, $"{await server.AutoResolveHostnameAsync()}:{server.Port}");
Dial(NameList.TYPE_UDPHOST, $"{await server.AutoResolveHostnameAsync()}:{server.Port}");
if (server.Auth())
{
Dial(NameList.TYPE_TCPHOST, $"{await socks5.AutoResolveHostnameAsync()}:{socks5.Port}");
Dial(NameList.TYPE_TCPUSER, server.Username!);
Dial(NameList.TYPE_TCPPASS, server.Password!);
Dial(NameList.TYPE_UDPHOST, $"{await socks5.AutoResolveHostnameAsync()}:{socks5.Port}");
if (socks5.Auth())
{
Dial(NameList.TYPE_TCPUSER, socks5.Username!);
Dial(NameList.TYPE_TCPPASS, socks5.Password!);
Dial(NameList.TYPE_UDPUSER, socks5.Username!);
Dial(NameList.TYPE_UDPPASS, socks5.Password!);
}
}
else
{
Trace.Assert(false);
Dial(NameList.TYPE_UDPUSER, server.Username!);
Dial(NameList.TYPE_UDPPASS, server.Password!);
}
#endregion
@@ -150,6 +148,7 @@ namespace Netch.Controllers
{
Global.MainForm.StatusText(i18N.Translate("Setup Route Table Rule"));
var tunNetworkInterface = NetworkInterfaceUtils.Get(_tun.InterfaceIndex);
// Server Address
if (_serverRemoteAddress != null)
RouteUtils.CreateRoute(_outbound.FillTemplate(_serverRemoteAddress.ToString(), 32));
@@ -157,38 +156,22 @@ namespace Netch.Controllers
// Global Bypass IPs
RouteUtils.CreateRouteFill(_outbound, _tunConfig.BypassIPs);
var tunNetworkInterface = NetworkInterfaceUtils.Get(_tun.InterfaceIndex);
switch (_mode.Type)
// rule
RouteUtils.CreateRouteFill(_tun, _mode.Handle);
RouteUtils.CreateRouteFill(_outbound, _mode.Bypass);
// dns
// NOTICE: DNS metric is network interface metric
tunNetworkInterface.SetDns(DummyDns);
RouteUtils.CreateRoute(_tun.FillTemplate(DummyDns, 32));
if (!_tunConfig.UseCustomDNS)
{
case ModeType.ProxyRuleIPs:
// rules
RouteUtils.CreateRouteFill(_tun, _mode.GetRules());
if (_tunConfig.ProxyDNS)
{
tunNetworkInterface.SetDns(DummyDns);
// proxy dummy dns
RouteUtils.CreateRoute(_tun.FillTemplate(DummyDns, 32));
if (!_tunConfig.UseCustomDNS)
// proxy AioDNS other dns
RouteUtils.CreateRoute(_tun.FillTemplate(Utils.Utils.GetHostFromUri(Global.Settings.AioDNS.OtherDNS), 32));
}
break;
case ModeType.BypassRuleIPs:
RouteUtils.CreateRouteFill(_outbound, _mode.GetRules());
tunNetworkInterface.SetDns(DummyDns);
if (!_tunConfig.UseCustomDNS)
// bypass AioDNS other dns
RouteUtils.CreateRoute(_outbound.FillTemplate(Utils.Utils.GetHostFromUri(Global.Settings.AioDNS.ChinaDNS), 32));
NetworkInterfaceUtils.SetInterfaceMetric(_tun.InterfaceIndex, 0);
RouteUtils.CreateRoute(_tun.FillTemplate("0.0.0.0", 0));
break;
RouteUtils.CreateRoute(_outbound.FillTemplate(Utils.Utils.GetHostFromUri(Global.Settings.AioDNS.ChinaDNS), 32));
RouteUtils.CreateRoute(_tun.FillTemplate(Utils.Utils.GetHostFromUri(Global.Settings.AioDNS.OtherDNS), 32));
}
NetworkInterfaceUtils.SetInterfaceMetric(_tun.InterfaceIndex, 0);
}
private void ClearRouteTable()
@@ -198,13 +181,11 @@ namespace Netch.Controllers
RouteUtils.DeleteRouteFill(_outbound, Global.Settings.TUNTAP.BypassIPs);
switch (_mode.Type)
{
case ModeType.BypassRuleIPs:
RouteUtils.DeleteRouteFill(_outbound, _mode.GetRules());
NetworkInterfaceUtils.SetInterfaceMetric(_outbound.InterfaceIndex);
break;
}
RouteUtils.DeleteRouteFill(_outbound, _mode.Bypass);
RouteUtils.DeleteRoute(_outbound.FillTemplate(Utils.Utils.GetHostFromUri(Global.Settings.AioDNS.ChinaDNS), 32));
NetworkInterfaceUtils.SetInterfaceMetric(_outbound.InterfaceIndex);
}
#endregion

View File

@@ -1,10 +0,0 @@
namespace Netch.Enums
{
public enum ModeType
{
Process = 0,
ProxyRuleIPs = 1,
BypassRuleIPs = 2,
Pcap2Socks = 6
}
}

View File

@@ -0,0 +1,94 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Netch.Models;
namespace Netch.Forms
{
public class BindingForm : Form
{
private readonly Dictionary<Control, Func<string, bool>> _checkActions = new();
private readonly Dictionary<Control, Action<Control>> _saveActions = new();
protected void BindTextBox(TextBoxBase control, Func<string, bool> check, Action<string> save, object value)
{
BindTextBox<string>(control, check, save, value);
}
protected void BindTextBox<T>(TextBoxBase control, Func<T, bool> check, Action<T> save, object value)
{
control.Text = value.ToString();
_checkActions.Add(control,
s =>
{
try
{
return check.Invoke((T)Convert.ChangeType(s, typeof(T)));
}
catch
{
return false;
}
});
_saveActions.Add(control, c => save.Invoke((T)Convert.ChangeType(((TextBoxBase)c).Text, typeof(T))));
}
protected void BindCheckBox(CheckBox control, Action<bool> save, bool value)
{
control.Checked = value;
_saveActions.Add(control, c => save(((CheckBox)c).Checked));
}
protected void BindSyncGlobalCheckBox(SyncGlobalCheckBox control, Action<bool?> save, bool? value, bool globalValue)
{
control.Value = value;
control.GlobalValue = globalValue;
_saveActions.Add(control, c => save(((SyncGlobalCheckBox)c).Value));
}
protected void BindRadioBox(RadioButton control, Action<bool> save, bool value)
{
control.Checked = value;
_saveActions.Add(control, c => save.Invoke(((RadioButton)c).Checked));
}
protected void BindListComboBox<T>(ComboBox comboBox, Action<T> save, IEnumerable<T> values, T value) where T : notnull
{
if (comboBox.DropDownStyle != ComboBoxStyle.DropDownList)
throw new ArgumentOutOfRangeException();
var tagItems = values.Select(o => new TagItem<T>(o, o.ToString()!)).ToArray();
comboBox.Items.AddRange(tagItems.Cast<object>().ToArray());
comboBox.ValueMember = nameof(TagItem<T>.Value);
comboBox.DisplayMember = nameof(TagItem<T>.Text);
_saveActions.Add(comboBox, c => save.Invoke(((TagItem<T>)((ComboBox)c).SelectedItem).Value));
Load += (_, _) => { comboBox.SelectedItem = tagItems.SingleOrDefault(t => t.Value.Equals(value)); };
}
protected void BindComboBox(ComboBox control, Func<string, bool> check, Action<string> save, string value, object[]? values = null)
{
if (values != null)
control.Items.AddRange(values);
_saveActions.Add(control, c => save.Invoke(((ComboBox)c).Text));
_checkActions.Add(control, check.Invoke);
Load += (_, _) => { control.Text = value; };
}
protected List<Control> GetCheckFailedControls()
{
return _checkActions.Where(pair => !pair.Value.Invoke(pair.Key.Text)).Select(pair => pair.Key).ToList();
}
protected void SaveBinds()
{
foreach (var pair in _saveActions)
pair.Value.Invoke(pair.Key);
}
}
}

View File

@@ -86,6 +86,7 @@
this.ProfileTable = new System.Windows.Forms.TableLayoutPanel();
this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
this.ButtomControlContainerControl = new System.Windows.Forms.ContainerControl();
this.ReloadModesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.MenuStrip.SuspendLayout();
this.ConfigurationGroupBox.SuspendLayout();
this.configLayoutPanel.SuspendLayout();
@@ -144,7 +145,8 @@
//
this.ModeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.CreateProcessModeToolStripMenuItem,
this.CreateRouteTableRuleToolStripMenuItem});
this.CreateRouteTableRuleToolStripMenuItem,
this.ReloadModesToolStripMenuItem});
this.ModeToolStripMenuItem.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1);
this.ModeToolStripMenuItem.Name = "ModeToolStripMenuItem";
this.ModeToolStripMenuItem.Size = new System.Drawing.Size(55, 21);
@@ -620,19 +622,19 @@
this.ExitToolStripButton});
this.NotifyMenu.Name = "NotifyMenu";
this.NotifyMenu.ShowItemToolTips = false;
this.NotifyMenu.Size = new System.Drawing.Size(181, 70);
this.NotifyMenu.Size = new System.Drawing.Size(108, 48);
//
// ShowMainFormToolStripButton
//
this.ShowMainFormToolStripButton.Name = "ShowMainFormToolStripButton";
this.ShowMainFormToolStripButton.Size = new System.Drawing.Size(180, 22);
this.ShowMainFormToolStripButton.Size = new System.Drawing.Size(107, 22);
this.ShowMainFormToolStripButton.Text = "Show";
this.ShowMainFormToolStripButton.Click += new System.EventHandler(this.ShowMainFormToolStripButton_Click);
//
// ExitToolStripButton
//
this.ExitToolStripButton.Name = "ExitToolStripButton";
this.ExitToolStripButton.Size = new System.Drawing.Size(180, 22);
this.ExitToolStripButton.Size = new System.Drawing.Size(107, 22);
this.ExitToolStripButton.Text = "Exit";
this.ExitToolStripButton.Click += new System.EventHandler(this.ExitToolStripButton_Click);
//
@@ -697,6 +699,13 @@
this.ButtomControlContainerControl.TabStop = false;
this.ButtomControlContainerControl.Text = "groupBox1";
//
// ReloadModesToolStripMenuItem
//
this.ReloadModesToolStripMenuItem.Name = "ReloadModesToolStripMenuItem";
this.ReloadModesToolStripMenuItem.Size = new System.Drawing.Size(217, 22);
this.ReloadModesToolStripMenuItem.Text = "Reload Modes";
this.ReloadModesToolStripMenuItem.Click += new System.EventHandler(this.ReloadModesToolStripMenuItem_Click);
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
@@ -804,5 +813,6 @@
private System.Windows.Forms.ContainerControl ButtomControlContainerControl;
private System.Windows.Forms.ToolStripMenuItem ShowHideConsoleToolStripMenuItem;
private System.Windows.Forms.ToolStripStatusLabel HttpStatusLabel;
private System.Windows.Forms.ToolStripMenuItem ReloadModesToolStripMenuItem;
}
}

View File

@@ -19,6 +19,7 @@ using Netch.Enums;
using Netch.Forms.ModeForms;
using Netch.Interfaces;
using Netch.Models;
using Netch.Models.Modes;
using Netch.Properties;
using Netch.Services;
using Netch.Utils;
@@ -57,7 +58,7 @@ namespace Netch.Forms
private void AddAddServerToolStripMenuItems()
{
foreach (var serversUtil in ServerHelper.ServerUtilDictionary.Values.OrderBy(i => i.Priority)
.Where(i => !string.IsNullOrEmpty(i.FullName)))
.Where(i => !string.IsNullOrEmpty(i.FullName)))
{
var fullName = serversUtil.FullName;
var control = new ToolStripMenuItem
@@ -83,10 +84,7 @@ namespace Netch.Forms
SelectLastServer();
DelayTestHelper.UpdateTick(true);
ModeHelper.InitWatcher();
ModeHelper.Load();
LoadModes();
SelectLastMode();
ModeService.Instance.Load();
// 加载翻译
TranslateControls();
@@ -109,7 +107,7 @@ namespace Netch.Forms
if (Global.Settings.StartWhenOpened)
ControlButton.PerformClick();
Netch.SingleInstance.ListenForArgumentsFromSuccessiveInstances();
Program.SingleInstance.ListenForArgumentsFromSuccessiveInstances();
}
private void RecordSize()
@@ -262,6 +260,19 @@ namespace Netch.Forms
Show();
}
private void ReloadModesToolStripMenuItem_Click(object sender, EventArgs e)
{
Enabled = false;
try
{
ModeService.Instance.Load();
}
finally
{
Enabled = true;
}
}
#endregion
#region Subscription
@@ -395,9 +406,9 @@ namespace Netch.Forms
private void ShowHideConsoleToolStripMenuItem_Click(object sender, EventArgs e)
{
var windowStyles = (WINDOW_STYLE)PInvoke.GetWindowLong(new HWND(Netch.ConsoleHwnd), WINDOW_LONG_PTR_INDEX.GWL_STYLE);
var windowStyles = (WINDOW_STYLE)PInvoke.GetWindowLong(new HWND(Program.ConsoleHwnd), WINDOW_LONG_PTR_INDEX.GWL_STYLE);
var visible = windowStyles.HasFlag(WINDOW_STYLE.WS_VISIBLE);
PInvoke.ShowWindow(Netch.ConsoleHwnd, visible ? SHOW_WINDOW_CMD.SW_HIDE : SHOW_WINDOW_CMD.SW_SHOWNOACTIVATE);
PInvoke.ShowWindow(Program.ConsoleHwnd, visible ? SHOW_WINDOW_CMD.SW_HIDE : SHOW_WINDOW_CMD.SW_SHOWNOACTIVATE);
}
#endregion
@@ -467,7 +478,6 @@ namespace Netch.Forms
throw new MessageException(i18N.Translate("The downloaded file has the wrong hash"));
}
ModeHelper.SuspendWatcher = true;
await StopAsync();
await Configuration.SaveAsync();
@@ -475,7 +485,7 @@ namespace Netch.Forms
await Task.Run(updater.ApplyUpdate);
// release mutex, exit
Netch.SingleInstance.Dispose();
Program.SingleInstance.Dispose();
Process.Start(Global.NetchExecutable);
Environment.Exit(0);
}
@@ -768,25 +778,26 @@ namespace Netch.Forms
var mode = (Mode)ModeComboBox.SelectedItem;
if (ModifierKeys == Keys.Control)
{
Utils.Utils.Open(ModeHelper.GetFullPath(mode.RelativePath!));
Utils.Utils.Open(mode.FullName);
return;
}
switch (mode.Type)
{
case ModeType.Process:
case ModeType.ProcessMode:
Hide();
new ProcessForm(mode).ShowDialog();
Show();
break;
case ModeType.ProxyRuleIPs:
case ModeType.BypassRuleIPs:
case ModeType.TunMode:
Hide();
new RouteForm(mode).ShowDialog();
Show();
break;
case ModeType.ShareMode:
// throw new NotImplementedException();
default:
Utils.Utils.Open(ModeHelper.GetFullPath(mode.RelativePath!));
Utils.Utils.Open(mode.FullName);
break;
}
}
@@ -800,7 +811,7 @@ namespace Netch.Forms
return;
}
ModeHelper.Delete((Mode)ModeComboBox.SelectedItem);
ModeService.Delete((Mode)ModeComboBox.SelectedItem);
SelectLastMode();
}
@@ -1492,6 +1503,7 @@ namespace Netch.Forms
}
case Mode item:
{
/*
// 绘制 模式Box 底色
e.Graphics.FillRectangle(Brushes.Gray, _numberBoxX, e.Bounds.Y, _numberBoxWidth, e.Bounds.Height);
@@ -1502,6 +1514,7 @@ namespace Netch.Forms
new Point(_numberBoxX + _numberBoxWrap, e.Bounds.Y),
Color.Black,
TextFormatFlags.Left);
*/
break;
}

View File

@@ -20,7 +20,7 @@ namespace Netch.Forms.ModeForms
return string.Empty;
var safeFileName = ToSafeFileName(name);
var relativePath = $"Custom\\{safeFileName}.txt";
var relativePath = $"Custom\\{safeFileName}.json";
return relativePath;
}
}

View File

@@ -32,43 +32,103 @@ namespace Netch.Forms.ModeForms
private void InitializeComponent()
{
this.ConfigurationGroupBox = new System.Windows.Forms.GroupBox();
this.ConfigurationLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.NamePanel = new System.Windows.Forms.Panel();
this.RemarkLabel = new System.Windows.Forms.Label();
this.RemarkTextBox = new System.Windows.Forms.TextBox();
this.FilenameLabel = new System.Windows.Forms.Label();
this.FilenameTextBox = new System.Windows.Forms.TextBox();
this.containerControl1 = new System.Windows.Forms.ContainerControl();
this.RuleRichTextBox = new System.Windows.Forms.RichTextBox();
this.ProcessGroupBox = new System.Windows.Forms.GroupBox();
this.SelectButton = new System.Windows.Forms.Button();
this.ScanButton = new System.Windows.Forms.Button();
this.ValidationButton = new System.Windows.Forms.Button();
this.ControlButton = new System.Windows.Forms.Button();
this.OptionsGroupBox = new System.Windows.Forms.GroupBox();
this.ModeSpecificOptionsLabel = new System.Windows.Forms.Label();
this.HandleTCPCheckBox = new Netch.Forms.SyncGlobalCheckBox();
this.HandleUDPCheckBox = new Netch.Forms.SyncGlobalCheckBox();
this.HandleDNSCheckBox = new Netch.Forms.SyncGlobalCheckBox();
this.DNSLabel = new System.Windows.Forms.Label();
this.DNSTextBox = new System.Windows.Forms.TextBox();
this.HandleProcDNSCheckBox = new Netch.Forms.SyncGlobalCheckBox();
this.ProxyDNSCheckBox = new Netch.Forms.SyncGlobalCheckBox();
this.HandleICMPCheckBox = new Netch.Forms.SyncGlobalCheckBox();
this.ICMPDelayLabel = new System.Windows.Forms.Label();
this.ICMPDelayTextBox = new System.Windows.Forms.TextBox();
this.HandleLoopbackCheckBox = new System.Windows.Forms.CheckBox();
this.HandleLANCheckBox = new System.Windows.Forms.CheckBox();
this.HandleChildProcCheckBox = new Netch.Forms.SyncGlobalCheckBox();
this.RuleTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.ValidationButton = new System.Windows.Forms.Button();
this.HandleTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.HandleHelperFlowLayoutPanel = new System.Windows.Forms.FlowLayoutPanel();
this.HandleLabel = new System.Windows.Forms.Label();
this.HandleSelectButton = new System.Windows.Forms.Button();
this.HandleScanButton = new System.Windows.Forms.Button();
this.HandleContentTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.HandleRuleRichTextBox = new System.Windows.Forms.RichTextBox();
this.BypassTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.BypassFlowLayoutPanel = new System.Windows.Forms.FlowLayoutPanel();
this.BypassLabel = new System.Windows.Forms.Label();
this.BypassSelectButton = new System.Windows.Forms.Button();
this.BypassScanButton = new System.Windows.Forms.Button();
this.BypassContentTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.BypassRuleRichTextBox = new System.Windows.Forms.RichTextBox();
this.ConfigurationGroupBox.SuspendLayout();
this.containerControl1.SuspendLayout();
this.ProcessGroupBox.SuspendLayout();
this.ConfigurationLayoutPanel.SuspendLayout();
this.NamePanel.SuspendLayout();
this.OptionsGroupBox.SuspendLayout();
this.RuleTableLayoutPanel.SuspendLayout();
this.HandleTableLayoutPanel.SuspendLayout();
this.HandleHelperFlowLayoutPanel.SuspendLayout();
this.HandleContentTableLayoutPanel.SuspendLayout();
this.BypassTableLayoutPanel.SuspendLayout();
this.BypassFlowLayoutPanel.SuspendLayout();
this.BypassContentTableLayoutPanel.SuspendLayout();
this.SuspendLayout();
//
// ConfigurationGroupBox
//
this.ConfigurationGroupBox.Controls.Add(this.RemarkLabel);
this.ConfigurationGroupBox.Controls.Add(this.RemarkTextBox);
this.ConfigurationGroupBox.Controls.Add(this.FilenameLabel);
this.ConfigurationGroupBox.Controls.Add(this.FilenameTextBox);
this.ConfigurationGroupBox.Controls.Add(this.containerControl1);
this.ConfigurationGroupBox.Controls.Add(this.ProcessGroupBox);
this.ConfigurationGroupBox.Controls.Add(this.ControlButton);
this.ConfigurationGroupBox.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.ConfigurationGroupBox.Controls.Add(this.ConfigurationLayoutPanel);
this.ConfigurationGroupBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.ConfigurationGroupBox.Location = new System.Drawing.Point(12, 5);
this.ConfigurationGroupBox.Location = new System.Drawing.Point(0, 0);
this.ConfigurationGroupBox.Name = "ConfigurationGroupBox";
this.ConfigurationGroupBox.Size = new System.Drawing.Size(431, 378);
this.ConfigurationGroupBox.Size = new System.Drawing.Size(934, 591);
this.ConfigurationGroupBox.TabIndex = 0;
this.ConfigurationGroupBox.TabStop = false;
this.ConfigurationGroupBox.Text = "Configuration";
//
// ConfigurationLayoutPanel
//
this.ConfigurationLayoutPanel.ColumnCount = 1;
this.ConfigurationLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.ConfigurationLayoutPanel.Controls.Add(this.NamePanel, 0, 0);
this.ConfigurationLayoutPanel.Controls.Add(this.OptionsGroupBox, 0, 1);
this.ConfigurationLayoutPanel.Controls.Add(this.RuleTableLayoutPanel, 0, 2);
this.ConfigurationLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.ConfigurationLayoutPanel.Location = new System.Drawing.Point(3, 19);
this.ConfigurationLayoutPanel.Name = "ConfigurationLayoutPanel";
this.ConfigurationLayoutPanel.RowCount = 3;
this.ConfigurationLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.ConfigurationLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.ConfigurationLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.ConfigurationLayoutPanel.Size = new System.Drawing.Size(928, 569);
this.ConfigurationLayoutPanel.TabIndex = 0;
//
// NamePanel
//
this.NamePanel.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.NamePanel.Controls.Add(this.RemarkLabel);
this.NamePanel.Controls.Add(this.RemarkTextBox);
this.NamePanel.Controls.Add(this.FilenameLabel);
this.NamePanel.Controls.Add(this.FilenameTextBox);
this.NamePanel.Controls.Add(this.ControlButton);
this.NamePanel.Location = new System.Drawing.Point(208, 3);
this.NamePanel.Name = "NamePanel";
this.NamePanel.Size = new System.Drawing.Size(512, 72);
this.NamePanel.TabIndex = 0;
//
// RemarkLabel
//
this.RemarkLabel.AutoSize = true;
this.RemarkLabel.Location = new System.Drawing.Point(12, 25);
this.RemarkLabel.Location = new System.Drawing.Point(8, 8);
this.RemarkLabel.Name = "RemarkLabel";
this.RemarkLabel.Size = new System.Drawing.Size(53, 17);
this.RemarkLabel.TabIndex = 0;
@@ -76,7 +136,7 @@ namespace Netch.Forms.ModeForms
//
// RemarkTextBox
//
this.RemarkTextBox.Location = new System.Drawing.Point(84, 22);
this.RemarkTextBox.Location = new System.Drawing.Point(72, 8);
this.RemarkTextBox.Name = "RemarkTextBox";
this.RemarkTextBox.Size = new System.Drawing.Size(341, 23);
this.RemarkTextBox.TabIndex = 1;
@@ -85,7 +145,7 @@ namespace Netch.Forms.ModeForms
// FilenameLabel
//
this.FilenameLabel.AutoSize = true;
this.FilenameLabel.Location = new System.Drawing.Point(12, 55);
this.FilenameLabel.Location = new System.Drawing.Point(8, 40);
this.FilenameLabel.Name = "FilenameLabel";
this.FilenameLabel.Size = new System.Drawing.Size(59, 17);
this.FilenameLabel.TabIndex = 2;
@@ -93,119 +153,491 @@ namespace Netch.Forms.ModeForms
//
// FilenameTextBox
//
this.FilenameTextBox.Location = new System.Drawing.Point(84, 52);
this.FilenameTextBox.Location = new System.Drawing.Point(72, 40);
this.FilenameTextBox.Name = "FilenameTextBox";
this.FilenameTextBox.ReadOnly = true;
this.FilenameTextBox.Size = new System.Drawing.Size(341, 23);
this.FilenameTextBox.TabIndex = 3;
//
// containerControl1
//
this.containerControl1.Controls.Add(this.RuleRichTextBox);
this.containerControl1.Location = new System.Drawing.Point(6, 81);
this.containerControl1.Name = "containerControl1";
this.containerControl1.Size = new System.Drawing.Size(419, 221);
this.containerControl1.TabIndex = 4;
this.containerControl1.Text = "containerControl1";
//
// RuleRichTextBox
//
this.RuleRichTextBox.DetectUrls = false;
this.RuleRichTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.RuleRichTextBox.Location = new System.Drawing.Point(0, 0);
this.RuleRichTextBox.Name = "RuleRichTextBox";
this.RuleRichTextBox.Size = new System.Drawing.Size(419, 221);
this.RuleRichTextBox.TabIndex = 0;
this.RuleRichTextBox.Text = "";
this.RuleRichTextBox.WordWrap = false;
//
// ProcessGroupBox
//
this.ProcessGroupBox.Controls.Add(this.SelectButton);
this.ProcessGroupBox.Controls.Add(this.ScanButton);
this.ProcessGroupBox.Controls.Add(this.ValidationButton);
this.ProcessGroupBox.Location = new System.Drawing.Point(6, 295);
this.ProcessGroupBox.Name = "ProcessGroupBox";
this.ProcessGroupBox.Size = new System.Drawing.Size(419, 44);
this.ProcessGroupBox.TabIndex = 5;
this.ProcessGroupBox.TabStop = false;
//
// SelectButton
//
this.SelectButton.Location = new System.Drawing.Point(6, 13);
this.SelectButton.Name = "SelectButton";
this.SelectButton.Size = new System.Drawing.Size(75, 23);
this.SelectButton.TabIndex = 0;
this.SelectButton.Text = "Select";
this.SelectButton.UseVisualStyleBackColor = true;
this.SelectButton.Click += new System.EventHandler(this.SelectButton_Click);
//
// ScanButton
//
this.ScanButton.Location = new System.Drawing.Point(87, 13);
this.ScanButton.Name = "ScanButton";
this.ScanButton.Size = new System.Drawing.Size(75, 23);
this.ScanButton.TabIndex = 1;
this.ScanButton.Text = "Scan";
this.ScanButton.UseVisualStyleBackColor = true;
this.ScanButton.Click += new System.EventHandler(this.ScanButton_Click);
//
// ValidationButton
//
this.ValidationButton.Location = new System.Drawing.Point(338, 13);
this.ValidationButton.Name = "ValidationButton";
this.ValidationButton.Size = new System.Drawing.Size(75, 23);
this.ValidationButton.TabIndex = 2;
this.ValidationButton.Text = "Validation";
this.ValidationButton.UseVisualStyleBackColor = true;
this.ValidationButton.Click += new System.EventHandler(this.ValidationButton_Click);
//
// ControlButton
//
this.ControlButton.Location = new System.Drawing.Point(344, 345);
this.ControlButton.Location = new System.Drawing.Point(424, 40);
this.ControlButton.Name = "ControlButton";
this.ControlButton.Size = new System.Drawing.Size(75, 23);
this.ControlButton.TabIndex = 6;
this.ControlButton.TabIndex = 4;
this.ControlButton.Text = "Save";
this.ControlButton.UseVisualStyleBackColor = true;
this.ControlButton.Click += new System.EventHandler(this.ControlButton_Click);
//
// Process
// OptionsGroupBox
//
this.OptionsGroupBox.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.OptionsGroupBox.Controls.Add(this.ModeSpecificOptionsLabel);
this.OptionsGroupBox.Controls.Add(this.HandleTCPCheckBox);
this.OptionsGroupBox.Controls.Add(this.HandleUDPCheckBox);
this.OptionsGroupBox.Controls.Add(this.HandleDNSCheckBox);
this.OptionsGroupBox.Controls.Add(this.DNSLabel);
this.OptionsGroupBox.Controls.Add(this.DNSTextBox);
this.OptionsGroupBox.Controls.Add(this.HandleProcDNSCheckBox);
this.OptionsGroupBox.Controls.Add(this.ProxyDNSCheckBox);
this.OptionsGroupBox.Controls.Add(this.HandleICMPCheckBox);
this.OptionsGroupBox.Controls.Add(this.ICMPDelayLabel);
this.OptionsGroupBox.Controls.Add(this.ICMPDelayTextBox);
this.OptionsGroupBox.Controls.Add(this.HandleLoopbackCheckBox);
this.OptionsGroupBox.Controls.Add(this.HandleLANCheckBox);
this.OptionsGroupBox.Controls.Add(this.HandleChildProcCheckBox);
this.OptionsGroupBox.Location = new System.Drawing.Point(15, 81);
this.OptionsGroupBox.Name = "OptionsGroupBox";
this.OptionsGroupBox.Size = new System.Drawing.Size(898, 183);
this.OptionsGroupBox.TabIndex = 1;
this.OptionsGroupBox.TabStop = false;
//
// ModeSpecificOptionsLabel
//
this.ModeSpecificOptionsLabel.AutoSize = true;
this.ModeSpecificOptionsLabel.Location = new System.Drawing.Point(720, 24);
this.ModeSpecificOptionsLabel.Name = "ModeSpecificOptionsLabel";
this.ModeSpecificOptionsLabel.Size = new System.Drawing.Size(138, 17);
this.ModeSpecificOptionsLabel.TabIndex = 13;
this.ModeSpecificOptionsLabel.Text = "Mode specific options";
//
// HandleTCPCheckBox
//
this.HandleTCPCheckBox.AutoCheck = false;
this.HandleTCPCheckBox.AutoSize = true;
this.HandleTCPCheckBox.BackColor = System.Drawing.Color.Yellow;
this.HandleTCPCheckBox.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic))), System.Drawing.GraphicsUnit.Point);
this.HandleTCPCheckBox.GlobalValue = false;
this.HandleTCPCheckBox.Location = new System.Drawing.Point(8, 24);
this.HandleTCPCheckBox.Name = "HandleTCPCheckBox";
this.HandleTCPCheckBox.Size = new System.Drawing.Size(99, 21);
this.HandleTCPCheckBox.SyncGlobal = false;
this.HandleTCPCheckBox.TabIndex = 0;
this.HandleTCPCheckBox.Text = "Handle TCP";
this.HandleTCPCheckBox.ThreeState = true;
this.HandleTCPCheckBox.UseVisualStyleBackColor = true;
this.HandleTCPCheckBox.Value = false;
//
// HandleUDPCheckBox
//
this.HandleUDPCheckBox.AutoCheck = false;
this.HandleUDPCheckBox.AutoSize = true;
this.HandleUDPCheckBox.BackColor = System.Drawing.Color.Yellow;
this.HandleUDPCheckBox.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic))), System.Drawing.GraphicsUnit.Point);
this.HandleUDPCheckBox.GlobalValue = false;
this.HandleUDPCheckBox.Location = new System.Drawing.Point(8, 56);
this.HandleUDPCheckBox.Name = "HandleUDPCheckBox";
this.HandleUDPCheckBox.Size = new System.Drawing.Size(102, 21);
this.HandleUDPCheckBox.SyncGlobal = false;
this.HandleUDPCheckBox.TabIndex = 1;
this.HandleUDPCheckBox.Text = "Handle UDP";
this.HandleUDPCheckBox.ThreeState = true;
this.HandleUDPCheckBox.UseVisualStyleBackColor = true;
this.HandleUDPCheckBox.Value = false;
//
// HandleDNSCheckBox
//
this.HandleDNSCheckBox.AutoCheck = false;
this.HandleDNSCheckBox.AutoSize = true;
this.HandleDNSCheckBox.BackColor = System.Drawing.Color.Yellow;
this.HandleDNSCheckBox.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic))), System.Drawing.GraphicsUnit.Point);
this.HandleDNSCheckBox.GlobalValue = false;
this.HandleDNSCheckBox.Location = new System.Drawing.Point(8, 88);
this.HandleDNSCheckBox.Name = "HandleDNSCheckBox";
this.HandleDNSCheckBox.Size = new System.Drawing.Size(203, 21);
this.HandleDNSCheckBox.SyncGlobal = false;
this.HandleDNSCheckBox.TabIndex = 2;
this.HandleDNSCheckBox.Text = "Handle DNS (DNS hijacking)";
this.HandleDNSCheckBox.ThreeState = true;
this.HandleDNSCheckBox.UseVisualStyleBackColor = true;
this.HandleDNSCheckBox.Value = false;
//
// DNSLabel
//
this.DNSLabel.AutoSize = true;
this.DNSLabel.Location = new System.Drawing.Point(248, 88);
this.DNSLabel.Name = "DNSLabel";
this.DNSLabel.Size = new System.Drawing.Size(34, 17);
this.DNSLabel.TabIndex = 3;
this.DNSLabel.Text = "DNS";
//
// DNSTextBox
//
this.DNSTextBox.Location = new System.Drawing.Point(296, 88);
this.DNSTextBox.Name = "DNSTextBox";
this.DNSTextBox.Size = new System.Drawing.Size(184, 23);
this.DNSTextBox.TabIndex = 4;
this.DNSTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// HandleProcDNSCheckBox
//
this.HandleProcDNSCheckBox.AutoCheck = false;
this.HandleProcDNSCheckBox.AutoSize = true;
this.HandleProcDNSCheckBox.BackColor = System.Drawing.Color.Yellow;
this.HandleProcDNSCheckBox.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic))), System.Drawing.GraphicsUnit.Point);
this.HandleProcDNSCheckBox.GlobalValue = false;
this.HandleProcDNSCheckBox.Location = new System.Drawing.Point(8, 120);
this.HandleProcDNSCheckBox.Name = "HandleProcDNSCheckBox";
this.HandleProcDNSCheckBox.Size = new System.Drawing.Size(216, 21);
this.HandleProcDNSCheckBox.SyncGlobal = false;
this.HandleProcDNSCheckBox.TabIndex = 5;
this.HandleProcDNSCheckBox.Text = "Handle handled process\'s DNS";
this.HandleProcDNSCheckBox.ThreeState = true;
this.HandleProcDNSCheckBox.UseVisualStyleBackColor = true;
this.HandleProcDNSCheckBox.Value = false;
//
// ProxyDNSCheckBox
//
this.ProxyDNSCheckBox.AutoCheck = false;
this.ProxyDNSCheckBox.AutoSize = true;
this.ProxyDNSCheckBox.BackColor = System.Drawing.Color.Yellow;
this.ProxyDNSCheckBox.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic))), System.Drawing.GraphicsUnit.Point);
this.ProxyDNSCheckBox.GlobalValue = false;
this.ProxyDNSCheckBox.Location = new System.Drawing.Point(240, 120);
this.ProxyDNSCheckBox.Name = "ProxyDNSCheckBox";
this.ProxyDNSCheckBox.Size = new System.Drawing.Size(195, 21);
this.ProxyDNSCheckBox.SyncGlobal = false;
this.ProxyDNSCheckBox.TabIndex = 6;
this.ProxyDNSCheckBox.Text = "Handle DNS through proxy";
this.ProxyDNSCheckBox.ThreeState = true;
this.ProxyDNSCheckBox.UseVisualStyleBackColor = true;
this.ProxyDNSCheckBox.Value = false;
//
// HandleICMPCheckBox
//
this.HandleICMPCheckBox.AutoCheck = false;
this.HandleICMPCheckBox.AutoSize = true;
this.HandleICMPCheckBox.BackColor = System.Drawing.Color.Yellow;
this.HandleICMPCheckBox.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic))), System.Drawing.GraphicsUnit.Point);
this.HandleICMPCheckBox.GlobalValue = false;
this.HandleICMPCheckBox.Location = new System.Drawing.Point(8, 152);
this.HandleICMPCheckBox.Name = "HandleICMPCheckBox";
this.HandleICMPCheckBox.Size = new System.Drawing.Size(107, 21);
this.HandleICMPCheckBox.SyncGlobal = false;
this.HandleICMPCheckBox.TabIndex = 7;
this.HandleICMPCheckBox.Text = "Handle ICMP";
this.HandleICMPCheckBox.ThreeState = true;
this.HandleICMPCheckBox.UseVisualStyleBackColor = true;
this.HandleICMPCheckBox.Value = false;
//
// ICMPDelayLabel
//
this.ICMPDelayLabel.AutoSize = true;
this.ICMPDelayLabel.Location = new System.Drawing.Point(176, 152);
this.ICMPDelayLabel.Name = "ICMPDelayLabel";
this.ICMPDelayLabel.Size = new System.Drawing.Size(99, 17);
this.ICMPDelayLabel.TabIndex = 8;
this.ICMPDelayLabel.Text = "ICMP delay(ms)";
//
// ICMPDelayTextBox
//
this.ICMPDelayTextBox.Location = new System.Drawing.Point(296, 152);
this.ICMPDelayTextBox.Name = "ICMPDelayTextBox";
this.ICMPDelayTextBox.Size = new System.Drawing.Size(80, 23);
this.ICMPDelayTextBox.TabIndex = 9;
this.ICMPDelayTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// HandleLoopbackCheckBox
//
this.HandleLoopbackCheckBox.AutoSize = true;
this.HandleLoopbackCheckBox.Location = new System.Drawing.Point(720, 56);
this.HandleLoopbackCheckBox.Name = "HandleLoopbackCheckBox";
this.HandleLoopbackCheckBox.Size = new System.Drawing.Size(158, 21);
this.HandleLoopbackCheckBox.TabIndex = 10;
this.HandleLoopbackCheckBox.Text = "Handle local loopback";
this.HandleLoopbackCheckBox.UseVisualStyleBackColor = true;
//
// HandleLANCheckBox
//
this.HandleLANCheckBox.AutoSize = true;
this.HandleLANCheckBox.Location = new System.Drawing.Point(720, 88);
this.HandleLANCheckBox.Name = "HandleLANCheckBox";
this.HandleLANCheckBox.Size = new System.Drawing.Size(96, 21);
this.HandleLANCheckBox.TabIndex = 11;
this.HandleLANCheckBox.Text = "Handle LAN";
this.HandleLANCheckBox.UseVisualStyleBackColor = true;
//
// HandleChildProcCheckBox
//
this.HandleChildProcCheckBox.AutoCheck = false;
this.HandleChildProcCheckBox.AutoSize = true;
this.HandleChildProcCheckBox.BackColor = System.Drawing.Color.Yellow;
this.HandleChildProcCheckBox.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic))), System.Drawing.GraphicsUnit.Point);
this.HandleChildProcCheckBox.GlobalValue = false;
this.HandleChildProcCheckBox.Location = new System.Drawing.Point(496, 24);
this.HandleChildProcCheckBox.Name = "HandleChildProcCheckBox";
this.HandleChildProcCheckBox.Size = new System.Drawing.Size(155, 21);
this.HandleChildProcCheckBox.SyncGlobal = false;
this.HandleChildProcCheckBox.TabIndex = 12;
this.HandleChildProcCheckBox.Text = "Handle child process";
this.HandleChildProcCheckBox.ThreeState = true;
this.HandleChildProcCheckBox.UseVisualStyleBackColor = true;
this.HandleChildProcCheckBox.Value = false;
//
// RuleTableLayoutPanel
//
this.RuleTableLayoutPanel.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.RuleTableLayoutPanel.ColumnCount = 2;
this.RuleTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.RuleTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.RuleTableLayoutPanel.Controls.Add(this.ValidationButton, 0, 0);
this.RuleTableLayoutPanel.Controls.Add(this.HandleTableLayoutPanel, 0, 1);
this.RuleTableLayoutPanel.Controls.Add(this.BypassTableLayoutPanel, 1, 1);
this.RuleTableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.RuleTableLayoutPanel.Location = new System.Drawing.Point(3, 270);
this.RuleTableLayoutPanel.Name = "RuleTableLayoutPanel";
this.RuleTableLayoutPanel.RowCount = 2;
this.RuleTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.RuleTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.RuleTableLayoutPanel.Size = new System.Drawing.Size(922, 296);
this.RuleTableLayoutPanel.TabIndex = 2;
//
// ValidationButton
//
this.ValidationButton.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.RuleTableLayoutPanel.SetColumnSpan(this.ValidationButton, 2);
this.ValidationButton.Location = new System.Drawing.Point(423, 3);
this.ValidationButton.Name = "ValidationButton";
this.ValidationButton.Size = new System.Drawing.Size(75, 23);
this.ValidationButton.TabIndex = 0;
this.ValidationButton.Text = "Validation";
this.ValidationButton.UseVisualStyleBackColor = true;
this.ValidationButton.Click += new System.EventHandler(this.ValidationButton_Click);
//
// HandleTableLayoutPanel
//
this.HandleTableLayoutPanel.ColumnCount = 1;
this.HandleTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.HandleTableLayoutPanel.Controls.Add(this.HandleHelperFlowLayoutPanel, 0, 0);
this.HandleTableLayoutPanel.Controls.Add(this.HandleContentTableLayoutPanel, 0, 1);
this.HandleTableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.HandleTableLayoutPanel.Location = new System.Drawing.Point(3, 32);
this.HandleTableLayoutPanel.Name = "HandleTableLayoutPanel";
this.HandleTableLayoutPanel.RowCount = 2;
this.HandleTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.HandleTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.HandleTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.HandleTableLayoutPanel.Size = new System.Drawing.Size(455, 261);
this.HandleTableLayoutPanel.TabIndex = 1;
//
// HandleHelperFlowLayoutPanel
//
this.HandleHelperFlowLayoutPanel.Controls.Add(this.HandleLabel);
this.HandleHelperFlowLayoutPanel.Controls.Add(this.HandleSelectButton);
this.HandleHelperFlowLayoutPanel.Controls.Add(this.HandleScanButton);
this.HandleHelperFlowLayoutPanel.Location = new System.Drawing.Point(3, 3);
this.HandleHelperFlowLayoutPanel.Name = "HandleHelperFlowLayoutPanel";
this.HandleHelperFlowLayoutPanel.Size = new System.Drawing.Size(269, 32);
this.HandleHelperFlowLayoutPanel.TabIndex = 0;
//
// HandleLabel
//
this.HandleLabel.AutoSize = true;
this.HandleLabel.Location = new System.Drawing.Point(3, 0);
this.HandleLabel.Name = "HandleLabel";
this.HandleLabel.Padding = new System.Windows.Forms.Padding(7);
this.HandleLabel.Size = new System.Drawing.Size(95, 31);
this.HandleLabel.TabIndex = 0;
this.HandleLabel.Text = "Handle rules";
//
// HandleSelectButton
//
this.HandleSelectButton.Location = new System.Drawing.Point(104, 3);
this.HandleSelectButton.Name = "HandleSelectButton";
this.HandleSelectButton.Size = new System.Drawing.Size(75, 23);
this.HandleSelectButton.TabIndex = 1;
this.HandleSelectButton.Text = "Select";
this.HandleSelectButton.UseVisualStyleBackColor = true;
this.HandleSelectButton.Click += new System.EventHandler(this.SelectButton_Click);
//
// HandleScanButton
//
this.HandleHelperFlowLayoutPanel.SetFlowBreak(this.HandleScanButton, true);
this.HandleScanButton.Location = new System.Drawing.Point(185, 3);
this.HandleScanButton.Name = "HandleScanButton";
this.HandleScanButton.Size = new System.Drawing.Size(75, 23);
this.HandleScanButton.TabIndex = 2;
this.HandleScanButton.Text = "Scan";
this.HandleScanButton.UseVisualStyleBackColor = true;
this.HandleScanButton.Click += new System.EventHandler(this.ScanButton_Click);
//
// HandleContentTableLayoutPanel
//
this.HandleContentTableLayoutPanel.ColumnCount = 1;
this.HandleContentTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.HandleContentTableLayoutPanel.Controls.Add(this.HandleRuleRichTextBox, 0, 0);
this.HandleContentTableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.HandleContentTableLayoutPanel.Location = new System.Drawing.Point(3, 41);
this.HandleContentTableLayoutPanel.Name = "HandleContentTableLayoutPanel";
this.HandleContentTableLayoutPanel.RowCount = 1;
this.HandleContentTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.HandleContentTableLayoutPanel.Size = new System.Drawing.Size(449, 217);
this.HandleContentTableLayoutPanel.TabIndex = 1;
//
// HandleRuleRichTextBox
//
this.HandleRuleRichTextBox.DetectUrls = false;
this.HandleRuleRichTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.HandleRuleRichTextBox.Location = new System.Drawing.Point(3, 3);
this.HandleRuleRichTextBox.Name = "HandleRuleRichTextBox";
this.HandleRuleRichTextBox.Size = new System.Drawing.Size(443, 211);
this.HandleRuleRichTextBox.TabIndex = 0;
this.HandleRuleRichTextBox.Text = "";
this.HandleRuleRichTextBox.WordWrap = false;
//
// BypassTableLayoutPanel
//
this.BypassTableLayoutPanel.ColumnCount = 1;
this.BypassTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.BypassTableLayoutPanel.Controls.Add(this.BypassFlowLayoutPanel, 0, 0);
this.BypassTableLayoutPanel.Controls.Add(this.BypassContentTableLayoutPanel, 0, 1);
this.BypassTableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.BypassTableLayoutPanel.Location = new System.Drawing.Point(464, 32);
this.BypassTableLayoutPanel.Name = "BypassTableLayoutPanel";
this.BypassTableLayoutPanel.RowCount = 2;
this.BypassTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.BypassTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.BypassTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.BypassTableLayoutPanel.Size = new System.Drawing.Size(455, 261);
this.BypassTableLayoutPanel.TabIndex = 2;
//
// BypassFlowLayoutPanel
//
this.BypassFlowLayoutPanel.Controls.Add(this.BypassLabel);
this.BypassFlowLayoutPanel.Controls.Add(this.BypassSelectButton);
this.BypassFlowLayoutPanel.Controls.Add(this.BypassScanButton);
this.BypassFlowLayoutPanel.Location = new System.Drawing.Point(3, 3);
this.BypassFlowLayoutPanel.Name = "BypassFlowLayoutPanel";
this.BypassFlowLayoutPanel.Size = new System.Drawing.Size(269, 32);
this.BypassFlowLayoutPanel.TabIndex = 0;
//
// BypassLabel
//
this.BypassLabel.AutoSize = true;
this.BypassLabel.Location = new System.Drawing.Point(3, 0);
this.BypassLabel.Name = "BypassLabel";
this.BypassLabel.Padding = new System.Windows.Forms.Padding(7);
this.BypassLabel.Size = new System.Drawing.Size(95, 31);
this.BypassLabel.TabIndex = 0;
this.BypassLabel.Text = "Bypass rules";
//
// BypassSelectButton
//
this.BypassSelectButton.Location = new System.Drawing.Point(104, 3);
this.BypassSelectButton.Name = "BypassSelectButton";
this.BypassSelectButton.Size = new System.Drawing.Size(75, 23);
this.BypassSelectButton.TabIndex = 1;
this.BypassSelectButton.Text = "Select";
this.BypassSelectButton.UseVisualStyleBackColor = true;
this.BypassSelectButton.Click += new System.EventHandler(this.SelectButton_Click);
//
// BypassScanButton
//
this.BypassScanButton.Location = new System.Drawing.Point(185, 3);
this.BypassScanButton.Name = "BypassScanButton";
this.BypassScanButton.Size = new System.Drawing.Size(75, 23);
this.BypassScanButton.TabIndex = 2;
this.BypassScanButton.Text = "Scan";
this.BypassScanButton.UseVisualStyleBackColor = true;
this.BypassScanButton.Click += new System.EventHandler(this.ScanButton_Click);
//
// BypassContentTableLayoutPanel
//
this.BypassContentTableLayoutPanel.ColumnCount = 1;
this.BypassContentTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.BypassContentTableLayoutPanel.Controls.Add(this.BypassRuleRichTextBox, 0, 0);
this.BypassContentTableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.BypassContentTableLayoutPanel.Location = new System.Drawing.Point(3, 41);
this.BypassContentTableLayoutPanel.Name = "BypassContentTableLayoutPanel";
this.BypassContentTableLayoutPanel.RowCount = 1;
this.BypassContentTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.BypassContentTableLayoutPanel.Size = new System.Drawing.Size(449, 217);
this.BypassContentTableLayoutPanel.TabIndex = 1;
//
// BypassRuleRichTextBox
//
this.BypassRuleRichTextBox.DetectUrls = false;
this.BypassRuleRichTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.BypassRuleRichTextBox.Location = new System.Drawing.Point(3, 3);
this.BypassRuleRichTextBox.Name = "BypassRuleRichTextBox";
this.BypassRuleRichTextBox.Size = new System.Drawing.Size(443, 211);
this.BypassRuleRichTextBox.TabIndex = 0;
this.BypassRuleRichTextBox.Text = "";
this.BypassRuleRichTextBox.WordWrap = false;
//
// ProcessForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.ClientSize = new System.Drawing.Size(455, 388);
this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.ClientSize = new System.Drawing.Size(934, 591);
this.Controls.Add(this.ConfigurationGroupBox);
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
this.MaximizeBox = false;
this.MinimumSize = new System.Drawing.Size(950, 630);
this.Name = "ProcessForm";
this.Padding = new System.Windows.Forms.Padding(12, 5, 12, 5);
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Create Process Mode";
this.Load += new System.EventHandler(this.ModeForm_Load);
this.ConfigurationGroupBox.ResumeLayout(false);
this.ConfigurationGroupBox.PerformLayout();
this.containerControl1.ResumeLayout(false);
this.ProcessGroupBox.ResumeLayout(false);
this.ConfigurationLayoutPanel.ResumeLayout(false);
this.NamePanel.ResumeLayout(false);
this.NamePanel.PerformLayout();
this.OptionsGroupBox.ResumeLayout(false);
this.OptionsGroupBox.PerformLayout();
this.RuleTableLayoutPanel.ResumeLayout(false);
this.HandleTableLayoutPanel.ResumeLayout(false);
this.HandleHelperFlowLayoutPanel.ResumeLayout(false);
this.HandleHelperFlowLayoutPanel.PerformLayout();
this.HandleContentTableLayoutPanel.ResumeLayout(false);
this.BypassTableLayoutPanel.ResumeLayout(false);
this.BypassFlowLayoutPanel.ResumeLayout(false);
this.BypassFlowLayoutPanel.PerformLayout();
this.BypassContentTableLayoutPanel.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button ScanButton;
private System.Windows.Forms.ContainerControl containerControl1;
private System.Windows.Forms.Button HandleScanButton;
public System.Windows.Forms.GroupBox ConfigurationGroupBox;
private System.Windows.Forms.Label RemarkLabel;
private System.Windows.Forms.GroupBox ProcessGroupBox;
private System.Windows.Forms.TextBox RemarkTextBox;
private System.Windows.Forms.Button SelectButton;
private System.Windows.Forms.Button HandleSelectButton;
public System.Windows.Forms.Button ControlButton;
private System.Windows.Forms.Label FilenameLabel;
private System.Windows.Forms.TextBox FilenameTextBox;
private RichTextBox RuleRichTextBox;
private RichTextBox HandleRuleRichTextBox;
private Button ValidationButton;
private RichTextBox BypassRuleRichTextBox;
private Button BypassSelectButton;
private Button BypassScanButton;
private Label BypassLabel;
private Label HandleLabel;
private GroupBox OptionsGroupBox;
private SyncGlobalCheckBox ProxyDNSCheckBox;
private SyncGlobalCheckBox HandleDNSCheckBox;
private SyncGlobalCheckBox HandleUDPCheckBox;
private SyncGlobalCheckBox HandleTCPCheckBox;
private CheckBox HandleLANCheckBox;
private CheckBox HandleLoopbackCheckBox;
private TextBox ICMPDelayTextBox;
private TextBox DNSTextBox;
private SyncGlobalCheckBox HandleICMPCheckBox;
private SyncGlobalCheckBox HandleProcDNSCheckBox;
private Label ICMPDelayLabel;
private Label DNSLabel;
private FlowLayoutPanel BypassFlowLayoutPanel;
private FlowLayoutPanel HandleHelperFlowLayoutPanel;
private TableLayoutPanel ConfigurationLayoutPanel;
private Panel NamePanel;
private TableLayoutPanel HandleTableLayoutPanel;
private TableLayoutPanel RuleTableLayoutPanel;
private TableLayoutPanel BypassTableLayoutPanel;
private TableLayoutPanel HandleContentTableLayoutPanel;
private TableLayoutPanel BypassContentTableLayoutPanel;
private SyncGlobalCheckBox HandleChildProcCheckBox;
private Label ModeSpecificOptionsLabel;
}
}

View File

@@ -1,23 +1,24 @@
using Microsoft.WindowsAPICodePack.Dialogs;
using Netch.Controllers;
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Windows.Forms;
using Netch.Controllers;
using Netch.Enums;
using Netch.Models.Modes;
using Netch.Models.Modes.ProcessMode;
using Netch.Properties;
using Netch.Services;
using Netch.Utils;
namespace Netch.Forms.ModeForms
{
public partial class ProcessForm : Form
public partial class ProcessForm : BindingForm
{
/// <summary>
/// 被编辑的模式
/// </summary>
private readonly Mode? _mode;
private readonly bool IsCreateMode;
private readonly Redirector _mode;
/// <summary>
/// 编辑模式
@@ -25,131 +26,141 @@ namespace Netch.Forms.ModeForms
/// <param name="mode">模式</param>
public ProcessForm(Mode? mode = null)
{
if (mode != null && mode.Type is not ModeType.Process)
throw new ArgumentOutOfRangeException();
switch (mode)
{
case Redirector processMode:
IsCreateMode = false;
_mode = processMode;
break;
case null:
IsCreateMode = true;
_mode = new Redirector();
break;
default:
throw new ArgumentOutOfRangeException();
}
InitializeComponent();
Icon = Resources.icon;
CheckForIllegalCrossThreadCalls = false;
InitBindings();
_mode = mode;
var g = Global.Settings.Redirector;
BindTextBox(RemarkTextBox, _ => true, s => _mode.i18NRemark = s, _mode.i18NRemark);
BindSyncGlobalCheckBox(HandleTCPCheckBox, b => _mode.FilterTCP = b, _mode.FilterTCP, g.FilterTCP);
BindSyncGlobalCheckBox(HandleUDPCheckBox, b => _mode.FilterUDP = b, _mode.FilterUDP, g.FilterUDP);
BindSyncGlobalCheckBox(HandleDNSCheckBox, b => _mode.FilterDNS = b, _mode.FilterDNS, g.FilterDNS);
BindTextBox(DNSTextBox, s => IPEndPoint.TryParse(s, out _), s => _mode.DNSHost = s, _mode.DNSHost ?? Constants.DefaultPrimaryDNS);
BindSyncGlobalCheckBox(HandleProcDNSCheckBox, b => _mode.HandleOnlyDNS = b, _mode.HandleOnlyDNS, g.HandleOnlyDNS);
BindSyncGlobalCheckBox(ProxyDNSCheckBox, b => _mode.DNSProxy = b, _mode.DNSProxy, g.DNSProxy);
BindSyncGlobalCheckBox(HandleICMPCheckBox, b => _mode.FilterICMP = b, _mode.FilterICMP, g.FilterICMP);
BindTextBox<int>(ICMPDelayTextBox, s => s >= 0, s => _mode.ICMPDelay = s, _mode.ICMPDelay ?? 10);
BindCheckBox(HandleLoopbackCheckBox, b => _mode.FilterLoopback = b, _mode.FilterLoopback);
BindCheckBox(HandleLANCheckBox, b => _mode.FilterIntranet = b, _mode.FilterIntranet);
BindSyncGlobalCheckBox(HandleChildProcCheckBox, b => _mode.FilterParent = b, _mode.FilterParent, g.FilterParent);
BindTextBox(BypassRuleRichTextBox, s => true, s => _mode.Bypass = s.GetLines().ToList(), string.Join(Constants.EOF, _mode.Bypass));
BindTextBox(HandleRuleRichTextBox, s => true, s => _mode.Handle = s.GetLines().ToList(), string.Join(Constants.EOF, _mode.Handle));
}
#region Model
public IEnumerable<string> Rules => RuleRichTextBox.Lines;
private void RuleAdd(string value)
private void InitBindings()
{
RuleRichTextBox.AppendText($"{value}\n");
DNSTextBox.DataBindings.Add(new Binding("Enabled", HandleDNSCheckBox, "Checked", true));
HandleProcDNSCheckBox.DataBindings.Add(new Binding("Enabled", HandleDNSCheckBox, "Checked", true));
ProxyDNSCheckBox.DataBindings.Add(new Binding("Enabled", HandleDNSCheckBox, "Checked", true));
ICMPDelayTextBox.DataBindings.Add(new Binding("Enabled", HandleICMPCheckBox, "Checked", true));
}
private void RuleAddRange(IEnumerable<string> value)
{
foreach (string s in value)
{
RuleAdd(s);
}
}
#endregion
public void ModeForm_Load(object sender, EventArgs e)
{
if (_mode != null)
if (!IsCreateMode)
{
Text = "Edit Process Mode";
RemarkTextBox.TextChanged -= RemarkTextBox_TextChanged;
RemarkTextBox.Text = _mode.Remark;
FilenameTextBox.Text = _mode.RelativePath;
RuleAddRange(_mode.Content);
RemarkTextBox.Text = _mode.i18NRemark;
FilenameTextBox.Text = ModeService.Instance.GetRelativePath(_mode.FullName);
}
if (!_mode.FullName.EndsWith(".json"))
ControlButton.Enabled = false;
BypassRuleRichTextBox.Text = string.Join(Constants.EOF, _mode.Bypass);
HandleRuleRichTextBox.Text = string.Join(Constants.EOF, _mode.Handle);
i18N.TranslateForm(this);
}
private void SelectButton_Click(object sender, EventArgs e)
{
var dialog = new CommonOpenFileDialog
RichTextBox ruleRichTextBox;
if (sender == HandleSelectButton)
ruleRichTextBox = HandleRuleRichTextBox;
else if (sender == BypassSelectButton)
ruleRichTextBox = BypassRuleRichTextBox;
else
{
IsFolderPicker = true,
Multiselect = true,
Title = i18N.Translate("Select a folder"),
AddToMostRecentlyUsedList = false,
EnsurePathExists = true,
NavigateToShortcut = true
};
if (dialog.ShowDialog(Handle) == CommonFileDialogResult.Ok)
{
foreach (string p in dialog.FileNames)
{
string path = p;
if (!path.EndsWith(@"\"))
path += @"\";
RuleAdd($"^{path.ToRegexString()}");
}
throw new InvalidOperationException();
}
var dialog = new FolderBrowserDialog();
if (dialog.ShowDialog() == DialogResult.OK)
{
var path = dialog.SelectedPath;
if (!path.EndsWith(@"\"))
path += @"\";
AppendText(ruleRichTextBox, $"^{path.ToRegexString()}");
}
}
private static void AppendText(Control ruleTextBox, string value)
{
if (ruleTextBox.Text.Any())
ruleTextBox.Text = ruleTextBox.Text.Trim() + Constants.EOF + value;
else
ruleTextBox.Text = value;
}
public void ControlButton_Click(object sender, EventArgs e)
{
if (!RuleRichTextBox.Lines.Any())
{
MessageBoxX.Show(i18N.Translate("Unable to add empty rule"));
return;
}
if (string.IsNullOrWhiteSpace(RemarkTextBox.Text))
{
MessageBoxX.Show(i18N.Translate("Please enter a mode remark"));
return;
}
if (string.IsNullOrWhiteSpace(FilenameTextBox.Text))
{
MessageBoxX.Show(i18N.Translate("Please enter a mode filename"));
return;
}
SaveBinds();
if (_mode != null)
{
_mode.Remark = RemarkTextBox.Text;
_mode.Content.Clear();
_mode.Content.AddRange(RuleRichTextBox.Lines);
_mode.WriteFile();
MessageBoxX.Show(i18N.Translate("Mode updated successfully"));
}
else
if (IsCreateMode)
{
var relativePath = FilenameTextBox.Text;
var fullName = ModeHelper.GetFullPath(relativePath);
var fullName = ModeService.Instance.GetFullPath(relativePath);
if (File.Exists(fullName))
{
MessageBoxX.Show(i18N.Translate("File already exists.\n Please Change the filename"));
return;
}
var mode = new Mode(fullName)
{
Type = ModeType.Process,
Remark = RemarkTextBox.Text
};
_mode.FullName = fullName;
mode.Content.AddRange(RuleRichTextBox.Lines);
mode.WriteFile();
ModeService.Instance.Add(_mode);
MessageBoxX.Show(i18N.Translate("Mode added successfully"));
}
else
{
_mode.WriteFile();
MessageBoxX.Show(i18N.Translate("Mode updated successfully"));
}
Close();
}
private void RemarkTextBox_TextChanged(object? sender, EventArgs? e)
{
if (!IsHandleCreated)
return;
BeginInvoke(new Action(() =>
{
FilenameTextBox.Text = FilenameTextBox.Text = ModeEditorUtils.GetCustomModeRelativePath(RemarkTextBox.Text);
@@ -158,24 +169,26 @@ namespace Netch.Forms.ModeForms
private void ScanButton_Click(object sender, EventArgs e)
{
var dialog = new CommonOpenFileDialog
RichTextBox ruleRichTextBox;
if (sender == HandleScanButton)
ruleRichTextBox = HandleRuleRichTextBox;
else if (sender == BypassScanButton)
ruleRichTextBox = BypassRuleRichTextBox;
else
{
IsFolderPicker = true,
Multiselect = false,
Title = i18N.Translate("Select a folder"),
AddToMostRecentlyUsedList = false,
EnsurePathExists = true,
NavigateToShortcut = true
};
throw new InvalidOperationException();
}
if (dialog.ShowDialog(Handle) == CommonFileDialogResult.Ok)
var dialog = new FolderBrowserDialog();
if (dialog.ShowDialog() == DialogResult.OK)
{
var path = dialog.FileName;
var path = dialog.SelectedPath;
var list = new List<string>();
const uint maxCount = 50;
try
{
ScanDirectory(path, list);
ScanDirectory(path, list, maxCount);
}
catch
{
@@ -185,13 +198,13 @@ namespace Netch.Forms.ModeForms
return;
}
RuleAddRange(list);
AppendText(ruleRichTextBox, string.Join(Constants.EOF, list));
}
}
private void ScanDirectory(string directory, List<string> list, uint maxCount = 30)
{
foreach (string dir in Directory.GetDirectories(directory))
foreach (var dir in Directory.GetDirectories(directory))
ScanDirectory(dir, list, maxCount);
list.AddRange(
@@ -203,7 +216,7 @@ namespace Netch.Forms.ModeForms
private void ValidationButton_Click(object sender, EventArgs e)
{
if (!NFController.CheckRules(Rules, out var results))
if (!NFController.CheckRules(_mode.Bypass, out var results))
MessageBoxX.Show(NFController.GenerateInvalidRulesMessage(results), LogLevel.WARNING);
else
MessageBoxX.Show("Fine");

View File

@@ -1,64 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
@@ -112,9 +52,9 @@
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -32,166 +32,349 @@ namespace Netch.Forms.ModeForms
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.ConfigurationGroupBox = new System.Windows.Forms.GroupBox();
this.comboBox1 = new System.Windows.Forms.ComboBox();
this.HandleTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.HandleLabel = new System.Windows.Forms.Label();
this.HandleContentTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.HandleRuleRichTextBox = new System.Windows.Forms.RichTextBox();
this.BypassTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.BypassLabel = new System.Windows.Forms.Label();
this.BypassContentTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.BypassRuleRichTextBox = new System.Windows.Forms.RichTextBox();
this.HandleDNSCheckBox = new Netch.Forms.SyncGlobalCheckBox();
this.DNSLabel = new System.Windows.Forms.Label();
this.DNSTextBox = new System.Windows.Forms.TextBox();
this.UseCustomDNSCheckBox = new System.Windows.Forms.CheckBox();
this.RuleTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.OptionsGroupBox = new System.Windows.Forms.GroupBox();
this.RemarkLabel = new System.Windows.Forms.Label();
this.RemarkTextBox = new System.Windows.Forms.TextBox();
this.FilenameLabel = new System.Windows.Forms.Label();
this.FilenameTextBox = new System.Windows.Forms.TextBox();
this.ActionLabel = new System.Windows.Forms.Label();
this.RemarkTextBox = new System.Windows.Forms.TextBox();
this.RemarkLabel = new System.Windows.Forms.Label();
this.containerControl1 = new System.Windows.Forms.ContainerControl();
this.richTextBox1 = new System.Windows.Forms.RichTextBox();
this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
this.DeleteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ControlButton = new System.Windows.Forms.Button();
this.NamePanel = new System.Windows.Forms.Panel();
this.ConfigurationLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.ConfigurationGroupBox = new System.Windows.Forms.GroupBox();
this.HandleTableLayoutPanel.SuspendLayout();
this.HandleContentTableLayoutPanel.SuspendLayout();
this.BypassTableLayoutPanel.SuspendLayout();
this.BypassContentTableLayoutPanel.SuspendLayout();
this.RuleTableLayoutPanel.SuspendLayout();
this.OptionsGroupBox.SuspendLayout();
this.NamePanel.SuspendLayout();
this.ConfigurationLayoutPanel.SuspendLayout();
this.ConfigurationGroupBox.SuspendLayout();
this.containerControl1.SuspendLayout();
this.contextMenuStrip.SuspendLayout();
this.SuspendLayout();
//
// ConfigurationGroupBox
// HandleTableLayoutPanel
//
this.ConfigurationGroupBox.Controls.Add(this.comboBox1);
this.ConfigurationGroupBox.Controls.Add(this.FilenameLabel);
this.ConfigurationGroupBox.Controls.Add(this.FilenameTextBox);
this.ConfigurationGroupBox.Controls.Add(this.ActionLabel);
this.ConfigurationGroupBox.Controls.Add(this.RemarkTextBox);
this.ConfigurationGroupBox.Controls.Add(this.RemarkLabel);
this.ConfigurationGroupBox.Controls.Add(this.containerControl1);
this.ConfigurationGroupBox.Location = new System.Drawing.Point(8, 12);
this.ConfigurationGroupBox.Name = "ConfigurationGroupBox";
this.ConfigurationGroupBox.Size = new System.Drawing.Size(340, 355);
this.ConfigurationGroupBox.TabIndex = 2;
this.ConfigurationGroupBox.TabStop = false;
this.ConfigurationGroupBox.Text = "Configuration";
this.HandleTableLayoutPanel.ColumnCount = 1;
this.HandleTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.HandleTableLayoutPanel.Controls.Add(this.HandleLabel, 0, 0);
this.HandleTableLayoutPanel.Controls.Add(this.HandleContentTableLayoutPanel, 0, 1);
this.HandleTableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.HandleTableLayoutPanel.Location = new System.Drawing.Point(3, 3);
this.HandleTableLayoutPanel.Name = "HandleTableLayoutPanel";
this.HandleTableLayoutPanel.RowCount = 2;
this.HandleTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.HandleTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.HandleTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.HandleTableLayoutPanel.Size = new System.Drawing.Size(455, 424);
this.HandleTableLayoutPanel.TabIndex = 1;
//
// comboBox1
// HandleLabel
//
this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBox1.FormattingEnabled = true;
this.comboBox1.Location = new System.Drawing.Point(84, 49);
this.comboBox1.Name = "comboBox1";
this.comboBox1.Size = new System.Drawing.Size(138, 25);
this.comboBox1.TabIndex = 11;
this.HandleLabel.AutoSize = true;
this.HandleLabel.Location = new System.Drawing.Point(3, 0);
this.HandleLabel.Name = "HandleLabel";
this.HandleLabel.Size = new System.Drawing.Size(81, 17);
this.HandleLabel.TabIndex = 0;
this.HandleLabel.Text = "Handle rules";
//
// FilenameLabel
// HandleContentTableLayoutPanel
//
this.FilenameLabel.AutoSize = true;
this.FilenameLabel.Location = new System.Drawing.Point(12, 79);
this.FilenameLabel.Name = "FilenameLabel";
this.FilenameLabel.Size = new System.Drawing.Size(59, 17);
this.FilenameLabel.TabIndex = 6;
this.FilenameLabel.Text = "Filename";
this.HandleContentTableLayoutPanel.ColumnCount = 1;
this.HandleContentTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.HandleContentTableLayoutPanel.Controls.Add(this.HandleRuleRichTextBox, 0, 0);
this.HandleContentTableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.HandleContentTableLayoutPanel.Location = new System.Drawing.Point(3, 20);
this.HandleContentTableLayoutPanel.Name = "HandleContentTableLayoutPanel";
this.HandleContentTableLayoutPanel.RowCount = 1;
this.HandleContentTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.HandleContentTableLayoutPanel.Size = new System.Drawing.Size(449, 401);
this.HandleContentTableLayoutPanel.TabIndex = 1;
//
// FilenameTextBox
// HandleRuleRichTextBox
//
this.FilenameTextBox.Location = new System.Drawing.Point(84, 76);
this.FilenameTextBox.Name = "FilenameTextBox";
this.FilenameTextBox.ReadOnly = true;
this.FilenameTextBox.Size = new System.Drawing.Size(250, 23);
this.FilenameTextBox.TabIndex = 5;
this.HandleRuleRichTextBox.DetectUrls = false;
this.HandleRuleRichTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.HandleRuleRichTextBox.Location = new System.Drawing.Point(3, 3);
this.HandleRuleRichTextBox.Name = "HandleRuleRichTextBox";
this.HandleRuleRichTextBox.Size = new System.Drawing.Size(443, 395);
this.HandleRuleRichTextBox.TabIndex = 0;
this.HandleRuleRichTextBox.Text = "";
this.HandleRuleRichTextBox.WordWrap = false;
//
// ActionLabel
// BypassTableLayoutPanel
//
this.ActionLabel.AutoSize = true;
this.ActionLabel.Location = new System.Drawing.Point(12, 52);
this.ActionLabel.Name = "ActionLabel";
this.ActionLabel.Size = new System.Drawing.Size(44, 17);
this.ActionLabel.TabIndex = 0;
this.ActionLabel.Text = "Action";
this.BypassTableLayoutPanel.ColumnCount = 1;
this.BypassTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.BypassTableLayoutPanel.Controls.Add(this.BypassLabel, 0, 0);
this.BypassTableLayoutPanel.Controls.Add(this.BypassContentTableLayoutPanel, 0, 1);
this.BypassTableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.BypassTableLayoutPanel.Location = new System.Drawing.Point(464, 3);
this.BypassTableLayoutPanel.Name = "BypassTableLayoutPanel";
this.BypassTableLayoutPanel.RowCount = 2;
this.BypassTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.BypassTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.BypassTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.BypassTableLayoutPanel.Size = new System.Drawing.Size(455, 424);
this.BypassTableLayoutPanel.TabIndex = 2;
//
// RemarkTextBox
// BypassLabel
//
this.RemarkTextBox.Location = new System.Drawing.Point(84, 22);
this.RemarkTextBox.Name = "RemarkTextBox";
this.RemarkTextBox.Size = new System.Drawing.Size(250, 23);
this.RemarkTextBox.TabIndex = 1;
this.RemarkTextBox.TextChanged += new System.EventHandler(this.RemarkTextBox_TextChanged);
this.BypassLabel.AutoSize = true;
this.BypassLabel.Location = new System.Drawing.Point(3, 0);
this.BypassLabel.Name = "BypassLabel";
this.BypassLabel.Size = new System.Drawing.Size(81, 17);
this.BypassLabel.TabIndex = 0;
this.BypassLabel.Text = "Bypass rules";
//
// BypassContentTableLayoutPanel
//
this.BypassContentTableLayoutPanel.ColumnCount = 1;
this.BypassContentTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.BypassContentTableLayoutPanel.Controls.Add(this.BypassRuleRichTextBox, 0, 0);
this.BypassContentTableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.BypassContentTableLayoutPanel.Location = new System.Drawing.Point(3, 20);
this.BypassContentTableLayoutPanel.Name = "BypassContentTableLayoutPanel";
this.BypassContentTableLayoutPanel.RowCount = 1;
this.BypassContentTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.BypassContentTableLayoutPanel.Size = new System.Drawing.Size(449, 401);
this.BypassContentTableLayoutPanel.TabIndex = 1;
//
// BypassRuleRichTextBox
//
this.BypassRuleRichTextBox.DetectUrls = false;
this.BypassRuleRichTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.BypassRuleRichTextBox.Location = new System.Drawing.Point(3, 3);
this.BypassRuleRichTextBox.Name = "BypassRuleRichTextBox";
this.BypassRuleRichTextBox.Size = new System.Drawing.Size(443, 395);
this.BypassRuleRichTextBox.TabIndex = 0;
this.BypassRuleRichTextBox.Text = "";
this.BypassRuleRichTextBox.WordWrap = false;
//
// HandleDNSCheckBox
//
this.HandleDNSCheckBox.AutoCheck = false;
this.HandleDNSCheckBox.AutoSize = true;
this.HandleDNSCheckBox.BackColor = System.Drawing.Color.Yellow;
this.HandleDNSCheckBox.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic))), System.Drawing.GraphicsUnit.Point);
this.HandleDNSCheckBox.GlobalValue = false;
this.HandleDNSCheckBox.Location = new System.Drawing.Point(8, 24);
this.HandleDNSCheckBox.Name = "HandleDNSCheckBox";
this.HandleDNSCheckBox.Size = new System.Drawing.Size(203, 21);
this.HandleDNSCheckBox.SyncGlobal = false;
this.HandleDNSCheckBox.TabIndex = 2;
this.HandleDNSCheckBox.Text = "Handle DNS (DNS hijacking)";
this.HandleDNSCheckBox.ThreeState = true;
this.HandleDNSCheckBox.UseVisualStyleBackColor = true;
this.HandleDNSCheckBox.Value = false;
//
// DNSLabel
//
this.DNSLabel.AutoSize = true;
this.DNSLabel.Location = new System.Drawing.Point(176, 56);
this.DNSLabel.Name = "DNSLabel";
this.DNSLabel.Size = new System.Drawing.Size(34, 17);
this.DNSLabel.TabIndex = 3;
this.DNSLabel.Text = "DNS";
//
// DNSTextBox
//
this.DNSTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", this.UseCustomDNSCheckBox, "Checked", true));
this.DNSTextBox.Location = new System.Drawing.Point(224, 56);
this.DNSTextBox.Name = "DNSTextBox";
this.DNSTextBox.Size = new System.Drawing.Size(184, 23);
this.DNSTextBox.TabIndex = 4;
this.DNSTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// UseCustomDNSCheckBox
//
this.UseCustomDNSCheckBox.AutoSize = true;
this.UseCustomDNSCheckBox.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", this.HandleDNSCheckBox, "Checked", true));
this.UseCustomDNSCheckBox.Location = new System.Drawing.Point(8, 56);
this.UseCustomDNSCheckBox.Name = "UseCustomDNSCheckBox";
this.UseCustomDNSCheckBox.Size = new System.Drawing.Size(125, 21);
this.UseCustomDNSCheckBox.TabIndex = 7;
this.UseCustomDNSCheckBox.Text = "Use custom DNS";
this.UseCustomDNSCheckBox.ThreeState = true;
this.UseCustomDNSCheckBox.UseVisualStyleBackColor = true;
//
// RuleTableLayoutPanel
//
this.RuleTableLayoutPanel.ColumnCount = 2;
this.RuleTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.RuleTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.RuleTableLayoutPanel.Controls.Add(this.HandleTableLayoutPanel, 0, 0);
this.RuleTableLayoutPanel.Controls.Add(this.BypassTableLayoutPanel, 1, 0);
this.RuleTableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.RuleTableLayoutPanel.Location = new System.Drawing.Point(3, 206);
this.RuleTableLayoutPanel.Name = "RuleTableLayoutPanel";
this.RuleTableLayoutPanel.RowCount = 1;
this.RuleTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.RuleTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 430F));
this.RuleTableLayoutPanel.Size = new System.Drawing.Size(922, 430);
this.RuleTableLayoutPanel.TabIndex = 2;
//
// OptionsGroupBox
//
this.OptionsGroupBox.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.OptionsGroupBox.Controls.Add(this.HandleDNSCheckBox);
this.OptionsGroupBox.Controls.Add(this.UseCustomDNSCheckBox);
this.OptionsGroupBox.Controls.Add(this.DNSLabel);
this.OptionsGroupBox.Controls.Add(this.DNSTextBox);
this.OptionsGroupBox.Location = new System.Drawing.Point(15, 81);
this.OptionsGroupBox.Name = "OptionsGroupBox";
this.OptionsGroupBox.Size = new System.Drawing.Size(898, 119);
this.OptionsGroupBox.TabIndex = 1;
this.OptionsGroupBox.TabStop = false;
this.OptionsGroupBox.Visible = false;
//
// RemarkLabel
//
this.RemarkLabel.AutoSize = true;
this.RemarkLabel.Location = new System.Drawing.Point(12, 25);
this.RemarkLabel.Location = new System.Drawing.Point(8, 8);
this.RemarkLabel.Name = "RemarkLabel";
this.RemarkLabel.Size = new System.Drawing.Size(53, 17);
this.RemarkLabel.TabIndex = 0;
this.RemarkLabel.Text = "Remark";
//
// containerControl1
// RemarkTextBox
//
this.containerControl1.Controls.Add(this.richTextBox1);
this.containerControl1.Location = new System.Drawing.Point(6, 103);
this.containerControl1.Name = "containerControl1";
this.containerControl1.Size = new System.Drawing.Size(328, 246);
this.containerControl1.TabIndex = 10;
this.containerControl1.Text = "containerControl1";
this.RemarkTextBox.Location = new System.Drawing.Point(72, 8);
this.RemarkTextBox.Name = "RemarkTextBox";
this.RemarkTextBox.Size = new System.Drawing.Size(341, 23);
this.RemarkTextBox.TabIndex = 1;
//
// richTextBox1
// FilenameLabel
//
this.richTextBox1.Dock = System.Windows.Forms.DockStyle.Fill;
this.richTextBox1.Location = new System.Drawing.Point(0, 0);
this.richTextBox1.Name = "richTextBox1";
this.richTextBox1.Size = new System.Drawing.Size(328, 246);
this.richTextBox1.TabIndex = 0;
this.richTextBox1.Text = "";
this.FilenameLabel.AutoSize = true;
this.FilenameLabel.Location = new System.Drawing.Point(8, 40);
this.FilenameLabel.Name = "FilenameLabel";
this.FilenameLabel.Size = new System.Drawing.Size(59, 17);
this.FilenameLabel.TabIndex = 2;
this.FilenameLabel.Text = "Filename";
//
// contextMenuStrip
// FilenameTextBox
//
this.contextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.DeleteToolStripMenuItem});
this.contextMenuStrip.Name = "contextMenuStrip";
this.contextMenuStrip.Size = new System.Drawing.Size(114, 26);
//
// DeleteToolStripMenuItem
//
this.DeleteToolStripMenuItem.Name = "DeleteToolStripMenuItem";
this.DeleteToolStripMenuItem.Size = new System.Drawing.Size(113, 22);
this.DeleteToolStripMenuItem.Text = "Delete";
this.FilenameTextBox.Location = new System.Drawing.Point(72, 40);
this.FilenameTextBox.Name = "FilenameTextBox";
this.FilenameTextBox.ReadOnly = true;
this.FilenameTextBox.Size = new System.Drawing.Size(341, 23);
this.FilenameTextBox.TabIndex = 3;
//
// ControlButton
//
this.ControlButton.Location = new System.Drawing.Point(273, 373);
this.ControlButton.Location = new System.Drawing.Point(424, 40);
this.ControlButton.Name = "ControlButton";
this.ControlButton.Size = new System.Drawing.Size(75, 23);
this.ControlButton.TabIndex = 3;
this.ControlButton.TabIndex = 4;
this.ControlButton.Text = "Save";
this.ControlButton.UseVisualStyleBackColor = true;
this.ControlButton.Click += new System.EventHandler(this.ControlButton_Click);
//
// Route
// NamePanel
//
this.NamePanel.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.NamePanel.Controls.Add(this.RemarkLabel);
this.NamePanel.Controls.Add(this.RemarkTextBox);
this.NamePanel.Controls.Add(this.FilenameLabel);
this.NamePanel.Controls.Add(this.FilenameTextBox);
this.NamePanel.Controls.Add(this.ControlButton);
this.NamePanel.Location = new System.Drawing.Point(208, 3);
this.NamePanel.Name = "NamePanel";
this.NamePanel.Size = new System.Drawing.Size(512, 72);
this.NamePanel.TabIndex = 0;
//
// ConfigurationLayoutPanel
//
this.ConfigurationLayoutPanel.ColumnCount = 1;
this.ConfigurationLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.ConfigurationLayoutPanel.Controls.Add(this.NamePanel, 0, 0);
this.ConfigurationLayoutPanel.Controls.Add(this.OptionsGroupBox, 0, 1);
this.ConfigurationLayoutPanel.Controls.Add(this.RuleTableLayoutPanel, 0, 2);
this.ConfigurationLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.ConfigurationLayoutPanel.Location = new System.Drawing.Point(3, 19);
this.ConfigurationLayoutPanel.Name = "ConfigurationLayoutPanel";
this.ConfigurationLayoutPanel.RowCount = 3;
this.ConfigurationLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.ConfigurationLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.ConfigurationLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.ConfigurationLayoutPanel.Size = new System.Drawing.Size(928, 639);
this.ConfigurationLayoutPanel.TabIndex = 0;
//
// ConfigurationGroupBox
//
this.ConfigurationGroupBox.Controls.Add(this.ConfigurationLayoutPanel);
this.ConfigurationGroupBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.ConfigurationGroupBox.Location = new System.Drawing.Point(0, 0);
this.ConfigurationGroupBox.Name = "ConfigurationGroupBox";
this.ConfigurationGroupBox.Size = new System.Drawing.Size(934, 661);
this.ConfigurationGroupBox.TabIndex = 1;
this.ConfigurationGroupBox.TabStop = false;
this.ConfigurationGroupBox.Text = "Configuration";
//
// RouteForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(356, 419);
this.ClientSize = new System.Drawing.Size(934, 661);
this.Controls.Add(this.ConfigurationGroupBox);
this.Controls.Add(this.ControlButton);
this.MinimumSize = new System.Drawing.Size(950, 700);
this.Name = "RouteForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Create Route Table Rule";
this.Load += new System.EventHandler(this.Route_Load);
this.HandleTableLayoutPanel.ResumeLayout(false);
this.HandleTableLayoutPanel.PerformLayout();
this.HandleContentTableLayoutPanel.ResumeLayout(false);
this.BypassTableLayoutPanel.ResumeLayout(false);
this.BypassTableLayoutPanel.PerformLayout();
this.BypassContentTableLayoutPanel.ResumeLayout(false);
this.RuleTableLayoutPanel.ResumeLayout(false);
this.OptionsGroupBox.ResumeLayout(false);
this.OptionsGroupBox.PerformLayout();
this.NamePanel.ResumeLayout(false);
this.NamePanel.PerformLayout();
this.ConfigurationLayoutPanel.ResumeLayout(false);
this.ConfigurationGroupBox.ResumeLayout(false);
this.ConfigurationGroupBox.PerformLayout();
this.containerControl1.ResumeLayout(false);
this.contextMenuStrip.ResumeLayout(false);
this.ResumeLayout(false);
}
public System.Windows.Forms.GroupBox ConfigurationGroupBox;
private System.Windows.Forms.ContainerControl containerControl1;
private System.Windows.Forms.ContextMenuStrip contextMenuStrip;
public System.Windows.Forms.Button ControlButton;
private System.Windows.Forms.ToolStripMenuItem DeleteToolStripMenuItem;
private System.Windows.Forms.Label FilenameLabel;
private System.Windows.Forms.TextBox FilenameTextBox;
private System.Windows.Forms.Label RemarkLabel;
private System.Windows.Forms.TextBox RemarkTextBox;
private System.Windows.Forms.RichTextBox richTextBox1;
#endregion
private System.Windows.Forms.ComboBox comboBox1;
private System.Windows.Forms.Label ActionLabel;
private System.Windows.Forms.TableLayoutPanel HandleTableLayoutPanel;
private System.Windows.Forms.Label HandleLabel;
private System.Windows.Forms.TableLayoutPanel HandleContentTableLayoutPanel;
private System.Windows.Forms.RichTextBox HandleRuleRichTextBox;
private System.Windows.Forms.TableLayoutPanel BypassTableLayoutPanel;
private System.Windows.Forms.Label BypassLabel;
private System.Windows.Forms.TableLayoutPanel BypassContentTableLayoutPanel;
private System.Windows.Forms.RichTextBox BypassRuleRichTextBox;
private SyncGlobalCheckBox HandleDNSCheckBox;
private System.Windows.Forms.Label DNSLabel;
private System.Windows.Forms.TextBox DNSTextBox;
private System.Windows.Forms.TableLayoutPanel RuleTableLayoutPanel;
private System.Windows.Forms.GroupBox OptionsGroupBox;
private System.Windows.Forms.Label RemarkLabel;
private System.Windows.Forms.TextBox RemarkTextBox;
private System.Windows.Forms.Label FilenameLabel;
private System.Windows.Forms.TextBox FilenameTextBox;
private System.Windows.Forms.Panel NamePanel;
private System.Windows.Forms.TableLayoutPanel ConfigurationLayoutPanel;
private System.Windows.Forms.CheckBox UseCustomDNSCheckBox;
private System.Windows.Forms.Button ControlButton;
private System.Windows.Forms.GroupBox ConfigurationGroupBox;
}
}

View File

@@ -1,47 +1,61 @@
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
using System;
using System;
using System.IO;
using System.Windows.Forms;
using Netch.Enums;
using System.Linq;
using Netch.Models.Modes;
using Netch.Models.Modes.TunMode;
using Netch.Properties;
using Netch.Services;
using Netch.Utils;
namespace Netch.Forms.ModeForms
{
public partial class RouteForm : Form
public partial class RouteForm : BindingForm
{
private readonly TagItem<ModeType>[] _items =
{ new(ModeType.ProxyRuleIPs, "Proxy Rule IPs"), new(ModeType.BypassRuleIPs, "Bypass Rule IPs") };
private readonly bool IsCreateMode;
private readonly Mode? _mode;
private readonly TunMode _mode;
public RouteForm(Mode? mode = null)
{
if (mode != null && mode.Type is not (ModeType.ProxyRuleIPs or ModeType.BypassRuleIPs))
throw new ArgumentOutOfRangeException();
_mode = mode;
switch (mode)
{
case null:
IsCreateMode = true;
_mode = new TunMode();
break;
case TunMode tunMode:
IsCreateMode = false;
_mode = tunMode;
break;
default:
throw new ArgumentOutOfRangeException();
}
InitializeComponent();
Icon = Resources.icon;
comboBox1.DataSource = _items;
comboBox1.ValueMember = nameof(TagItem<int>.Value);
comboBox1.DisplayMember = nameof(TagItem<int>.Text);
BindTextBox(RemarkTextBox, _ => true, s => _mode.i18NRemark = s, _mode.i18NRemark);
// TODO Options Not implemented
BindTextBox(BypassRuleRichTextBox, s => true, s => _mode.Bypass = s.GetLines().ToList(), string.Join(Constants.EOF, _mode.Bypass));
BindTextBox(HandleRuleRichTextBox, s => true, s => _mode.Handle = s.GetLines().ToList(), string.Join(Constants.EOF, _mode.Handle));
}
private void Route_Load(object sender, EventArgs e)
{
if (_mode != null)
if (!IsCreateMode)
{
Text = "Edit Route Table Rule";
RemarkTextBox.TextChanged -= RemarkTextBox_TextChanged;
RemarkTextBox.Text = _mode.Remark;
comboBox1.SelectedValue = _mode.Type; // ComboBox SelectedValue worked after ctor
FilenameTextBox.Text = _mode.RelativePath;
richTextBox1.Lines = _mode.Content.ToArray();
RemarkTextBox.Text = _mode.i18NRemark;
FilenameTextBox.Text = ModeService.Instance.GetRelativePath(_mode.FullName);
}
if (!_mode.FullName.EndsWith(".json"))
ControlButton.Enabled = false;
i18N.TranslateForm(this);
}
@@ -53,50 +67,33 @@ namespace Netch.Forms.ModeForms
return;
}
if (string.IsNullOrWhiteSpace(FilenameTextBox.Text))
{
MessageBoxX.Show(i18N.Translate("Please enter a mode filename"));
return;
}
if (_mode != null)
{
_mode.Remark = RemarkTextBox.Text;
_mode.Content.Clear();
_mode.Content.AddRange(richTextBox1.Lines);
_mode.Type = (ModeType)comboBox1.SelectedValue;
_mode.WriteFile();
MessageBoxX.Show(i18N.Translate("Mode updated successfully"));
}
else
if (IsCreateMode)
{
var relativePath = FilenameTextBox.Text;
var fullName = ModeHelper.GetFullPath(relativePath);
var fullName = ModeService.Instance.GetFullPath(relativePath);
if (File.Exists(fullName))
{
MessageBoxX.Show(i18N.Translate("File already exists.\n Please Change the filename"));
return;
}
var mode = new Mode(fullName)
{
Type = (ModeType)comboBox1.SelectedValue,
Remark = RemarkTextBox.Text
};
_mode.FullName = fullName;
mode.Content.AddRange(richTextBox1.Lines);
mode.WriteFile();
ModeService.Instance.Add(_mode);
MessageBoxX.Show(i18N.Translate("Mode added successfully"));
}
else
{
_mode.WriteFile();
MessageBoxX.Show(i18N.Translate("Mode updated successfully"));
}
Close();
}
private void RemarkTextBox_TextChanged(object? sender, EventArgs? e)
{
BeginInvoke(new Action(() => { FilenameTextBox.Text = ModeEditorUtils.GetCustomModeRelativePath(RemarkTextBox.Text); }));
FilenameTextBox.Text = ModeEditorUtils.GetCustomModeRelativePath(RemarkTextBox.Text);
}
}
}

View File

@@ -51,13 +51,16 @@ namespace Netch.Forms
this.LanguageLabel = new System.Windows.Forms.Label();
this.LanguageComboBox = new System.Windows.Forms.ComboBox();
this.NFTabPage = new System.Windows.Forms.TabPage();
this.ProcessFilterProtocolLabel = new System.Windows.Forms.Label();
this.ProcessFilterProtocolComboBox = new System.Windows.Forms.ComboBox();
this.FilterTCPCheckBox = new System.Windows.Forms.CheckBox();
this.FilterUDPCheckBox = new System.Windows.Forms.CheckBox();
this.FilterICMPCheckBox = new System.Windows.Forms.CheckBox();
this.DNSHijackLabel = new System.Windows.Forms.Label();
this.ICMPDelayLabel = new System.Windows.Forms.Label();
this.ICMPDelayTextBox = new System.Windows.Forms.TextBox();
this.DNSHijackCheckBox = new System.Windows.Forms.CheckBox();
this.FilterDNSCheckBox = new System.Windows.Forms.CheckBox();
this.DNSHijackHostTextBox = new System.Windows.Forms.TextBox();
this.DNSProxyCheckBox = new System.Windows.Forms.CheckBox();
this.HandleProcDNSCheckBox = new System.Windows.Forms.CheckBox();
this.ChildProcessHandleCheckBox = new System.Windows.Forms.CheckBox();
this.WinTUNTabPage = new System.Windows.Forms.TabPage();
this.WinTUNGroupBox = new System.Windows.Forms.GroupBox();
@@ -109,7 +112,6 @@ namespace Netch.Forms
this.AioDNSListenPortTextBox = new System.Windows.Forms.TextBox();
this.ControlButton = new System.Windows.Forms.Button();
this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
this.DNSHijackLabel = new System.Windows.Forms.Label();
this.TabControl.SuspendLayout();
this.GeneralTabPage.SuspendLayout();
this.PortGroupBox.SuspendLayout();
@@ -322,14 +324,16 @@ namespace Netch.Forms
// NFTabPage
//
this.NFTabPage.BackColor = System.Drawing.SystemColors.ButtonFace;
this.NFTabPage.Controls.Add(this.ProcessFilterProtocolLabel);
this.NFTabPage.Controls.Add(this.ProcessFilterProtocolComboBox);
this.NFTabPage.Controls.Add(this.FilterTCPCheckBox);
this.NFTabPage.Controls.Add(this.FilterUDPCheckBox);
this.NFTabPage.Controls.Add(this.FilterICMPCheckBox);
this.NFTabPage.Controls.Add(this.DNSHijackLabel);
this.NFTabPage.Controls.Add(this.ICMPDelayLabel);
this.NFTabPage.Controls.Add(this.ICMPDelayTextBox);
this.NFTabPage.Controls.Add(this.DNSHijackCheckBox);
this.NFTabPage.Controls.Add(this.FilterDNSCheckBox);
this.NFTabPage.Controls.Add(this.DNSHijackHostTextBox);
this.NFTabPage.Controls.Add(this.HandleProcDNSCheckBox);
this.NFTabPage.Controls.Add(this.DNSProxyCheckBox);
this.NFTabPage.Controls.Add(this.ChildProcessHandleCheckBox);
this.NFTabPage.Location = new System.Drawing.Point(4, 29);
this.NFTabPage.Name = "NFTabPage";
@@ -338,79 +342,112 @@ namespace Netch.Forms
this.NFTabPage.TabIndex = 1;
this.NFTabPage.Text = "Process Mode";
//
// ProcessFilterProtocolLabel
// FilterTCPCheckBox
//
this.ProcessFilterProtocolLabel.AutoSize = true;
this.ProcessFilterProtocolLabel.Location = new System.Drawing.Point(30, 20);
this.ProcessFilterProtocolLabel.Name = "ProcessFilterProtocolLabel";
this.ProcessFilterProtocolLabel.Size = new System.Drawing.Size(89, 17);
this.ProcessFilterProtocolLabel.TabIndex = 0;
this.ProcessFilterProtocolLabel.Text = "Filter Protocol";
this.FilterTCPCheckBox.AutoSize = true;
this.FilterTCPCheckBox.Location = new System.Drawing.Point(16, 16);
this.FilterTCPCheckBox.Name = "FilterTCPCheckBox";
this.FilterTCPCheckBox.Size = new System.Drawing.Size(81, 21);
this.FilterTCPCheckBox.TabIndex = 1;
this.FilterTCPCheckBox.Text = "Handle TCP";
this.FilterTCPCheckBox.UseVisualStyleBackColor = true;
//
// ProcessFilterProtocolComboBox
// FilterUDPCheckBox
//
this.ProcessFilterProtocolComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.ProcessFilterProtocolComboBox.FormattingEnabled = true;
this.ProcessFilterProtocolComboBox.Location = new System.Drawing.Point(237, 17);
this.ProcessFilterProtocolComboBox.Name = "ProcessFilterProtocolComboBox";
this.ProcessFilterProtocolComboBox.Size = new System.Drawing.Size(98, 25);
this.ProcessFilterProtocolComboBox.TabIndex = 1;
this.FilterUDPCheckBox.AutoSize = true;
this.FilterUDPCheckBox.Location = new System.Drawing.Point(216, 16);
this.FilterUDPCheckBox.Name = "FilterUDPCheckBox";
this.FilterUDPCheckBox.Size = new System.Drawing.Size(84, 21);
this.FilterUDPCheckBox.TabIndex = 2;
this.FilterUDPCheckBox.Text = "Handle UDP";
this.FilterUDPCheckBox.UseVisualStyleBackColor = true;
//
// FilterICMPCheckBox
//
this.FilterICMPCheckBox.AutoSize = true;
this.FilterICMPCheckBox.Location = new System.Drawing.Point(15, 50);
this.FilterICMPCheckBox.Location = new System.Drawing.Point(16, 48);
this.FilterICMPCheckBox.Name = "FilterICMPCheckBox";
this.FilterICMPCheckBox.Size = new System.Drawing.Size(90, 21);
this.FilterICMPCheckBox.TabIndex = 2;
this.FilterICMPCheckBox.Text = "Filter ICMP";
this.FilterICMPCheckBox.TabIndex = 3;
this.FilterICMPCheckBox.Text = "Handle ICMP";
this.FilterICMPCheckBox.UseVisualStyleBackColor = true;
//
// DNSHijackLabel
//
this.DNSHijackLabel.AutoSize = true;
this.DNSHijackLabel.Location = new System.Drawing.Point(48, 144);
this.DNSHijackLabel.Name = "DNSHijackLabel";
this.DNSHijackLabel.Size = new System.Drawing.Size(34, 17);
this.DNSHijackLabel.TabIndex = 3;
this.DNSHijackLabel.Text = "DNS";
//
// ICMPDelayLabel
//
this.ICMPDelayLabel.AutoSize = true;
this.ICMPDelayLabel.Location = new System.Drawing.Point(65, 80);
this.ICMPDelayLabel.Location = new System.Drawing.Point(48, 80);
this.ICMPDelayLabel.Name = "ICMPDelayLabel";
this.ICMPDelayLabel.Size = new System.Drawing.Size(100, 17);
this.ICMPDelayLabel.TabIndex = 3;
this.ICMPDelayLabel.Text = "ICMP Delay(ms)";
this.ICMPDelayLabel.Text = "ICMP delay(ms)";
//
// ICMPDelayTextBox
//
this.ICMPDelayTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", this.FilterICMPCheckBox, "Checked", true));
this.ICMPDelayTextBox.Location = new System.Drawing.Point(237, 77);
this.ICMPDelayTextBox.Location = new System.Drawing.Point(216, 80);
this.ICMPDelayTextBox.Name = "ICMPDelayTextBox";
this.ICMPDelayTextBox.Size = new System.Drawing.Size(98, 23);
this.ICMPDelayTextBox.TabIndex = 4;
this.ICMPDelayTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// DNSHijackCheckBox
// FilterDNSCheckBox
//
this.DNSHijackCheckBox.AutoSize = true;
this.DNSHijackCheckBox.Location = new System.Drawing.Point(15, 110);
this.DNSHijackCheckBox.Name = "DNSHijackCheckBox";
this.DNSHijackCheckBox.Size = new System.Drawing.Size(92, 21);
this.DNSHijackCheckBox.TabIndex = 5;
this.DNSHijackCheckBox.Text = "DNS Hijack";
this.DNSHijackCheckBox.UseVisualStyleBackColor = true;
this.FilterDNSCheckBox.AutoSize = true;
this.FilterDNSCheckBox.Location = new System.Drawing.Point(16, 112);
this.FilterDNSCheckBox.Name = "FilterDNSCheckBox";
this.FilterDNSCheckBox.Size = new System.Drawing.Size(85, 21);
this.FilterDNSCheckBox.TabIndex = 5;
this.FilterDNSCheckBox.Text = "Handle DNS (DNS hijacking)";
this.FilterDNSCheckBox.UseVisualStyleBackColor = true;
//
// DNSHijackHostTextBox
//
this.DNSHijackHostTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", this.DNSHijackCheckBox, "Checked", true));
this.DNSHijackHostTextBox.Location = new System.Drawing.Point(237, 138);
this.DNSHijackHostTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", this.FilterDNSCheckBox, "Checked", true));
this.DNSHijackHostTextBox.Location = new System.Drawing.Point(216, 144);
this.DNSHijackHostTextBox.Name = "DNSHijackHostTextBox";
this.DNSHijackHostTextBox.Size = new System.Drawing.Size(191, 23);
this.DNSHijackHostTextBox.TabIndex = 6;
this.DNSHijackHostTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// DNSProxyCheckBox
//
this.DNSProxyCheckBox.AutoSize = true;
this.DNSProxyCheckBox.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", this.FilterDNSCheckBox, "Checked", true));
this.DNSProxyCheckBox.Location = new System.Drawing.Point(16, 208);
this.DNSProxyCheckBox.Name = "DNSProxyCheckBox";
this.DNSProxyCheckBox.Size = new System.Drawing.Size(184, 21);
this.DNSProxyCheckBox.TabIndex = 8;
this.DNSProxyCheckBox.Text = "Handle DNS through proxy";
this.DNSProxyCheckBox.UseVisualStyleBackColor = true;
//
// HandleProcDNSCheckBox
//
this.HandleProcDNSCheckBox.AutoSize = true;
this.HandleProcDNSCheckBox.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", this.FilterDNSCheckBox, "Checked", true));
this.HandleProcDNSCheckBox.Location = new System.Drawing.Point(16, 176);
this.HandleProcDNSCheckBox.Name = "HandleProcDNSCheckBox";
this.HandleProcDNSCheckBox.Size = new System.Drawing.Size(203, 21);
this.HandleProcDNSCheckBox.TabIndex = 7;
this.HandleProcDNSCheckBox.Text = "Handle handled process's DNS";
this.HandleProcDNSCheckBox.UseVisualStyleBackColor = true;
//
// ChildProcessHandleCheckBox
//
this.ChildProcessHandleCheckBox.AutoSize = true;
this.ChildProcessHandleCheckBox.Location = new System.Drawing.Point(15, 170);
this.ChildProcessHandleCheckBox.Location = new System.Drawing.Point(16, 240);
this.ChildProcessHandleCheckBox.Name = "ChildProcessHandleCheckBox";
this.ChildProcessHandleCheckBox.Size = new System.Drawing.Size(150, 21);
this.ChildProcessHandleCheckBox.TabIndex = 7;
this.ChildProcessHandleCheckBox.Text = "Child Process Handle";
this.ChildProcessHandleCheckBox.TabIndex = 9;
this.ChildProcessHandleCheckBox.Text = "Handle child process";
this.ChildProcessHandleCheckBox.UseVisualStyleBackColor = true;
//
// WinTUNTabPage
@@ -519,7 +556,7 @@ namespace Netch.Forms
this.UseCustomDNSCheckBox.Name = "UseCustomDNSCheckBox";
this.UseCustomDNSCheckBox.Size = new System.Drawing.Size(127, 21);
this.UseCustomDNSCheckBox.TabIndex = 8;
this.UseCustomDNSCheckBox.Text = "Use Custom DNS";
this.UseCustomDNSCheckBox.Text = "Use custom DNS";
this.UseCustomDNSCheckBox.UseVisualStyleBackColor = true;
this.UseCustomDNSCheckBox.Click += new System.EventHandler(this.TUNTAPUseCustomDNSCheckBox_CheckedChanged);
//
@@ -743,7 +780,7 @@ namespace Netch.Forms
// ExitWhenClosedCheckBox
//
this.ExitWhenClosedCheckBox.AutoSize = true;
this.ExitWhenClosedCheckBox.Location = new System.Drawing.Point(6, 6);
this.ExitWhenClosedCheckBox.Location = new System.Drawing.Point(16, 16);
this.ExitWhenClosedCheckBox.Name = "ExitWhenClosedCheckBox";
this.ExitWhenClosedCheckBox.Size = new System.Drawing.Size(123, 21);
this.ExitWhenClosedCheckBox.TabIndex = 0;
@@ -754,7 +791,7 @@ namespace Netch.Forms
// StopWhenExitedCheckBox
//
this.StopWhenExitedCheckBox.AutoSize = true;
this.StopWhenExitedCheckBox.Location = new System.Drawing.Point(200, 6);
this.StopWhenExitedCheckBox.Location = new System.Drawing.Point(224, 18);
this.StopWhenExitedCheckBox.Name = "StopWhenExitedCheckBox";
this.StopWhenExitedCheckBox.Size = new System.Drawing.Size(127, 21);
this.StopWhenExitedCheckBox.TabIndex = 1;
@@ -765,7 +802,7 @@ namespace Netch.Forms
// StartWhenOpenedCheckBox
//
this.StartWhenOpenedCheckBox.AutoSize = true;
this.StartWhenOpenedCheckBox.Location = new System.Drawing.Point(6, 28);
this.StartWhenOpenedCheckBox.Location = new System.Drawing.Point(16, 48);
this.StartWhenOpenedCheckBox.Name = "StartWhenOpenedCheckBox";
this.StartWhenOpenedCheckBox.Size = new System.Drawing.Size(137, 21);
this.StartWhenOpenedCheckBox.TabIndex = 2;
@@ -776,7 +813,7 @@ namespace Netch.Forms
// MinimizeWhenStartedCheckBox
//
this.MinimizeWhenStartedCheckBox.AutoSize = true;
this.MinimizeWhenStartedCheckBox.Location = new System.Drawing.Point(200, 28);
this.MinimizeWhenStartedCheckBox.Location = new System.Drawing.Point(224, 48);
this.MinimizeWhenStartedCheckBox.Name = "MinimizeWhenStartedCheckBox";
this.MinimizeWhenStartedCheckBox.Size = new System.Drawing.Size(158, 21);
this.MinimizeWhenStartedCheckBox.TabIndex = 3;
@@ -786,7 +823,7 @@ namespace Netch.Forms
// RunAtStartupCheckBox
//
this.RunAtStartupCheckBox.AutoSize = true;
this.RunAtStartupCheckBox.Location = new System.Drawing.Point(6, 50);
this.RunAtStartupCheckBox.Location = new System.Drawing.Point(16, 80);
this.RunAtStartupCheckBox.Name = "RunAtStartupCheckBox";
this.RunAtStartupCheckBox.Size = new System.Drawing.Size(109, 21);
this.RunAtStartupCheckBox.TabIndex = 4;
@@ -796,7 +833,7 @@ namespace Netch.Forms
// CheckUpdateWhenOpenedCheckBox
//
this.CheckUpdateWhenOpenedCheckBox.AutoSize = true;
this.CheckUpdateWhenOpenedCheckBox.Location = new System.Drawing.Point(200, 50);
this.CheckUpdateWhenOpenedCheckBox.Location = new System.Drawing.Point(224, 80);
this.CheckUpdateWhenOpenedCheckBox.Name = "CheckUpdateWhenOpenedCheckBox";
this.CheckUpdateWhenOpenedCheckBox.Size = new System.Drawing.Size(190, 21);
this.CheckUpdateWhenOpenedCheckBox.TabIndex = 5;
@@ -807,7 +844,7 @@ namespace Netch.Forms
// NoSupportDialogCheckBox
//
this.NoSupportDialogCheckBox.AutoSize = true;
this.NoSupportDialogCheckBox.Location = new System.Drawing.Point(6, 72);
this.NoSupportDialogCheckBox.Location = new System.Drawing.Point(16, 112);
this.NoSupportDialogCheckBox.Name = "NoSupportDialogCheckBox";
this.NoSupportDialogCheckBox.Size = new System.Drawing.Size(174, 21);
this.NoSupportDialogCheckBox.TabIndex = 6;
@@ -817,7 +854,7 @@ namespace Netch.Forms
// CheckBetaUpdateCheckBox
//
this.CheckBetaUpdateCheckBox.AutoSize = true;
this.CheckBetaUpdateCheckBox.Location = new System.Drawing.Point(200, 72);
this.CheckBetaUpdateCheckBox.Location = new System.Drawing.Point(224, 112);
this.CheckBetaUpdateCheckBox.Name = "CheckBetaUpdateCheckBox";
this.CheckBetaUpdateCheckBox.Size = new System.Drawing.Size(137, 21);
this.CheckBetaUpdateCheckBox.TabIndex = 7;
@@ -828,7 +865,7 @@ namespace Netch.Forms
// UpdateServersWhenOpenedCheckBox
//
this.UpdateServersWhenOpenedCheckBox.AutoSize = true;
this.UpdateServersWhenOpenedCheckBox.Location = new System.Drawing.Point(200, 94);
this.UpdateServersWhenOpenedCheckBox.Location = new System.Drawing.Point(224, 144);
this.UpdateServersWhenOpenedCheckBox.Name = "UpdateServersWhenOpenedCheckBox";
this.UpdateServersWhenOpenedCheckBox.Size = new System.Drawing.Size(200, 21);
this.UpdateServersWhenOpenedCheckBox.TabIndex = 8;
@@ -927,15 +964,6 @@ namespace Netch.Forms
this.flowLayoutPanel1.Size = new System.Drawing.Size(480, 400);
this.flowLayoutPanel1.TabIndex = 0;
//
// DNSHijackLabel
//
this.DNSHijackLabel.AutoSize = true;
this.DNSHijackLabel.Location = new System.Drawing.Point(65, 140);
this.DNSHijackLabel.Name = "DNSHijackLabel";
this.DNSHijackLabel.Size = new System.Drawing.Size(34, 17);
this.DNSHijackLabel.TabIndex = 3;
this.DNSHijackLabel.Text = "DNS";
//
// SettingForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
@@ -999,7 +1027,7 @@ namespace Netch.Forms
private System.Windows.Forms.Label TUNTAPAddressLabel;
private System.Windows.Forms.TextBox TUNTAPAddressTextBox;
private System.Windows.Forms.Button GlobalBypassIPsButton;
private System.Windows.Forms.CheckBox DNSHijackCheckBox;
private System.Windows.Forms.CheckBox FilterDNSCheckBox;
private System.Windows.Forms.Button ControlButton;
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
private System.Windows.Forms.TabPage OtherTabPage;
@@ -1047,13 +1075,15 @@ namespace Netch.Forms
private System.Windows.Forms.Label ServerPingTypeLabel;
private System.Windows.Forms.RadioButton TCPingRadioBtn;
private System.Windows.Forms.RadioButton ICMPingRadioBtn;
private System.Windows.Forms.ComboBox ProcessFilterProtocolComboBox;
private System.Windows.Forms.Label ProcessFilterProtocolLabel;
private System.Windows.Forms.CheckBox FilterICMPCheckBox;
private System.Windows.Forms.CheckBox ChildProcessHandleCheckBox;
private System.Windows.Forms.TextBox ICMPDelayTextBox;
private System.Windows.Forms.Label ICMPDelayLabel;
private System.Windows.Forms.CheckBox NoSupportDialogCheckBox;
private System.Windows.Forms.Label DNSHijackLabel;
private System.Windows.Forms.CheckBox HandleProcDNSCheckBox;
private System.Windows.Forms.CheckBox FilterTCPCheckBox;
private System.Windows.Forms.CheckBox FilterUDPCheckBox;
private System.Windows.Forms.CheckBox DNSProxyCheckBox;
}
}

View File

@@ -1,23 +1,17 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Windows.Forms;
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
using Serilog;
namespace Netch.Forms
{
public partial class SettingForm : Form
public partial class SettingForm : BindingForm
{
private readonly Dictionary<Control, Func<string, bool>> _checkActions = new();
private readonly Dictionary<Control, Action<Control>> _saveActions = new();
public SettingForm()
{
InitializeComponent();
@@ -89,22 +83,25 @@ namespace Netch.Forms
#region Process Mode
BindListComboBox(ProcessFilterProtocolComboBox,
s => Global.Settings.Redirector.FilterProtocol = (PortType)Enum.Parse(typeof(PortType), s.ToString(), false),
Enum.GetNames(typeof(PortType)),
Global.Settings.Redirector.FilterProtocol.ToString());
BindCheckBox(FilterTCPCheckBox, b => Global.Settings.Redirector.FilterTCP = b, Global.Settings.Redirector.FilterTCP);
BindCheckBox(FilterUDPCheckBox, b => Global.Settings.Redirector.FilterUDP = b, Global.Settings.Redirector.FilterUDP);
BindCheckBox(FilterICMPCheckBox, b => Global.Settings.Redirector.FilterICMP = b, Global.Settings.Redirector.FilterICMP);
BindTextBox<int>(ICMPDelayTextBox, s => true, s => Global.Settings.Redirector.ICMPDelay = s, Global.Settings.Redirector.ICMPDelay);
BindCheckBox(DNSHijackCheckBox, b => Global.Settings.Redirector.DNSHijack = b, Global.Settings.Redirector.DNSHijack);
BindCheckBox(FilterDNSCheckBox, b => Global.Settings.Redirector.FilterDNS = b, Global.Settings.Redirector.FilterDNS);
BindTextBox(DNSHijackHostTextBox, s => true, s => Global.Settings.Redirector.DNSHijackHost = s, Global.Settings.Redirector.DNSHijackHost);
BindTextBox(DNSHijackHostTextBox, s => true, s => Global.Settings.Redirector.DNSHost = s, Global.Settings.Redirector.DNSHost);
BindCheckBox(ChildProcessHandleCheckBox,
s => Global.Settings.Redirector.ChildProcessHandle = s,
Global.Settings.Redirector.ChildProcessHandle);
s => Global.Settings.Redirector.FilterParent = s,
Global.Settings.Redirector.FilterParent);
BindCheckBox(DNSProxyCheckBox, b => Global.Settings.Redirector.DNSProxy = b, Global.Settings.Redirector.DNSProxy);
BindCheckBox(HandleProcDNSCheckBox, b => Global.Settings.Redirector.HandleOnlyDNS = b, Global.Settings.Redirector.HandleOnlyDNS);
#endregion
@@ -237,7 +234,7 @@ namespace Netch.Forms
#region Check
var checkNotPassControl = _checkActions.Where(pair => !pair.Value.Invoke(pair.Key.Text)).Select(pair => pair.Key).ToList();
var checkNotPassControl = GetCheckFailedControls();
foreach (Control control in checkNotPassControl)
Utils.Utils.ChangeControlForeColor(control, Color.Red);
@@ -248,8 +245,7 @@ namespace Netch.Forms
#region Save
foreach (var pair in _saveActions)
pair.Value.Invoke(pair.Key);
SaveBinds();
#endregion
@@ -259,71 +255,5 @@ namespace Netch.Forms
MessageBoxX.Show(i18N.Translate("Saved"));
Close();
}
#region BindUtils
private void BindTextBox(TextBox control, Func<string, bool> check, Action<string> save, object value)
{
BindTextBox<string>(control, check, save, value);
}
private void BindTextBox<T>(TextBox control, Func<T, bool> check, Action<T> save, object value)
{
control.Text = value.ToString();
_checkActions.Add(control,
s =>
{
try
{
return check.Invoke((T)Convert.ChangeType(s, typeof(T)));
}
catch
{
return false;
}
});
_saveActions.Add(control, c => save.Invoke((T)Convert.ChangeType(((TextBox)c).Text, typeof(T))));
}
private void BindCheckBox(CheckBox control, Action<bool> save, bool value)
{
control.Checked = value;
_saveActions.Add(control, c => save.Invoke(((CheckBox)c).Checked));
}
private void BindRadioBox(RadioButton control, Action<bool> save, bool value)
{
control.Checked = value;
_saveActions.Add(control, c => save.Invoke(((RadioButton)c).Checked));
}
private void BindListComboBox<T>(ComboBox comboBox, Action<T> save, IEnumerable<T> values, T value) where T : notnull
{
if (comboBox.DropDownStyle != ComboBoxStyle.DropDownList)
throw new ArgumentOutOfRangeException();
var tagItems = values.Select(o => new TagItem<T>(o, o.ToString()!)).ToArray();
comboBox.Items.AddRange(tagItems.Cast<object>().ToArray());
comboBox.ValueMember = nameof(TagItem<T>.Value);
comboBox.DisplayMember = nameof(TagItem<T>.Text);
_saveActions.Add(comboBox, c => save.Invoke(((TagItem<T>)((ComboBox)c).SelectedItem).Value));
Load += (_, _) => { comboBox.SelectedItem = tagItems.SingleOrDefault(t => t.Value.Equals(value)); };
}
private void BindComboBox(ComboBox control, Func<string, bool> check, Action<string> save, string value, object[]? values = null)
{
if (values != null)
control.Items.AddRange(values);
_saveActions.Add(control, c => save.Invoke(((ComboBox)c).Text));
_checkActions.Add(control, check.Invoke);
Load += (_, _) => { control.Text = value; };
}
#endregion
}
}

View File

@@ -0,0 +1,92 @@
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Netch.Forms
{
public class SyncGlobalCheckBox : CheckBox
{
public SyncGlobalCheckBox()
{
AutoCheck = false;
OnSyncGlobalChanged();
}
private bool _syncGlobal;
private bool _globalValue;
public bool SyncGlobal
{
get => _syncGlobal;
set
{
if (value == _syncGlobal)
return;
_syncGlobal = value;
OnSyncGlobalChanged();
}
}
public bool GlobalValue
{
get => _globalValue;
set
{
if (value == _globalValue)
return;
_globalValue = value;
if (SyncGlobal)
Checked = value;
}
}
protected override void OnClick(EventArgs e)
{
if (Checked == GlobalValue)
{
SyncGlobal = !SyncGlobal;
if (SyncGlobal)
return;
}
Checked = !Checked;
base.OnClick(e);
}
public bool? Value
{
get => _syncGlobal ? null : Checked;
set
{
if (value == null)
{
SyncGlobal = true;
}
else
{
SyncGlobal = false;
Checked = (bool)value;
}
}
}
private void OnSyncGlobalChanged()
{
if (_syncGlobal)
{
Font = new Font(Font, FontStyle.Regular);
BackColor = SystemColors.Control;
}
else
{
Font = new Font(Font, FontStyle.Bold | FontStyle.Italic);
BackColor = Color.Yellow;
}
}
}
}

View File

@@ -6,6 +6,7 @@ using System.Text.Json.Serialization;
using System.Windows.Forms;
using Netch.Forms;
using Netch.Models;
using Netch.Models.Modes;
namespace Netch
{

View File

@@ -1,11 +1,13 @@
using System.Threading.Tasks;
using Netch.Models;
using Netch.Models.Modes;
using Netch.Servers;
namespace Netch.Interfaces
{
public interface IModeController : IController
{
public ModeFeature Features { get; }
public Task StartAsync(Socks5Server server, Mode mode);
}
}

View File

@@ -33,6 +33,12 @@ namespace Netch.Interops
AIO_BYPNAME
}
public static bool Dial(NameList name, bool value)
{
Log.Verbose($"[Redirector] Dial {name}: {value}");
return aio_dial(name, value.ToString().ToLower());
}
public static bool Dial(NameList name, string value)
{
Log.Verbose($"[Redirector] Dial {name}: {value}");

View File

@@ -0,0 +1,44 @@
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
using Netch.Models.Modes;
using Netch.Models.Modes.ProcessMode;
using Netch.Models.Modes.ShareMode;
using Netch.Models.Modes.TunMode;
namespace Netch.JsonConverter
{
public class ModeConverterWithTypeDiscriminator : JsonConverter<Mode>
{
public override Mode? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var jsonElement = JsonSerializer.Deserialize<JsonElement>(ref reader);
var modeTypePropertyName = JsonNamingPolicy.CamelCase.ConvertName(nameof(Mode.Type));
if (!jsonElement.TryGetProperty(modeTypePropertyName, out var modeTypeToken))
throw new JsonException();
var modeTypeEnum = modeTypeToken.ValueKind switch
{
JsonValueKind.Number => (ModeType)modeTypeToken.GetInt32(),
JsonValueKind.String => Enum.Parse<ModeType>(modeTypeToken.GetString()!),
_ => throw new JsonException()
};
var modeType = modeTypeEnum switch
{
ModeType.ProcessMode => typeof(Redirector),
ModeType.TunMode => typeof(TunMode),
ModeType.ShareMode => typeof(ShareMode),
_ => throw new ArgumentOutOfRangeException()
};
return (Mode?)jsonElement.Deserialize(modeType, options);
}
public override void Write(Utf8JsonWriter writer, Mode value, JsonSerializerOptions options)
{
JsonSerializer.Serialize<object>(writer, value, options);
}
}
}

View File

@@ -8,8 +8,6 @@ namespace Netch.JsonConverter
{
public class ServerConverterWithTypeDiscriminator : JsonConverter<Server>
{
public override bool CanConvert(Type typeToConvert) => typeToConvert == typeof(Server);
public override Server Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var jsonElement = JsonSerializer.Deserialize<JsonElement>(ref reader);

View File

@@ -1,123 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Netch.Enums;
using Netch.Utils;
namespace Netch.Models
{
public class Mode
{
private List<string>? _content;
public Mode(string? fullName)
{
FullName = fullName;
if (FullName == null || !File.Exists(FullName))
return;
Load();
}
public string? FullName { get; }
public List<string> Content => _content ??= ReadContent();
public string Remark { get; set; } = "";
public ModeType Type { get; set; } = ModeType.Process;
public string? RelativePath => FullName == null ? null : ModeHelper.GetRelativePath(FullName);
private void Load()
{
if (FullName == null)
return;
(Remark, Type) = ReadHead(FullName);
_content = null;
}
public IEnumerable<string> GetRules()
{
foreach (var s in Content)
{
if (string.IsNullOrWhiteSpace(s))
continue;
if (s.StartsWith("//"))
continue;
const string include = "#include";
if (s.StartsWith(include))
{
var relativePath = new StringBuilder(s[include.Length..].Trim());
relativePath.Replace("<", "").Replace(">", "");
relativePath.Replace(".h", ".txt");
var mode = Global.Modes.FirstOrDefault(m => m.RelativePath?.Equals(relativePath.ToString()) ?? false) ??
throw new MessageException($"{relativePath} file included in {Remark} not found");
if (mode == this)
throw new MessageException("Can't self-reference");
if (mode.Type != Type)
throw new MessageException($"{mode.Remark}'s mode is not as same as {Remark}'s mode");
if (mode.Content.Any(rule => rule.StartsWith(include)))
throw new Exception("Cannot reference mode that reference other mode");
foreach (var rule in mode.GetRules())
yield return rule;
}
else
{
yield return s;
}
}
}
private static (string, ModeType) ReadHead(string fileName)
{
var text = File.ReadLines(fileName).First();
if (text.First() != '#')
throw new FormatException($"{fileName} head not found at Line 0");
var strings = text[1..].SplitTrimEntries(',');
var remark = strings[0];
var typeNumber = int.TryParse(strings.ElementAtOrDefault(1), out var type) ? type : 0;
if (!Enum.GetValues(typeof(ModeType)).Cast<int>().Contains(typeNumber))
throw new NotSupportedException($"Not support mode \"{typeNumber}\".");
return (remark, (ModeType)typeNumber);
}
private List<string> ReadContent()
{
if (FullName == null || !File.Exists(FullName))
return new List<string>();
return File.ReadLines(FullName).Skip(1).ToList();
}
public void WriteFile()
{
var dir = Path.GetDirectoryName(FullName)!;
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
var content = $"# {Remark}, {(int)Type}{Constants.EOF}{string.Join(Constants.EOF, Content)}";
// 写入到模式文件里
File.WriteAllText(FullName!, content);
}
public override string ToString()
{
return $"[{(int)Type + 1}] {i18N.Translate(Remark)}";
}
}
}

View File

@@ -0,0 +1,29 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Netch.Utils;
namespace Netch.Models.Modes
{
public abstract class Mode
{
[JsonPropertyOrder(int.MinValue)]
public abstract ModeType Type { get; }
public Dictionary<string, string> Remark { get; set; } = new();
[JsonIgnore]
// File FullName
// TODO maybe make it becomes mode dictionary key
public string FullName { get; set; } = null!;
public override string ToString() => $"[{(int)Type + 1}] {i18NRemark}";
[JsonIgnore]
public string i18NRemark
{
// TODO i18N.Culture to support fallback
get => Remark.GetValueOrDefault(i18N.LangCode) ?? Remark.GetValueOrDefault("en") ?? "";
set => Remark[i18N.LangCode] = value;
}
}
}

View File

@@ -1,6 +1,6 @@
using System;
namespace Netch.Enums
namespace Netch.Models.Modes
{
[Flags]
public enum ModeFeature

View File

@@ -0,0 +1,20 @@
namespace Netch.Models.Modes
{
public enum ModeType
{
/// <summary>
/// 进程代理
/// </summary>
ProcessMode,
/// <summary>
/// 网络共享
/// </summary>
ShareMode,
/// <summary>
/// 网卡代理
/// </summary>
TunMode
}
}

View File

@@ -0,0 +1,39 @@
using System.Collections.Generic;
namespace Netch.Models.Modes.ProcessMode
{
public class Redirector : Mode
{
public override ModeType Type => ModeType.ProcessMode;
#region Base
public bool? FilterICMP { get; set; }
public bool? FilterTCP { get; set; }
public bool? FilterUDP { get; set; }
public bool? FilterDNS { get; set; }
public bool? FilterParent { get; set; }
public int? ICMPDelay { get; set; }
public bool? DNSProxy { get; set; }
public bool? HandleOnlyDNS { get; set; }
public string? DNSHost { get; set; }
#endregion
public bool FilterLoopback { get; set; } = false;
public bool FilterIntranet { get; set; } = true;
public List<string> Bypass { get; set; } = new();
public List<string> Handle { get; set; } = new();
}
}

View File

@@ -0,0 +1,9 @@
namespace Netch.Models.Modes.ShareMode
{
public class ShareMode : Mode
{
public override ModeType Type => ModeType.ShareMode;
public string Argument = "--preset uu";
}
}

View File

@@ -0,0 +1,13 @@
using System.Collections.Generic;
namespace Netch.Models.Modes.TunMode
{
public class TunMode : Mode
{
public override ModeType Type => ModeType.TunMode;
public List<string> Bypass { get; set; } = new();
public List<string> Handle { get; set; } = new();
}
}

View File

@@ -1,4 +1,6 @@
namespace Netch.Models
using Netch.Models.Modes;
namespace Netch.Models
{
public class Profile
{
@@ -13,7 +15,7 @@
public Profile(Server server, Mode mode, string name, int index)
{
ServerRemark = server.Remark;
ModeRemark = mode.Remark;
ModeRemark = mode.i18NRemark;
ProfileName = name;
Index = index;
}

View File

@@ -0,0 +1,11 @@
namespace Netch.Models
{
public class AioDNSConfig
{
public string ChinaDNS { get; set; } = $"tcp://{Constants.DefaultCNPrimaryDNS}";
public string OtherDNS { get; set; } = $"tcp://{Constants.DefaultPrimaryDNS}";
public ushort ListenPort { get; set; } = 253;
}
}

View File

@@ -0,0 +1,19 @@
namespace Netch.Models
{
public class KcpConfig
{
public bool congestion { get; set; } = false;
public int downlinkCapacity { get; set; } = 100;
public int mtu { get; set; } = 1350;
public int readBufferSize { get; set; } = 2;
public int tti { get; set; } = 50;
public int uplinkCapacity { get; set; } = 12;
public int writeBufferSize { get; set; } = 2;
}
}

View File

@@ -0,0 +1,23 @@
namespace Netch.Models
{
public class RedirectorConfig
{
public bool FilterTCP { get; set; } = true;
public bool FilterUDP { get; set; } = true;
public bool FilterDNS { get; set; } = true;
public bool FilterParent { get; set; } = false;
public bool HandleOnlyDNS { get; set; } = true;
public bool DNSProxy { get; set; } = true;
public string DNSHost { get; set; } = Constants.DefaultPrimaryDNS;
public int ICMPDelay { get; set; } = 10;
public bool FilterICMP { get; set; } = false;
}
}

View File

@@ -2,117 +2,9 @@
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Netch.Utils;
namespace Netch.Models
{
/// <summary>
/// TUN/TAP 适配器配置类
/// </summary>
public class TUNConfig
{
/// <summary>
/// 地址
/// </summary>
public string Address { get; set; } = "10.0.236.10";
/// <summary>
/// DNS
/// </summary>
public string HijackDNS { get; set; } = "tcp://1.1.1.1:53";
/// <summary>
/// 网关
/// </summary>
public string Gateway { get; set; } = "10.0.236.1";
/// <summary>
/// 掩码
/// </summary>
public string Netmask { get; set; } = "255.255.255.0";
/// <summary>
/// 模式 2 下是否代理 DNS
/// </summary>
public bool ProxyDNS { get; set; } = false;
/// <summary>
/// 使用自定义 DNS 设置
/// </summary>
public bool UseCustomDNS { get; set; } = false;
/// <summary>
/// 全局绕过 IP 列表
/// </summary>
public List<string> BypassIPs { get; set; } = new();
}
public class KcpConfig
{
public bool congestion { get; set; } = false;
public int downlinkCapacity { get; set; } = 100;
public int mtu { get; set; } = 1350;
public int readBufferSize { get; set; } = 2;
public int tti { get; set; } = 50;
public int uplinkCapacity { get; set; } = 12;
public int writeBufferSize { get; set; } = 2;
}
public class V2rayConfig
{
public bool AllowInsecure { get; set; } = false;
public KcpConfig KcpConfig { get; set; } = new();
public bool UseMux { get; set; } = false;
public bool V2rayNShareLink { get; set; } = true;
public bool XrayCone { get; set; } = true;
}
public class AioDNSConfig
{
public string ChinaDNS { get; set; } = "tcp://223.5.5.5:53";
public string OtherDNS { get; set; } = "tcp://1.1.1.1:53";
public ushort ListenPort { get; set; } = 253;
}
public class RedirectorConfig
{
/// <summary>
/// 不代理TCP
/// </summary>
public PortType FilterProtocol { get; set; } = PortType.Both;
/// <summary>
/// 是否开启DNS转发
/// </summary>
public bool DNSHijack { get; set; } = true;
/// <summary>
/// 转发DNS地址
/// </summary>
public string DNSHijackHost { get; set; } = "1.1.1.1:53";
public int ICMPDelay { get; set; } = 0;
public bool FilterICMP { get; set; } = false;
/// <summary>
/// 是否代理子进程
/// </summary>
public bool ChildProcessHandle { get; set; } = false;
}
/// <summary>
/// 用于读取和写入的配置的类
/// </summary>

View File

@@ -0,0 +1,45 @@
using System.Collections.Generic;
namespace Netch.Models
{
/// <summary>
/// TUN/TAP 适配器配置类
/// </summary>
public class TUNConfig
{
/// <summary>
/// 地址
/// </summary>
public string Address { get; set; } = "10.0.236.10";
/// <summary>
/// DNS
/// </summary>
public string HijackDNS { get; set; } = $"tcp://{Constants.DefaultPrimaryDNS}";
/// <summary>
/// 网关
/// </summary>
public string Gateway { get; set; } = "10.0.236.1";
/// <summary>
/// 掩码
/// </summary>
public string Netmask { get; set; } = "255.255.255.0";
/// <summary>
/// 模式 2 下是否代理 DNS
/// </summary>
public bool ProxyDNS { get; set; } = false;
/// <summary>
/// 使用自定义 DNS 设置
/// </summary>
public bool UseCustomDNS { get; set; } = false;
/// <summary>
/// Global bypass IPs
/// </summary>
public List<string> BypassIPs { get; set; } = new();
}
}

View File

@@ -0,0 +1,15 @@
namespace Netch.Models
{
public class V2rayConfig
{
public bool AllowInsecure { get; set; } = false;
public KcpConfig KcpConfig { get; set; } = new();
public bool UseMux { get; set; } = false;
public bool V2rayNShareLink { get; set; } = true;
public bool XrayCone { get; set; } = true;
}
}

View File

@@ -32,9 +32,9 @@
<ItemGroup>
<PackageReference Include="HMBSbige.SingleInstance" Version="5.0.7" />
<PackageReference Include="MaxMind.GeoIP2" Version="4.0.1" />
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="2.0.72" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.VisualStudio.Threading" Version="16.10.56" />
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.1.506-beta">
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="2.0.73" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.VisualStudio.Threading" Version="17.0.63" />
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.1.588-beta">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
@@ -49,10 +49,8 @@
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.0" />
<PackageReference Include="Stun.Net" Version="5.0.0" />
<PackageReference Include="System.Management" Version="5.0.0" />
<PackageReference Include="System.Reactive" Version="5.0.0" />
<PackageReference Include="System.Text.Json" Version="6.0.0-rc.1.21451.13" />
<PackageReference Include="TaskScheduler" Version="2.9.1" />
<PackageReference Include="Microsoft-WindowsAPICodePack-Shell" Version="1.1.4" />
<PackageReference Include="System.Text.Json" Version="6.0.0-rc.2.21480.5" />
<PackageReference Include="TaskScheduler" Version="2.9.2" />
<PackageReference Include="WindowsFirewallHelper" Version="2.1.4.81" />
<PackageReference Include="System.ServiceProcess.ServiceController" Version="5.0.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="5.0.0" />
@@ -68,6 +66,9 @@
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Update="Forms\SyncGlobalCheckBox.cs">
<SubType>UserControl</SubType>
</Compile>
</ItemGroup>
<ItemGroup>

View File

@@ -25,9 +25,9 @@ using Windows.Win32.UI.WindowsAndMessaging;
namespace Netch
{
public static class Netch
public static class Program
{
public static readonly SingleInstanceService SingleInstance = new($"Global\\{nameof(Netch)}");
public static readonly SingleInstanceService SingleInstance = new($"Global\\{nameof(Program)}");
internal static HWND ConsoleHwnd { get; private set; }
@@ -115,12 +115,14 @@ namespace Netch
Log.Information("SHA256: {Hash}", $"{Utils.Utils.SHA256CheckSum(Global.NetchExecutable)}");
Log.Information("System Language: {Language}", CultureInfo.CurrentCulture.Name);
#if RELEASE
if (Log.IsEnabled(LogEventLevel.Debug))
{
// TODO log level setting
Task.Run(() => Log.Debug("Third-party Drivers:\n{Drivers}", string.Join(Constants.EOF, SystemInfo.SystemDrivers(false)))).Forget();
Task.Run(() => Log.Debug("Running Processes: \n{Processes}", string.Join(Constants.EOF, SystemInfo.Processes(false)))).Forget();
}
#endif
}
private static void CheckClr()

View File

@@ -1,6 +1,6 @@
using Netch.Controllers;
using System.Reflection;
using System.Reflection;
using System.Runtime.InteropServices;
using Netch.Controllers;
// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
@@ -13,9 +13,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCopyright(UpdateChecker.Copyright)]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
#if NET
[assembly: System.Runtime.Versioning.SupportedOSPlatformAttribute("Windows7.0")]
#endif
// 将 ComVisible 设置为 false 会使此程序集中的类型
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型

View File

@@ -39,6 +39,10 @@
"Edit Process Mode": "修改进程模式",
"Create Route Table Rule": "创建路由表规则",
"Edit Route Table Rule": "修改路由表规则",
"Reload Modes": "重新加载模式",
"Handle rules": "处理规则",
"Bypass rules": "分流规则",
"Handle DNS through proxy": "经过代理处理 DNS",
"Address": "地址",
"Username": "用户名",
@@ -110,7 +114,6 @@
"Remark": "备注",
"Filename": "文件名",
"Use Custom Filename": "使用自定义文件名",
"Add": "添加",
"Scan": "扫描",
"Save": "保存",
@@ -148,7 +151,7 @@
"Allow other Devices to connect": "允许其他设备连入",
"Netmask": "子网掩码",
"Gateway": "网关",
"Use Custom DNS": "使用自定义 DNS",
"Use custom DNS": "使用自定义 DNS",
"Proxy DNS in Proxy Rule IPs Mode": "在 代理规则IP 模式下代理 DNS",
"Exit when closed": "关闭时退出",
"Stop when exited": "退出时停止",
@@ -156,10 +159,16 @@
"Check update when opened": "打开软件时检查更新",
"Check Beta update": "检查 Beta 更新",
"Update Servers when opened": "打开软件时更新服务器",
"Filter Protocol": "Filter 协议",
"Handle process's DNS Hijack": "被代理进程 DNS 劫持",
"Child Process Handle": "子进程代理",
"ICMP Delay(ms)": "ICMP 延迟(毫秒",
"Handle ICMP": "处理 ICMP",
"Handle TCP": "处理 TCP",
"Handle UDP": "处理 UDP",
"Handle DNS (DNS hijacking)": "处理 DNSDNS 劫持",
"Handle handled process's DNS": "处理被处理进程 DNS",
"Handle local loopback": "处理本地回环",
"Handle LAN": "处理局域网",
"Handle child process": "处理子进程",
"ICMP delay(ms)": "ICMP 延迟(毫秒)",
"Mode specific options": "模式专用设置",
"Profile Count": "快捷配置数量",
"Delay test after start(sec)": "启动后延迟测试(秒)",
"Ping Protocol": "延迟测试协议",

View File

@@ -0,0 +1,115 @@
using System;
using System.IO;
using Netch.Controllers;
using Netch.Interfaces;
using Netch.Models;
using Netch.Models.Modes;
using Netch.Utils;
using Serilog;
namespace Netch.Services
{
public class ModeService
{
public static readonly ModeService Instance = new();
public string ModeDirectoryFullName => Path.Combine(Global.NetchDir, "mode");
public string GetRelativePath(string fullName)
{
var length = ModeDirectoryFullName.Length;
if (!ModeDirectoryFullName.EndsWith("\\"))
length++;
return fullName.Substring(length);
}
public string GetFullPath(string relativeName)
{
return Path.Combine(ModeDirectoryFullName, relativeName);
}
public void Load()
{
Global.Modes.Clear();
LoadCore(ModeDirectoryFullName);
Sort();
Global.MainForm.LoadModes();
}
private void LoadCore(string modeDirectory)
{
foreach (var directory in Directory.GetDirectories(modeDirectory))
LoadCore(directory);
// skip Directory with a disabled file in
if (File.Exists(Path.Combine(modeDirectory, Constants.DisableModeDirectoryFileName)))
return;
foreach (var file in Directory.GetFiles(modeDirectory))
{
try
{
Global.Modes.Add(ModeHelper.LoadMode(file));
}
catch (NotSupportedException)
{
// ignored
}
catch (Exception e)
{
Log.Warning(e, "Load mode \"{FileName}\" failed", file);
}
}
}
private static void Sort()
{
// TODO better sort need to discuss
// TODO replace Mode Collection type
Global.Modes.Sort((a, b) => string.Compare(a.i18NRemark, b.i18NRemark, StringComparison.Ordinal));
}
public void Add(Mode mode)
{
if (mode.FullName == null)
throw new InvalidOperationException();
Global.Modes.Add(mode);
Sort();
Global.MainForm.ModeComboBox.Items.Insert(Global.Modes.IndexOf(mode), mode);
mode.WriteFile();
}
public static void Delete(Mode mode)
{
if (mode.FullName == null)
throw new ArgumentException(nameof(mode.FullName));
Global.MainForm.ModeComboBox.Items.Remove(mode);
Global.Modes.Remove(mode);
if (File.Exists(mode.FullName))
File.Delete(mode.FullName);
}
public static IModeController GetModeControllerByType(ModeType type, out ushort? port, out string portName)
{
port = null;
portName = string.Empty;
switch (type)
{
case ModeType.ProcessMode:
return new NFController();
case ModeType.TunMode:
return new TUNController();
case ModeType.ShareMode:
return new PcapController();
default:
Log.Error("Unknown Mode Type \"{Type}\"", (int)type);
throw new MessageException("Unknown Mode Type");
}
}
}
}

View File

@@ -13,19 +13,13 @@ namespace Netch.Services
{
public class Updater
{
#region Static
#endregion
#region Class
private string UpdateFile { get; }
private string InstallDirectory { get; }
private readonly string _tempDirectory;
private static readonly string[] KeepDirectories = { "data", "mode\\Custom", "logging" };
private static readonly string[] KeepFiles = { ModeHelper.DisableModeDirectoryFileName };
private static readonly string[] KeepFiles = { Constants.DisableModeDirectoryFileName };
internal Updater(string updateFile, string installDirectory)
{
@@ -142,7 +136,5 @@ namespace Netch.Services
}
#endregion
#endregion
}
}

View File

@@ -1,7 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
@@ -64,8 +62,7 @@ namespace Netch.Utils
Cache6.Add(hostname, result);
break;
default:
Trace.Assert(false);
break;
throw new ArgumentOutOfRangeException();
}
return result;
@@ -74,34 +71,12 @@ namespace Netch.Utils
return null;
}
/// <summary>
/// 查询
/// </summary>
/// <param name="hostname">主机名</param>
/// <returns></returns>
public static void ClearCache()
{
Cache.Clear();
Cache6.Clear();
}
public static IEnumerable<string> Split(string dns)
{
return dns.SplitRemoveEmptyEntriesAndTrimEntries(',');
}
public static bool TrySplit(string value, out IEnumerable<string> result, ushort maxCount = 0)
{
result = Split(value).ToArray();
return maxCount == 0 || result.Count() <= maxCount && result.All(ip => IPAddress.TryParse(ip, out _));
}
public static string Join(IEnumerable<string> dns)
{
return string.Join(",", dns);
}
public static string AppendPort(string host, ushort port = 53)
{
if (!host.Contains(':'))
@@ -109,13 +84,5 @@ namespace Netch.Utils
return host;
}
public static string AppendScheme(string value, string scheme = "tcp")
{
if (!value.Contains(Uri.SchemeDelimiter))
return scheme + Uri.SchemeDelimiter + value;
return value;
}
}
}

View File

@@ -1,147 +1,142 @@
using System;
using System.IO;
using System.Linq;
using System.Reactive.Linq;
using Netch.Controllers;
using Netch.Enums;
using Netch.Interfaces;
using Netch.Models;
using Serilog;
using System.Text.Json;
using System.Text.Json.Serialization;
using Netch.JsonConverter;
using Netch.Models.Modes;
using Netch.Models.Modes.ProcessMode;
using Netch.Models.Modes.ShareMode;
using Netch.Models.Modes.TunMode;
using Netch.Services;
namespace Netch.Utils
{
public static class ModeHelper
{
public const string DisableModeDirectoryFileName = "disabled";
private static readonly JsonSerializerOptions JsonSerializerOptions = Global.NewCustomJsonSerializerOptions();
private static FileSystemWatcher _fileSystemWatcher = null!;
public static string ModeDirectoryFullName => Path.Combine(Global.NetchDir, "mode");
public static bool SuspendWatcher
static ModeHelper()
{
get => _fileSystemWatcher.EnableRaisingEvents;
set => _fileSystemWatcher.EnableRaisingEvents = value;
JsonSerializerOptions.Converters.Add(new ModeConverterWithTypeDiscriminator());
JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.Never;
}
public static void InitWatcher()
public static Mode LoadMode(string file)
{
_fileSystemWatcher = new FileSystemWatcher(ModeDirectoryFullName)
if (file.EndsWith(".json"))
return LoadJsonMode(file);
if (file.EndsWith(".txt"))
return ReadTxtMode(file);
throw new NotSupportedException();
}
private static Mode LoadJsonMode(string file)
{
using var fs = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true);
var mode = JsonSerializer.Deserialize<Mode>(fs, JsonSerializerOptions) ?? throw new ArgumentNullException();
mode.FullName = file;
return mode;
}
public static void WriteFile(this Mode mode)
{
using var fs = new FileStream(mode.FullName, FileMode.Create, FileAccess.Write, FileShare.None, 4096, true);
JsonSerializer.Serialize(fs, mode, JsonSerializerOptions);
}
private static Mode ReadTxtMode(string file)
{
Mode mode;
var ls = File.ReadAllLines(file);
string modeTypeNum;
if (ls.First().First() != '#')
throw new FormatException("Not a valid txt mode that begins with meta line");
var heads = ls[0][1..].Split(",", StringSplitOptions.TrimEntries);
switch (modeTypeNum = heads.ElementAtOrDefault(1) ?? "0")
{
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName,
IncludeSubdirectories = true,
EnableRaisingEvents = true
};
var created = Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(h => _fileSystemWatcher.Created += h,
h => _fileSystemWatcher.Created -= h)
.Select(x => x.EventArgs);
var changed = Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(h => _fileSystemWatcher.Changed += h,
h => _fileSystemWatcher.Changed -= h)
.Select(x => x.EventArgs);
var deleted = Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(h => _fileSystemWatcher.Deleted += h,
h => _fileSystemWatcher.Deleted -= h)
.Select(x => x.EventArgs);
var renamed = Observable.FromEventPattern<RenamedEventHandler, RenamedEventArgs>(h => _fileSystemWatcher.Renamed += h,
h => _fileSystemWatcher.Renamed -= h)
.Select(x => x.EventArgs);
var o = Observable.Merge(created, deleted, renamed, changed);
o.Throttle(TimeSpan.FromSeconds(3)).Subscribe(_ => OnModeChange(), exception => Log.Error(exception, "FileSystemWatcherError"));
}
private static void OnModeChange()
{
Load();
Global.MainForm.LoadModes();
}
public static string GetRelativePath(string fullName)
{
var length = ModeDirectoryFullName.Length;
if (!ModeDirectoryFullName.EndsWith("\\"))
length++;
return fullName.Substring(length);
}
public static string GetFullPath(string relativeName)
{
return Path.Combine(ModeDirectoryFullName, relativeName);
}
public static void Load()
{
Global.Modes.Clear();
LoadCore(ModeDirectoryFullName);
Sort();
}
private static void LoadCore(string modeDirectory)
{
try
{
foreach (var directory in Directory.GetDirectories(modeDirectory))
LoadCore(directory);
// skip Directory with a disabled file in
if (File.Exists(Path.Combine(modeDirectory, DisableModeDirectoryFileName)))
return;
foreach (var file in Directory.GetFiles(modeDirectory).Where(f => f.EndsWith(".txt")))
try
{
Global.Modes.Add(new Mode(file));
}
catch (Exception e)
{
Log.Warning(e, "Load mode \"{FileName}\" failed", file);
}
}
catch
{
// ignored
}
}
private static void Sort()
{
Global.Modes.Sort((a, b) => string.Compare(a.Remark, b.Remark, StringComparison.Ordinal));
}
public static void Delete(Mode mode)
{
if (mode.FullName == null)
throw new ArgumentException(nameof(mode.FullName));
Global.MainForm.ModeComboBox.Items.Remove(mode);
Global.Modes.Remove(mode);
if (File.Exists(mode.FullName))
File.Delete(mode.FullName);
}
public static (IModeController, ModeFeature) GetModeControllerByType(ModeType type, out ushort? port, out string portName)
{
port = null;
portName = string.Empty;
switch (type)
{
case ModeType.Process:
return (new NFController(), ModeFeature.SupportIPv6 | ModeFeature.SupportSocks5Auth);
case ModeType.ProxyRuleIPs:
return (new TUNController(), ModeFeature.SupportSocks5Auth);
case ModeType.BypassRuleIPs:
return (new TUNController(), ModeFeature.SupportSocks5Auth);
case ModeType.Pcap2Socks:
return (new PcapController(), 0);
case "0":
mode = new Redirector { FullName = file };
break;
case "1":
case "2":
mode = new TunMode { FullName = file };
break;
case "6":
mode = new ShareMode { FullName = file };
break;
default:
Log.Error("Unknown Mode Type \"{Type}\"", (int)type);
throw new MessageException("Unknown Mode Type");
throw new ArgumentOutOfRangeException();
}
mode.Remark.Add("en", heads[0]);
foreach (var l in ls.Skip(1))
{
if (l.IsNullOrWhiteSpace())
continue;
if (l.StartsWith("//"))
continue;
Mode? includeMode = null;
if (l.StartsWith("#include"))
{
var relativePath = l["#include ".Length..].Replace("<", "").Replace(">", "").Replace(".h", ".txt").Trim();
includeMode = ReadTxtMode(ModeService.Instance.GetFullPath(relativePath));
}
switch (mode)
{
case Redirector processMode:
if (includeMode is Redirector pMode)
{
processMode.Bypass.AddRange(pMode.Bypass);
processMode.Handle.AddRange(pMode.Handle);
}
else if (l.StartsWith("!"))
processMode.Bypass.Add(l);
else
processMode.Handle.Add(l);
break;
case ShareMode shareMode:
shareMode.Argument = l;
break;
case TunMode tunMode:
if (includeMode is TunMode tMode)
{
tunMode.Bypass.AddRange(tMode.Bypass);
tMode.Handle.AddRange(tMode.Handle);
break;
}
switch (modeTypeNum)
{
case "1":
tunMode.Handle.Add(l);
break;
case "2":
tunMode.Bypass.Add(l);
break;
}
break;
default:
throw new ArgumentOutOfRangeException();
}
}
if (modeTypeNum == "2")
((TunMode)mode).Handle.Add("0.0.0.0/0");
return mode;
}
}
}

View File

@@ -5,8 +5,8 @@ using System.Management;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using Netch.Models;
using Windows.Win32;
using Netch.Models;
namespace Netch.Utils
{
@@ -15,14 +15,15 @@ namespace Netch.Utils
public static NetworkInterface GetBest(AddressFamily addressFamily = AddressFamily.InterNetwork)
{
string ipAddress;
if (addressFamily == AddressFamily.InterNetwork)
switch (addressFamily)
{
ipAddress = "114.114.114.114";
}
else
{
Trace.Assert(addressFamily == AddressFamily.InterNetworkV6);
throw new NotImplementedException();
case AddressFamily.InterNetwork:
ipAddress = "114.114.114.114";
break;
case AddressFamily.InterNetworkV6:
throw new NotImplementedException();
default:
throw new InvalidOperationException();
}
if (PInvoke.GetBestRoute(BitConverter.ToUInt32(IPAddress.Parse(ipAddress).GetAddressBytes(), 0), 0, out var route) != 0)

View File

@@ -37,33 +37,41 @@ namespace Netch.Utils
if (port == 0)
throw new ArgumentOutOfRangeException();
if (inet != AddressFamily.InterNetwork)
Trace.Assert(inet == AddressFamily.InterNetworkV6);
var process = new List<Process>();
unsafe
switch (inet)
{
uint err;
uint size = 0;
PInvoke.GetExtendedTcpTable(default, ref size, false, (uint)inet, TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_LISTENER, 0); // get size
var tcpTable = (MIB_TCPTABLE_OWNER_PID*)Marshal.AllocHGlobal((int)size);
if ((err = PInvoke.GetExtendedTcpTable(tcpTable, ref size, false, (uint)inet, TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_LISTENER, 0)) != 0)
throw new Win32Exception((int)err);
for (var i = 0; i < tcpTable -> dwNumEntries; i++)
case AddressFamily.InterNetwork:
{
var row = tcpTable -> table.ReadOnlyItemRef(i);
var process = new List<Process>();
unsafe
{
uint err;
uint size = 0;
PInvoke.GetExtendedTcpTable(default, ref size, false, (uint)inet, TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_LISTENER, 0); // get size
var tcpTable = (MIB_TCPTABLE_OWNER_PID*)Marshal.AllocHGlobal((int)size);
if (row.dwOwningPid is 0 or 4)
continue;
if ((err = PInvoke.GetExtendedTcpTable(tcpTable, ref size, false, (uint)inet, TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_LISTENER, 0)) !=
0)
throw new Win32Exception((int)err);
if (PInvoke.ntohs((ushort)row.dwLocalPort) == port)
process.Add(Process.GetProcessById((int)row.dwOwningPid));
for (var i = 0; i < tcpTable -> dwNumEntries; i++)
{
var row = tcpTable -> table.ReadOnlyItemRef(i);
if (row.dwOwningPid is 0 or 4)
continue;
if (PInvoke.ntohs((ushort)row.dwLocalPort) == port)
process.Add(Process.GetProcessById((int)row.dwOwningPid));
}
}
return process;
}
case AddressFamily.InterNetworkV6:
throw new NotImplementedException();
default:
throw new InvalidOperationException();
}
return process;
}
private static void GetReservedPortRange(PortType portType, ref List<NumberRange> targetList)
@@ -136,8 +144,7 @@ namespace Netch.Utils
break;
default:
Trace.Assert(false);
return;
throw new ArgumentOutOfRangeException(nameof(type), type, null);
}
}

View File

@@ -13,12 +13,10 @@ namespace Netch.Utils
{
public static class i18N
{
#if NET
static i18N()
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
}
#endif
/// <summary>
/// 数据

View File

@@ -7,9 +7,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.6" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.6" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.7" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.7" />
<PackageReference Include="coverlet.collector" Version="3.1.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>