Compare commits

..

60 Commits
1.8.7 ... 1.9.3

Author SHA1 Message Date
ChsBuffer
7f82cac1d6 Bump version to 1.9.3 2021-11-05 00:14:01 +08:00
ChsBuffer
2d295a1449 [Features] Json Format Mode
New ModeEditForm
Refactors and Cleanup
Update nuget packages
2021-11-04 17:43:33 +08:00
ChsBuffer
5826d1a1a6 Fix TUNMode not bypass socks5 proxy remote address 2021-10-30 17:01:17 +08:00
ChsBuffer
072f2d16e6 Fix stop error when using socks5 proxy 2021-10-19 17:36:14 +08:00
ChsBuffer
ecaab55934 Revert default build SelfContained 2021-10-19 17:32:35 +08:00
Connection Refused
3c93aff15d [GitHub CI] Update build.yml 2021-10-18 19:15:00 +08:00
Connection Refused
de856dd2ec [Scripts] Update build.ps1 2021-10-18 19:09:32 +08:00
Connection Refused
a4a221ef2f [Netch] Compatible with the latest ss-rust 2021-10-18 19:03:27 +08:00
Connection Refused
1dbda9cbf9 [Netch] Compatible with the latest aiodns 2021-10-18 18:51:04 +08:00
Connection Refused
cecae73c03 [Netch] Compatible with the latest Redirector 2021-10-18 18:50:54 +08:00
ChsBuffer
0d535aa27e Bump version to 1.9.2 2021-10-15 20:44:50 +08:00
ChsBuffer
03c3c151bf Update CI 2021-10-15 20:44:07 +08:00
ChsBuffer
7a3b5ff487 Update Redirector settings
Update Redirector interop
Update NFController
Create Netch.JsonConverter namespace
2021-10-15 20:23:10 +08:00
ChsBuffer
598ff19535 Nice properties reuse, v2rayN. 2021-10-14 20:26:11 +08:00
ChsBuffer
d02135f31b Bump version to 1.9.1 2021-10-01 12:39:57 +08:00
ChsBuffer
a7756dabc1 Fix GetReservedPortRange 2021-10-01 12:39:46 +08:00
ChsBuffer
7ce1127006 Move bin folder check before create directories exist.
cleanup Core.bin strings
2021-10-01 12:30:57 +08:00
ChsBuffer
fec84a4952 Update NFController
Update ICMPDelay setting
Update WebUtil Default UserAgent
Hide unimplemented features' settings
Remove unused HTTP Port setting
2021-10-01 12:11:45 +08:00
ChsBuffer
d335c69fab Fix Import Server from Clipboard not set default group 2021-09-28 18:11:52 +08:00
ChsBuffer
1228a565c1 Update texts
rename Subscribe Link (WTF??) to Subscription
Full English log
Remove Debug Logging Sink
Add Console Logging Sink
2021-09-23 20:17:45 +08:00
ChsBuffer
dc904c9c0b Fix start failed deadlock 2021-09-21 17:16:40 +08:00
ChsBuffer
d829e347d3 Bump version to 1.9.0 2021-09-21 10:30:04 +08:00
ChsBuffer
a01761d2e2 Bump version to 1.8.9 2021-09-20 20:35:28 +08:00
ChsBuffer
68d87e2ff2 Remove Resolve Server Hostname setting 2021-09-20 20:34:23 +08:00
ChsBuffer
04d6933319 Rename TcpStatusLabel to HTTPStatusLabel 2021-09-20 19:08:01 +08:00
ChsBuffer
e46eef17d0 Create scripts\download\pcap2socks.ps1 2021-09-20 18:54:49 +08:00
ChsBuffer
d3c3958dab fix a typo 2021-09-20 18:20:59 +08:00
ChsBuffer
5ec8d38fd1 Fix build 2021-09-14 09:47:43 +08:00
ChsBuffer
2a8754ecfb Update build 2021-09-14 09:42:00 +08:00
ChsBuffer
cbc6822bff Refactor Cancel Connectivity Test 2021-09-14 08:49:37 +08:00
ChsBuffer
96bd7473ca Refactor AsyncLock 2021-09-14 08:41:30 +08:00
ChsBuffer
54b2b87dec Update Socks5ServerTestUtils.GetSimpleResult() 2021-09-12 03:18:35 +08:00
ChsBuffer
42baed8b8f Catch HttpConnectAsync's exception 2021-09-12 01:34:12 +08:00
ChsBuffer
f68aae6795 Update Setting.cs
- TUNTAP.UseCustomDNS true->false
- V2rayConfig.XrayCone false->true
- JsonIgnore Redirector.ChildProcessHandle
2021-09-12 01:32:48 +08:00
ChsBuffer
8e2008077d Bump version to 1.8.8 2021-09-11 01:32:41 +08:00
ChsBuffer
5b4f0026ff Feature: framework rollForward Major
this allows you to run .NET application targeting 5.x.x running on .NET 6.x.x runtime, but it's unsupported, May behave unexpectedly.
2021-09-11 01:28:27 +08:00
ChsBuffer
89f9dccb87 Fix virtual adapter mode NAT type test result "Wrong STUN server" 2021-09-11 01:19:01 +08:00
ChsBuffer
3e377f2e9d Feature: Server http connect time Test 2021-09-11 01:12:28 +08:00
ChsBuffer
635212f24d Replace NTTController with NatTypetester(Stun.Net)
Enable NAT Type Test for all mode types
Remove Shadowsocks SS
2021-09-10 23:56:25 +08:00
ChsBuffer
46d60babbc Refactor: Update Netch.Servers naming 2021-08-31 11:48:49 +08:00
ChsBuffer
8f80f9abef Update Nuget Packages 2021-08-29 03:54:19 +08:00
Netch
e268f1838f Update MainForm.cs 2021-08-14 09:18:27 +08:00
ChsBuffer
d99229ad50 Fix Netch.csproj loses ApplicationManifest property 2021-08-06 14:01:50 +08:00
ChsBuffer
df85d5797d Feature: remind will get no support from developers if OS is Windows 10 1809 below or CLR version is different from target framework 2021-08-06 06:59:19 +08:00
ChsBuffer
74856ccd61 Update UnitTest.csproj import common.props 2021-08-06 06:59:19 +08:00
ChsBuffer
0165d080c6 Feature: NFController.CheckCore check Core.bin file 2021-08-06 05:05:18 +08:00
ChsBuffer
97fb20e326 Update MainForm.State.StartDisableItems() 2021-08-06 04:55:16 +08:00
ChsBuffer
4d71e2d12f Bump Microsoft.Diagnostics.Tracing.TraceEvent from 2.0.70 to 2.0.71
Remove System.Drawing.Common nuget package
2021-08-06 04:45:59 +08:00
ChsBuffer
0fa83eac3c fix a typo 2021-08-06 02:13:32 +08:00
ChsBuffer
aa6623b063 Create common.props 2021-08-01 02:51:23 +08:00
ChsBuffer
94335ad900 Remove Properties\Settings.settings 2021-08-01 02:50:19 +08:00
ChsBuffer
baf3b39dd3 Fix Socks5 username and password not being saved to the configuration file 2021-08-01 02:49:00 +08:00
ChsBuffer
c12122f7d0 Refactor: Create ModeFeature Enum 2021-07-23 00:44:16 +08:00
ChsBuffer
3e5a4fc102 Update NatTestLock 2021-07-23 00:44:16 +08:00
ChsBuffer
57dbd0193a Move Netch.Models.State Netch.Models.LogLevel to Netch.Enums Namespace 2021-07-23 00:44:16 +08:00
ChsBuffer
5647a6c7ea Refactor SS,SSR Controller Generate Argument 2021-07-23 00:44:16 +08:00
ChsBuffer
773bad4845 Update ServerHelper.cs
Extract and Refactor DelayTestHelper
2021-07-23 00:44:15 +08:00
ChsBuffer
3e943ec6b8 Fix PcapController assert socks5 server false 2021-07-20 08:13:27 +08:00
ChsBuffer
920b068a1e Update DnsUtils 2021-07-19 08:09:57 +08:00
ChsBuffer
7eac7b0837 Fixup Touch Configuration File 2021-07-16 05:40:21 +08:00
131 changed files with 3407 additions and 2584 deletions

View File

@@ -1,13 +1,18 @@
name: Netch Build CI
on: [push, pull_request]
on:
push:
branches: [ master ]
pull_request:
jobs:
build:
name: Build
runs-on: windows-latest
runs-on: windows-2022
steps:
- name: MSBuild
uses: microsoft/setup-msbuild@v1.0.2
uses: microsoft/setup-msbuild@v1.0.3
with:
vs-prerelease: true
- name: Checkout
uses: actions/checkout@v2

View File

@@ -7,10 +7,12 @@ on:
jobs:
build:
name: Build
runs-on: windows-latest
runs-on: windows-2022
steps:
- name: MSBuild
uses: microsoft/setup-msbuild@v1.0.2
uses: microsoft/setup-msbuild@v1.0.3
with:
vs-prerelease: true
- name: Checkout
uses: actions/checkout@v2
@@ -41,6 +43,9 @@ jobs:
Netch.7z
body: |
[![](https://img.shields.io/badge/Telegram-Channel-blue)](https://t.me/netch_channel) [![](https://img.shields.io/badge/Telegram-Group-green)](https://t.me/netch_group)
[**第一次使用请务必先安装 .NET 5.0 运行库**](https://aka.ms/dotnet/5.0/windowsdesktop-runtime-win-x64.exe)
## Changelogs
* This is an automated deployment of GitHub Actions, the change log should be updated manually soon

View File

@@ -11,9 +11,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AdditionalFiles", "Addition
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
.gitignore = .gitignore
common.props = common.props
global.json = global.json
LICENSE = LICENSE
README.md = README.md
global.json = global.json
EndProjectSection
EndProject
Global
@@ -26,10 +27,10 @@ Global
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Debug|x64.Build.0 = Debug|x64
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Release|x64.ActiveCfg = Release|x64
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Release|x64.Build.0 = Release|x64
{38240783-9AD2-4A01-84C1-1A3E5F05720F}.Debug|x64.ActiveCfg = Debug|Any CPU
{38240783-9AD2-4A01-84C1-1A3E5F05720F}.Debug|x64.Build.0 = Debug|Any CPU
{38240783-9AD2-4A01-84C1-1A3E5F05720F}.Release|x64.ActiveCfg = Release|Any CPU
{38240783-9AD2-4A01-84C1-1A3E5F05720F}.Release|x64.Build.0 = Release|Any CPU
{38240783-9AD2-4A01-84C1-1A3E5F05720F}.Debug|x64.ActiveCfg = Debug|x64
{38240783-9AD2-4A01-84C1-1A3E5F05720F}.Debug|x64.Build.0 = Debug|x64
{38240783-9AD2-4A01-84C1-1A3E5F05720F}.Release|x64.ActiveCfg = Release|x64
{38240783-9AD2-4A01-84C1-1A3E5F05720F}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

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

@@ -23,8 +23,8 @@ namespace Netch.Controllers
var listenAddress = Global.Settings.LocalAddress;
Dial(NameList.TYPE_REST, "");
Dial(NameList.TYPE_ADDR, $"{listenAddress}:{aioDnsConfig.ListenPort}");
Dial(NameList.TYPE_LIST, Path.GetFullPath(Constants.AioDnsRuleFile));
Dial(NameList.TYPE_LISN, $"{listenAddress}:{aioDnsConfig.ListenPort}");
Dial(NameList.TYPE_CDNS, $"{aioDnsConfig.ChinaDNS}");
Dial(NameList.TYPE_ODNS, $"{aioDnsConfig.OtherDNS}");

View File

@@ -6,6 +6,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.Threading;
using Netch.Enums;
using Netch.Models;
using Netch.Utils;
using Serilog;
@@ -156,7 +157,7 @@ namespace Netch.Controllers
}
catch (Win32Exception e)
{
Log.Error(e, "停止 {Name} 异常", Instance.ProcessName);
Log.Error(e, "Stop {Name} failed", Instance.ProcessName);
}
catch
{

View File

@@ -1,56 +1,85 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.Threading;
using Netch.Interfaces;
using Netch.Models;
using Netch.Models.Modes;
using Netch.Servers;
using Netch.Services;
using Netch.Utils;
using Serilog;
using Serilog.Events;
namespace Netch.Controllers
{
public static class MainController
{
public static Mode? Mode { get; private set; }
public static Socks5Server? Socks5Server { get; private set; }
public static readonly NTTController NTTController = new();
public static Server? Server { get; private set; }
public static Mode? Mode { get; private set; }
public static IServerController? ServerController { get; private set; }
public static IModeController? ModeController { get; private set; }
private static readonly AsyncSemaphore Lock = new(1);
public static async Task StartAsync(Server server, Mode mode)
{
using var releaser = await Lock.EnterAsync();
Log.Information("Start MainController: {Server} {Mode}", $"{server.Type}", $"[{(int)mode.Type}]{mode.Remark}");
if (await DnsUtils.LookupAsync(server.Hostname) == null)
throw new MessageException(i18N.Translate("Lookup Server hostname failed"));
// TODO Disable NAT Type Test setting
// cache STUN Server ip to prevent "Wrong STUN Server"
DnsUtils.LookupAsync(Global.Settings.STUN_Server).Forget();
Server = server;
Mode = mode;
await Task.WhenAll(
Task.Run(NativeMethods.RefreshDNSCache),
Task.Run(Firewall.AddNetchFwRules)
);
if (Log.IsEnabled(LogEventLevel.Debug))
Task.Run(() =>
{
// TODO log level setting
Log.Debug("Running Processes: \n{Processes}", string.Join("\n", SystemInfo.Processes(false)));
})
.Forget();
await Task.WhenAll(Task.Run(NativeMethods.RefreshDNSCache), Task.Run(Firewall.AddNetchFwRules));
try
{
if (!ModeHelper.SkipServerController(server, mode))
server = await StartServerAsync(server);
ModeController = ModeService.GetModeControllerByType(mode.Type, out var modePort, out var portName);
await StartModeAsync(server, mode);
if (modePort != null)
TryReleaseTcpPort((ushort)modePort, portName);
if (Server is Socks5Server socks5 && (!socks5.Auth() || ModeController.Features.HasFlag(ModeFeature.SupportSocks5Auth)))
{
Socks5Server = socks5;
}
else
{
// Start Server Controller to get a local socks5 server
Log.Debug("Server Information: {Data}", $"{server.Type} {server.MaskedData()}");
ServerController = ServerHelper.GetUtilByTypeName(server.Type).GetController();
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ServerController.Name));
TryReleaseTcpPort(ServerController.Socks5LocalPort(), "Socks5");
Socks5Server = await ServerController.StartAsync(server);
StatusPortInfoText.Socks5Port = Socks5Server.Port;
StatusPortInfoText.UpdateShareLan();
}
// Start Mode Controller
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ModeController.Name));
await ModeController.StartAsync(Socks5Server, mode);
}
catch (Exception e)
{
releaser.Dispose();
await StopAsync();
switch (e)
@@ -68,49 +97,26 @@ namespace Netch.Controllers
}
}
private static async Task<Server> StartServerAsync(Server server)
{
ServerController = ServerHelper.GetUtilByTypeName(server.Type).GetController();
TryReleaseTcpPort(ServerController.Socks5LocalPort(), "Socks5");
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ServerController.Name));
Log.Debug("Server Information: {Data}", $"{server.Type} {server.MaskedData()}");
var socks5 = await ServerController.StartAsync(server);
StatusPortInfoText.Socks5Port = socks5.Port;
StatusPortInfoText.UpdateShareLan();
return socks5;
}
private static async Task StartModeAsync(Server server, Mode mode)
{
ModeController = ModeHelper.GetModeControllerByType(mode.Type, out var port, out var portName);
if (port != null)
TryReleaseTcpPort((ushort)port, portName);
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ModeController.Name));
await ModeController.StartAsync(server, mode);
}
public static async Task StopAsync()
{
if (Lock.CurrentCount == 0)
{
(await Lock.EnterAsync()).Dispose();
return;
}
using var _ = await Lock.EnterAsync();
if (ServerController == null && ModeController == null)
return;
Log.Information("Stop Main Controller");
StatusPortInfoText.Reset();
Task.Run(() => NTTController.StopAsync()).Forget();
var tasks = new[]
{
Task.Run(() => ServerController?.StopAsync()),
Task.Run(() => ModeController?.StopAsync())
ServerController?.StopAsync() ?? Task.CompletedTask,
ModeController?.StopAsync() ?? Task.CompletedTask
};
try
@@ -122,8 +128,8 @@ namespace Netch.Controllers
Log.Error(e, "MainController Stop Error");
}
ModeController = null;
ServerController = null;
ModeController = null;
}
public static void PortCheck(ushort port, string portName, PortType portType = PortType.Both)
@@ -163,5 +169,30 @@ namespace Netch.Controllers
PortCheck(port, portName, PortType.TCP);
}
public static async Task<NatTypeTestResult> DiscoveryNatTypeAsync(CancellationToken ctx = default)
{
Debug.Assert(Socks5Server != null, nameof(Socks5Server) + " != null");
return await Socks5ServerTestUtils.DiscoveryNatTypeAsync(Socks5Server, ctx);
}
public static async Task<int?> HttpConnectAsync(CancellationToken ctx = default)
{
Debug.Assert(Socks5Server != null, nameof(Socks5Server) + " != null");
try
{
return await Socks5ServerTestUtils.HttpConnectAsync(Socks5Server, ctx);
}
catch (OperationCanceledException)
{
// ignored
}
catch (Exception e)
{
Log.Warning(e, "Unhandled Socks5ServerTestUtils.HttpConnectAsync Exception");
}
return null;
}
}
}

View File

@@ -1,15 +1,15 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
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.Servers.Shadowsocks;
using Netch.Utils;
using Serilog;
using static Netch.Interops.Redirector;
@@ -19,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");
@@ -28,29 +28,55 @@ namespace Netch.Controllers
public string Name => "Redirector";
public async Task StartAsync(Server server, Mode mode)
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.TYPE_FILTERLOOPBACK, "false");
Dial(NameList.TYPE_FILTERICMP, "true");
var p = PortHelper.GetAvailablePort();
Dial(NameList.TYPE_TCPLISN, p.ToString());
Dial(NameList.TYPE_UDPLISN, p.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.TYPE_FILTERUDP, _rdrConfig.FilterProtocol.HasFlag(PortType.UDP).ToString().ToLower());
Dial(NameList.TYPE_FILTERTCP, _rdrConfig.FilterProtocol.HasFlag(PortType.TCP).ToString().ToLower());
await DialServerAsync(_rdrConfig.FilterProtocol, _server);
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
dial_Name(_mode);
// Features
Dial(NameList.TYPE_DNSHOST, _rdrConfig.DNSHijack ? _rdrConfig.DNSHijackHost : "");
DialRule();
if (!await InitAsync())
throw new MessageException("Redirector start failed.");
@@ -73,14 +99,14 @@ namespace Netch.Controllers
try
{
if (r.StartsWith("!"))
return Dial(NameList.TYPE_ADDNAME, r.Substring(1));
return Dial(NameList.AIO_ADDNAME, r.Substring(1));
return Dial(NameList.TYPE_ADDNAME, r);
return Dial(NameList.AIO_ADDNAME, r);
}
finally
{
if (clear)
Dial(NameList.TYPE_CLRNAME, "");
Dial(NameList.AIO_CLRNAME, "");
}
}
@@ -92,72 +118,38 @@ namespace Netch.Controllers
public static bool CheckRules(IEnumerable<string> rules, out IEnumerable<string> results)
{
results = rules.Where(r => !CheckCppRegex(r, false));
Dial(NameList.TYPE_CLRNAME, "");
Dial(NameList.AIO_CLRNAME, "");
return !results.Any();
}
public static string GenerateInvalidRulesMessage(IEnumerable<string> rules)
{
return $"{string.Join("\n", rules)}\nAbove rules does not conform to C++ regular expression syntax";
return $"{string.Join("\n", rules)}\n" + i18N.Translate("Above rules does not conform to C++ regular expression syntax");
}
#endregion
private async Task DialServerAsync(PortType portType, Server server)
private void DialRule()
{
if (portType == PortType.Both)
{
await DialServerAsync(PortType.TCP, server);
await DialServerAsync(PortType.UDP, server);
return;
}
var offset = portType == PortType.UDP ? UdpNameListOffset : 0;
if (server is Socks5 socks5)
{
Dial(NameList.TYPE_TCPTYPE + offset, "Socks5");
Dial(NameList.TYPE_TCPHOST + offset, $"{await socks5.AutoResolveHostnameAsync()}:{socks5.Port}");
Dial(NameList.TYPE_TCPUSER + offset, socks5.Username ?? string.Empty);
Dial(NameList.TYPE_TCPPASS + offset, socks5.Password ?? string.Empty);
Dial(NameList.TYPE_TCPMETH + offset, string.Empty);
}
else if (server is Shadowsocks shadowsocks && !shadowsocks.HasPlugin() && _rdrConfig.RedirectorSS)
{
Dial(NameList.TYPE_TCPTYPE + offset, "Shadowsocks");
Dial(NameList.TYPE_TCPHOST + offset, $"{await shadowsocks.AutoResolveHostnameAsync()}:{shadowsocks.Port}");
Dial(NameList.TYPE_TCPMETH + offset, shadowsocks.EncryptMethod);
Dial(NameList.TYPE_TCPPASS + offset, shadowsocks.Password);
}
else
{
Trace.Assert(false);
}
}
private void dial_Name(Mode mode)
{
Dial(NameList.TYPE_CLRNAME, "");
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.TYPE_BYPNAME, s.Substring(1)))
invalidList.Add(s);
if (!Dial(NameList.AIO_BYPNAME, s))
invalidList.Add(s);
}
continue;
}
if (!Dial(NameList.TYPE_ADDNAME, s))
foreach (var s in _mode.Handle)
{
if (!Dial(NameList.AIO_ADDNAME, s))
invalidList.Add(s);
}
if (invalidList.Any())
throw new MessageException(GenerateInvalidRulesMessage(invalidList));
Dial(NameList.TYPE_ADDNAME, @"NTT\.exe");
Dial(NameList.TYPE_BYPNAME, "^" + Global.NetchDir.ToRegexString() + @"((?!NTT\.exe).)*$");
// Bypass Self
Dial(NameList.AIO_BYPNAME, "^" + Global.NetchDir.ToRegexString());
}
#region DriverUtil
@@ -167,8 +159,8 @@ namespace Netch.Controllers
var binFileVersion = Utils.Utils.GetFileVersion(Constants.NFDriver);
var systemFileVersion = Utils.Utils.GetFileVersion(SystemDriver);
Log.Information("内置驱动版本: {Name}", binFileVersion);
Log.Information("系统驱动版本: {Name}", systemFileVersion);
Log.Information("Built-in netfilter2 driver version: {Name}", binFileVersion);
Log.Information("Installed netfilter2 driver version: {Name}", systemFileVersion);
if (!File.Exists(SystemDriver))
{
@@ -198,7 +190,7 @@ namespace Netch.Controllers
if (!reinstall)
return;
Log.Information("更新驱动");
Log.Information("Update netfilter2 driver");
UninstallDriver();
InstallDriver();
}
@@ -209,7 +201,8 @@ namespace Netch.Controllers
/// <returns>驱动是否安装成功</returns>
private static void InstallDriver()
{
Log.Information("安装 NF 驱动");
Log.Information("Install netfilter2 driver");
Global.MainForm.StatusText(i18N.Translate("Installing netfilter2 driver"));
if (!File.Exists(Constants.NFDriver))
throw new MessageException(i18N.Translate("builtin driver files missing, can't install NF driver"));
@@ -220,21 +213,18 @@ namespace Netch.Controllers
}
catch (Exception e)
{
Log.Error(e, "驱动复制失败\n");
throw new MessageException($"Copy NF driver file failed\n{e.Message}");
Log.Error(e, "Copy netfilter2.sys failed\n");
throw new MessageException($"Copy netfilter2.sys failed\n{e.Message}");
}
Global.MainForm.StatusText(i18N.Translate("Register driver"));
// 注册驱动文件
var result = NFAPI.nf_registerDriver("netfilter2");
if (result == NF_STATUS.NF_STATUS_SUCCESS)
if (Interops.Redirector.aio_register("netfilter2"))
{
Log.Information("驱动安装成功");
Log.Information("Install netfilter2 driver finished");
}
else
{
Log.Error("注册驱动失败: {Result}", result);
throw new MessageException($"Register NF driver failed\n{result}");
Log.Error("Register netfilter2 failed");
}
}
@@ -244,7 +234,7 @@ namespace Netch.Controllers
/// <returns>是否成功卸载</returns>
public static bool UninstallDriver()
{
Log.Information("卸载 NF 驱动");
Log.Information("Uninstall netfilter2");
try
{
if (NFService.Status == ServiceControllerStatus.Running)
@@ -261,7 +251,7 @@ namespace Netch.Controllers
if (!File.Exists(SystemDriver))
return true;
NFAPI.nf_unRegisterDriver("netfilter2");
Interops.Redirector.aio_unregister("netfilter2");
File.Delete(SystemDriver);
return true;

View File

@@ -1,106 +0,0 @@
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Netch.Interfaces;
using Netch.Utils;
using Serilog;
namespace Netch.Controllers
{
public class NTTController : Guard, IController
{
public NTTController() : base("NTT.exe")
{
}
public override string Name => "NTT";
/// <summary>
/// 启动 NatTypeTester
/// </summary>
/// <returns></returns>
public async Task<(string? result, string? localEnd, string? publicEnd)> StartAsync()
{
string? localEnd = null, publicEnd = null, result = null, bindingTest = null;
try
{
Instance.StartInfo.Arguments = $" {Global.Settings.STUN_Server} {Global.Settings.STUN_Server_Port}";
Instance.Start();
var output = await Instance.StandardOutput.ReadToEndAsync();
var error = await Instance.StandardError.ReadToEndAsync();
try
{
await File.WriteAllTextAsync(Path.Combine(Global.NetchDir, $"logging\\{Name}.log"), $"{output}\r\n{error}");
}
catch (Exception e)
{
Log.Warning(e, "写入 {Name} 日志错误", Name);
}
if (output.IsNullOrWhiteSpace())
{
if (error.IsNullOrWhiteSpace())
{
Log.Warning("NTT no output");
return (null, null, null);
}
var errorFirst = error.GetLines().First();
return (errorFirst.SplitTrimEntries(':').Last(), null, null);
}
foreach (var line in output.Split('\n'))
{
var str = line.SplitTrimEntries(':');
if (str.Length < 2)
continue;
var key = str[0];
var value = str[1];
switch (key)
{
case "Other address is":
case "Nat mapping behavior":
case "Nat filtering behavior":
break;
case "Binding test":
bindingTest = value;
break;
case "Local address":
localEnd = value;
break;
case "Mapped address":
publicEnd = value;
break;
case "result":
result = value;
break;
}
}
if (bindingTest == "Fail")
result = "Fail";
return (result, localEnd, publicEnd);
}
catch (Exception e)
{
Log.Error(e, "{Name} 控制器启动异常", Name);
try
{
await StopAsync();
}
catch
{
// ignored
}
return (null, null, null);
}
}
}
}

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 async Task StartAsync(Server server, Mode mode)
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 Socks5Bridge socks5)
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,13 +30,20 @@ namespace Netch.Controllers
public string Name => "tun2socks";
public async Task StartAsync(Server server, Mode mode)
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 Socks5Bridge socks5Bridge)
if (server is Socks5LocalServer socks5Bridge)
_serverRemoteAddress = await DnsUtils.LookupAsync(socks5Bridge.RemoteHostname);
else
_serverRemoteAddress = await DnsUtils.LookupAsync(server.Hostname);
if (_serverRemoteAddress != null && IPAddress.IsLoopback(_serverRemoteAddress))
_serverRemoteAddress = null;
@@ -56,24 +63,17 @@ namespace Netch.Controllers
Dial(NameList.TYPE_UDPREST, "");
Dial(NameList.TYPE_UDPTYPE, "Socks5");
if (server is Socks5 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
@@ -125,8 +125,8 @@ namespace Netch.Controllers
var binHash = Utils.Utils.SHA256CheckSum(binDriver);
var sysHash = Utils.Utils.SHA256CheckSum(sysDriver);
Log.Information("自带 wintun.dll Hash: {Hash}", binHash);
Log.Information("系统 wintun.dll Hash: {Hash}", sysHash);
Log.Information("Built-in wintun.dll Hash: {Hash}", binHash);
Log.Information("Installed wintun.dll Hash: {Hash}", sysHash);
if (binHash == sysHash)
return;
@@ -137,7 +137,7 @@ namespace Netch.Controllers
}
catch (Exception e)
{
Log.Error(e, "复制 wintun.dll 异常");
Log.Error(e, "Copy wintun.dll failed");
throw new MessageException($"Failed to copy wintun.dll to system directory: {e.Message}");
}
}
@@ -148,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));
@@ -155,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()
@@ -196,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

@@ -20,7 +20,7 @@ namespace Netch.Controllers
public const string Name = @"Netch";
public const string Copyright = @"Copyright © 2019 - 2021";
public const string AssemblyVersion = @"1.8.7";
public const string AssemblyVersion = @"1.9.3";
private const string Suffix = @"";
public static readonly string Version = $"{AssemblyVersion}{(string.IsNullOrEmpty(Suffix) ? "" : $"-{Suffix}")}";
@@ -48,24 +48,24 @@ namespace Netch.Controllers
var releases = JsonSerializer.Deserialize<List<Release>>(json)!;
LatestRelease = GetLatestRelease(releases, isPreRelease);
Log.Information("Github 最新发布版本: {Version}", LatestRelease.tag_name);
Log.Information("Github latest release: {Version}", LatestRelease.tag_name);
if (VersionUtil.CompareVersion(LatestRelease.tag_name, Version) > 0)
{
Log.Information("发现新版本");
Log.Information("Found newer version");
NewVersionFound?.Invoke(null, EventArgs.Empty);
}
else
{
Log.Information("目前是最新版本");
Log.Information("Already the latest version");
NewVersionNotFound?.Invoke(null, EventArgs.Empty);
}
}
catch (Exception e)
{
if (e is WebException)
Log.Warning(e, "获取新版本失败");
Log.Warning(e, "Get releases failed");
else
Log.Error(e, "获取新版本异常");
Log.Error(e, "Get releases error");
NewVersionFoundFailed?.Invoke(null, EventArgs.Empty);
}

View File

@@ -1,4 +1,4 @@
namespace Netch.Models
namespace Netch.Enums
{
public enum LogLevel
{

View File

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

View File

@@ -1,4 +1,4 @@
namespace Netch.Models
namespace Netch.Enums
{
/// <summary>
/// 状态

View File

@@ -7,5 +7,7 @@ namespace Netch
public static readonly bool IsWindows10Upper = Environment.OSVersion.Version.Major >= 10;
public static bool AlwaysShowNewVersionFound { get; set; }
public static bool NoSupport { get; set; }
}
}

View File

@@ -1,7 +1,6 @@
using Netch.Properties;
using Netch.Utils;
using System;
using System.Diagnostics;
using System.Windows.Forms;
namespace Netch.Forms

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

@@ -35,19 +35,19 @@
this.ModeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.CreateProcessModeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.CreateRouteTableRuleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.SubscribeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ManageSubscribeLinksToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.UpdateServersFromSubscribeLinksToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.SubscriptionToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ManageSubscriptionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.UpdateServersToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.OptionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.OpenDirectoryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ShowHideConsoleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.CleanDNSCacheToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.UninstallServiceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.removeNetchFirewallRulesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.RemoveNetchFirewallRulesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.HelpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.CheckForUpdatesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.fAQToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.CheckForUpdateToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.FAQToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ForceExitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.AboutToolStripButton = new System.Windows.Forms.ToolStripButton();
this.NewVersionLabel = new System.Windows.Forms.ToolStripLabel();
this.VersionLabel = new System.Windows.Forms.ToolStripLabel();
@@ -73,6 +73,7 @@
this.DownloadSpeedLabel = new System.Windows.Forms.ToolStripStatusLabel();
this.UploadSpeedLabel = new System.Windows.Forms.ToolStripStatusLabel();
this.blankToolStripStatusLabel = new System.Windows.Forms.ToolStripStatusLabel();
this.HttpStatusLabel = new System.Windows.Forms.ToolStripStatusLabel();
this.NatTypeStatusLabel = new System.Windows.Forms.ToolStripStatusLabel();
this.NatTypeStatusLightLabel = new System.Windows.Forms.ToolStripStatusLabel();
this.ControlButton = new System.Windows.Forms.Button();
@@ -85,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();
@@ -110,10 +112,10 @@
this.MenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.ServerToolStripMenuItem,
this.ModeToolStripMenuItem,
this.SubscribeToolStripMenuItem,
this.SubscriptionToolStripMenuItem,
this.OptionsToolStripMenuItem,
this.HelpToolStripMenuItem,
this.exitToolStripMenuItem,
this.ForceExitToolStripMenuItem,
this.AboutToolStripButton,
this.NewVersionLabel,
this.VersionLabel});
@@ -143,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);
@@ -163,29 +166,29 @@
this.CreateRouteTableRuleToolStripMenuItem.Text = "Create Route Table Rule";
this.CreateRouteTableRuleToolStripMenuItem.Click += new System.EventHandler(this.createRouteTableModeToolStripMenuItem_Click);
//
// SubscribeToolStripMenuItem
// SubscriptionToolStripMenuItem
//
this.SubscribeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.ManageSubscribeLinksToolStripMenuItem,
this.UpdateServersFromSubscribeLinksToolStripMenuItem});
this.SubscribeToolStripMenuItem.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1);
this.SubscribeToolStripMenuItem.Name = "SubscribeToolStripMenuItem";
this.SubscribeToolStripMenuItem.Size = new System.Drawing.Size(77, 21);
this.SubscribeToolStripMenuItem.Text = "Subscribe";
this.SubscriptionToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.ManageSubscriptionsToolStripMenuItem,
this.UpdateServersToolStripMenuItem});
this.SubscriptionToolStripMenuItem.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1);
this.SubscriptionToolStripMenuItem.Name = "SubscriptionToolStripMenuItem";
this.SubscriptionToolStripMenuItem.Size = new System.Drawing.Size(92, 21);
this.SubscriptionToolStripMenuItem.Text = "Subscription";
//
// ManageSubscribeLinksToolStripMenuItem
// ManageSubscriptionsToolStripMenuItem
//
this.ManageSubscribeLinksToolStripMenuItem.Name = "ManageSubscribeLinksToolStripMenuItem";
this.ManageSubscribeLinksToolStripMenuItem.Size = new System.Drawing.Size(294, 22);
this.ManageSubscribeLinksToolStripMenuItem.Text = "Manage Subscribe Links";
this.ManageSubscribeLinksToolStripMenuItem.Click += new System.EventHandler(this.ManageSubscribeLinksToolStripMenuItem_Click);
this.ManageSubscriptionsToolStripMenuItem.Name = "ManageSubscriptionsToolStripMenuItem";
this.ManageSubscriptionsToolStripMenuItem.Size = new System.Drawing.Size(206, 22);
this.ManageSubscriptionsToolStripMenuItem.Text = "Manage Subscriptions";
this.ManageSubscriptionsToolStripMenuItem.Click += new System.EventHandler(this.ManageSubscriptionLinksToolStripMenuItem_Click);
//
// UpdateServersFromSubscribeLinksToolStripMenuItem
// UpdateServersToolStripMenuItem
//
this.UpdateServersFromSubscribeLinksToolStripMenuItem.Name = "UpdateServersFromSubscribeLinksToolStripMenuItem";
this.UpdateServersFromSubscribeLinksToolStripMenuItem.Size = new System.Drawing.Size(294, 22);
this.UpdateServersFromSubscribeLinksToolStripMenuItem.Text = "Update Servers From Subscribe Links";
this.UpdateServersFromSubscribeLinksToolStripMenuItem.Click += new System.EventHandler(this.UpdateServersFromSubscribeLinksToolStripMenuItem_Click);
this.UpdateServersToolStripMenuItem.Name = "UpdateServersToolStripMenuItem";
this.UpdateServersToolStripMenuItem.Size = new System.Drawing.Size(206, 22);
this.UpdateServersToolStripMenuItem.Text = "Update Servers";
this.UpdateServersToolStripMenuItem.Click += new System.EventHandler(this.UpdateServersFromSubscriptionLinksToolStripMenuItem_Click);
//
// OptionsToolStripMenuItem
//
@@ -194,7 +197,7 @@
this.ShowHideConsoleToolStripMenuItem,
this.CleanDNSCacheToolStripMenuItem,
this.UninstallServiceToolStripMenuItem,
this.removeNetchFirewallRulesToolStripMenuItem});
this.RemoveNetchFirewallRulesToolStripMenuItem});
this.OptionsToolStripMenuItem.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1);
this.OptionsToolStripMenuItem.Name = "OptionsToolStripMenuItem";
this.OptionsToolStripMenuItem.Size = new System.Drawing.Size(66, 21);
@@ -228,43 +231,43 @@
this.UninstallServiceToolStripMenuItem.Text = "Uninstall NF Service";
this.UninstallServiceToolStripMenuItem.Click += new System.EventHandler(this.UninstallServiceToolStripMenuItem_Click);
//
// removeNetchFirewallRulesToolStripMenuItem
// RemoveNetchFirewallRulesToolStripMenuItem
//
this.removeNetchFirewallRulesToolStripMenuItem.Name = "removeNetchFirewallRulesToolStripMenuItem";
this.removeNetchFirewallRulesToolStripMenuItem.Size = new System.Drawing.Size(243, 22);
this.removeNetchFirewallRulesToolStripMenuItem.Text = "Remove Netch Firewall Rules";
this.removeNetchFirewallRulesToolStripMenuItem.Click += new System.EventHandler(this.RemoveNetchFirewallRulesToolStripMenuItem_Click);
this.RemoveNetchFirewallRulesToolStripMenuItem.Name = "RemoveNetchFirewallRulesToolStripMenuItem";
this.RemoveNetchFirewallRulesToolStripMenuItem.Size = new System.Drawing.Size(243, 22);
this.RemoveNetchFirewallRulesToolStripMenuItem.Text = "Remove Netch Firewall Rules";
this.RemoveNetchFirewallRulesToolStripMenuItem.Click += new System.EventHandler(this.RemoveNetchFirewallRulesToolStripMenuItem_Click);
//
// HelpToolStripMenuItem
//
this.HelpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.CheckForUpdatesToolStripMenuItem,
this.fAQToolStripMenuItem});
this.CheckForUpdateToolStripMenuItem,
this.FAQToolStripMenuItem});
this.HelpToolStripMenuItem.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1);
this.HelpToolStripMenuItem.Name = "HelpToolStripMenuItem";
this.HelpToolStripMenuItem.Size = new System.Drawing.Size(47, 21);
this.HelpToolStripMenuItem.Text = "Help";
//
// CheckForUpdatesToolStripMenuItem
// CheckForUpdateToolStripMenuItem
//
this.CheckForUpdatesToolStripMenuItem.Name = "CheckForUpdatesToolStripMenuItem";
this.CheckForUpdatesToolStripMenuItem.Size = new System.Drawing.Size(183, 22);
this.CheckForUpdatesToolStripMenuItem.Text = "Check for updates";
this.CheckForUpdatesToolStripMenuItem.Click += new System.EventHandler(this.CheckForUpdatesToolStripMenuItem_Click);
this.CheckForUpdateToolStripMenuItem.Name = "CheckForUpdateToolStripMenuItem";
this.CheckForUpdateToolStripMenuItem.Size = new System.Drawing.Size(177, 22);
this.CheckForUpdateToolStripMenuItem.Text = "Check for update";
this.CheckForUpdateToolStripMenuItem.Click += new System.EventHandler(this.CheckForUpdatesToolStripMenuItem_Click);
//
// fAQToolStripMenuItem
// FAQToolStripMenuItem
//
this.fAQToolStripMenuItem.Name = "fAQToolStripMenuItem";
this.fAQToolStripMenuItem.Size = new System.Drawing.Size(183, 22);
this.fAQToolStripMenuItem.Text = "FAQ";
this.fAQToolStripMenuItem.Click += new System.EventHandler(this.fAQToolStripMenuItem_Click);
this.FAQToolStripMenuItem.Name = "FAQToolStripMenuItem";
this.FAQToolStripMenuItem.Size = new System.Drawing.Size(177, 22);
this.FAQToolStripMenuItem.Text = "FAQ";
this.FAQToolStripMenuItem.Click += new System.EventHandler(this.fAQToolStripMenuItem_Click);
//
// exitToolStripMenuItem
// ForceExitToolStripMenuItem
//
this.exitToolStripMenuItem.Name = "exitToolStripMenuItem";
this.exitToolStripMenuItem.Size = new System.Drawing.Size(40, 22);
this.exitToolStripMenuItem.Text = "Exit";
this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click);
this.ForceExitToolStripMenuItem.Name = "ForceExitToolStripMenuItem";
this.ForceExitToolStripMenuItem.Size = new System.Drawing.Size(40, 22);
this.ForceExitToolStripMenuItem.Text = "Exit";
this.ForceExitToolStripMenuItem.Click += new System.EventHandler(this.ForceExitToolStripMenuItem_Click);
//
// AboutToolStripButton
//
@@ -521,6 +524,7 @@
this.DownloadSpeedLabel,
this.UploadSpeedLabel,
this.blankToolStripStatusLabel,
this.HttpStatusLabel,
this.NatTypeStatusLabel,
this.NatTypeStatusLightLabel});
this.StatusStrip.Location = new System.Drawing.Point(0, 272);
@@ -563,6 +567,15 @@
this.blankToolStripStatusLabel.Size = new System.Drawing.Size(494, 17);
this.blankToolStripStatusLabel.Spring = true;
//
// HttpStatusLabel
//
this.HttpStatusLabel.Name = "HttpStatusLabel";
this.HttpStatusLabel.Size = new System.Drawing.Size(41, 17);
this.HttpStatusLabel.Text = "HTTP:";
this.HttpStatusLabel.TextAlign = System.Drawing.ContentAlignment.BottomLeft;
this.HttpStatusLabel.Visible = false;
this.HttpStatusLabel.Click += new System.EventHandler(this.TcpStatusLabel_Click);
//
// NatTypeStatusLabel
//
this.NatTypeStatusLabel.Name = "NatTypeStatusLabel";
@@ -609,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);
//
@@ -686,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);
@@ -733,7 +753,7 @@
private System.Windows.Forms.ToolStripMenuItem CreateRouteTableRuleToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem removeNetchFirewallRulesToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem RemoveNetchFirewallRulesToolStripMenuItem;
private System.Windows.Forms.ToolStripButton AboutToolStripButton;
private System.Windows.Forms.ToolStripMenuItem CleanDNSCacheToolStripMenuItem;
@@ -748,9 +768,9 @@
private System.Windows.Forms.PictureBox EditModePictureBox;
private System.Windows.Forms.PictureBox EditServerPictureBox;
private System.Windows.Forms.ToolStripMenuItem ExitToolStripButton;
private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem ForceExitToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem ImportServersFromClipboardToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem ManageSubscribeLinksToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem ManageSubscriptionsToolStripMenuItem;
private System.Windows.Forms.MenuStrip MenuStrip;
public System.Windows.Forms.ComboBox ModeComboBox;
private System.Windows.Forms.Label ModeLabel;
@@ -765,7 +785,7 @@
private System.Windows.Forms.Label ProfileLabel;
private System.Windows.Forms.TextBox ProfileNameText;
private System.Windows.Forms.TableLayoutPanel ProfileTable;
private System.Windows.Forms.ToolStripMenuItem CheckForUpdatesToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem CheckForUpdateToolStripMenuItem;
private System.Windows.Forms.ComboBox ServerComboBox;
private System.Windows.Forms.Label ServerLabel;
private System.Windows.Forms.ToolStripMenuItem ServerToolStripMenuItem;
@@ -774,23 +794,25 @@
private System.Windows.Forms.PictureBox SpeedPictureBox;
private System.Windows.Forms.ToolStripStatusLabel StatusLabel;
private System.Windows.Forms.StatusStrip StatusStrip;
private System.Windows.Forms.ToolStripMenuItem SubscribeToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem SubscriptionToolStripMenuItem;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;
private System.Windows.Forms.ToolStripMenuItem UninstallServiceToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem UpdateServersFromSubscribeLinksToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem UpdateServersToolStripMenuItem;
private System.Windows.Forms.ToolStripStatusLabel UploadSpeedLabel;
private System.Windows.Forms.ToolStripStatusLabel UsedBandwidthLabel;
private System.Windows.Forms.ToolStripLabel NewVersionLabel;
private System.Windows.Forms.ToolStripLabel VersionLabel;
private System.Windows.Forms.ToolStripStatusLabel NatTypeStatusLightLabel;
private System.Windows.Forms.ToolStripStatusLabel blankToolStripStatusLabel;
private System.Windows.Forms.ToolStripMenuItem fAQToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem FAQToolStripMenuItem;
#endregion
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
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;
@@ -43,6 +44,9 @@ namespace Netch.Forms
#region i18N Translations
if (Flags.NoSupport)
_mainFormText.Add(Name, new[] { "{0} ({1})", "Netch", "No Support" });
_mainFormText.Add(UninstallServiceToolStripMenuItem.Name, new[] { "Uninstall {0}", "NF Service" });
#endregion
@@ -54,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
@@ -78,18 +82,15 @@ namespace Netch.Forms
LoadServers();
SelectLastServer();
ServerHelper.DelayTestHelper.UpdateInterval();
DelayTestHelper.UpdateTick(true);
ModeHelper.InitWatcher();
ModeHelper.Load();
LoadModes();
SelectLastMode();
ModeService.Instance.Load();
// 加载翻译
TranslateControls();
// 隐藏 NatTypeStatusLabel
NatTypeStatusText();
// 隐藏 ConnectivityStatusLabel
ConnectivityStatusVisible(false);
// 加载快速配置
LoadProfiles();
@@ -100,13 +101,13 @@ namespace Netch.Forms
// 检查订阅更新
if (Global.Settings.UpdateServersWhenOpened)
UpdateServersFromSubscribeAsync().Forget();
UpdateServersFromSubscriptionAsync().Forget();
// 打开软件时启动加速,产生开始按钮点击事件
if (Global.Settings.StartWhenOpened)
ControlButton.PerformClick();
Netch.SingleInstance.ListenForArgumentsFromSuccessiveInstances();
Program.SingleInstance.ListenForArgumentsFromSuccessiveInstances();
}
private void RecordSize()
@@ -212,15 +213,18 @@ namespace Netch.Forms
private async void ImportServersFromClipboardToolStripMenuItem_Click(object sender, EventArgs e)
{
var texts = Clipboard.GetText();
if (!string.IsNullOrWhiteSpace(texts))
{
var servers = ShareLink.ParseText(texts);
Global.Settings.Server.AddRange(servers);
NotifyTip(i18N.TranslateFormat("Import {0} server(s) form Clipboard", servers.Count));
if (string.IsNullOrWhiteSpace(texts))
return;
LoadServers();
await Configuration.SaveAsync();
}
var servers = ShareLink.ParseText(texts);
foreach (var server in servers)
server.Group = Constants.DefaultGroup;
Global.Settings.Server.AddRange(servers);
NotifyTip(i18N.TranslateFormat("Import {0} server(s) form Clipboard", servers.Count));
LoadServers();
await Configuration.SaveAsync();
}
private async void AddServerToolStripMenuItem_Click([NotNull] object? sender, EventArgs? e)
@@ -256,51 +260,64 @@ namespace Netch.Forms
Show();
}
private void ReloadModesToolStripMenuItem_Click(object sender, EventArgs e)
{
Enabled = false;
try
{
ModeService.Instance.Load();
}
finally
{
Enabled = true;
}
}
#endregion
#region Subscription
private void ManageSubscribeLinksToolStripMenuItem_Click(object sender, EventArgs e)
private void ManageSubscriptionLinksToolStripMenuItem_Click(object sender, EventArgs e)
{
Hide();
new SubscribeForm().ShowDialog();
new SubscriptionForm().ShowDialog();
LoadServers();
Show();
}
private async void UpdateServersFromSubscribeLinksToolStripMenuItem_Click(object sender, EventArgs e)
private async void UpdateServersFromSubscriptionLinksToolStripMenuItem_Click(object sender, EventArgs e)
{
await UpdateServersFromSubscribeAsync();
await UpdateServersFromSubscriptionAsync();
}
private async Task UpdateServersFromSubscribeAsync()
private async Task UpdateServersFromSubscriptionAsync()
{
void DisableItems(bool v)
{
MenuStrip.Enabled = ConfigurationGroupBox.Enabled = ProfileGroupBox.Enabled = ControlButton.Enabled = v;
}
if (Global.Settings.SubscribeLink.Count <= 0)
if (Global.Settings.Subscription.Count <= 0)
{
MessageBoxX.Show(i18N.Translate("No subscription link"));
return;
}
StatusText(i18N.Translate("Starting update subscription"));
StatusText(i18N.Translate("Updating servers"));
DisableItems(false);
try
{
await Subscription.UpdateServersAsync();
await SubscriptionUtil.UpdateServersAsync();
LoadServers();
await Configuration.SaveAsync();
StatusText(i18N.Translate("Subscription updated"));
StatusText(i18N.Translate("Servers updated"));
}
catch (Exception e)
{
NotifyTip(i18N.Translate("update servers failed") + "\n" + e.Message, info: false);
Log.Error("更新服务器 失败!" + e);
NotifyTip(i18N.Translate("Unhandled update servers error") + "\n" + e.Message, info: false);
Log.Error(e, "Unhandled Update servers error");
}
finally
{
@@ -321,7 +338,7 @@ namespace Netch.Forms
void OnNewVersionFoundFailed(object? o, EventArgs? args)
{
NotifyTip(i18N.Translate("New version found failed"), info: false);
NotifyTip(i18N.Translate("Check for update failed"), info: false);
}
try
@@ -389,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
@@ -399,7 +416,7 @@ namespace Netch.Forms
/// <summary>
/// 菜单栏强制退出
/// </summary>
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
private void ForceExitToolStripMenuItem_Click(object sender, EventArgs e)
{
Exit(true);
}
@@ -461,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();
@@ -469,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);
}
@@ -479,7 +495,7 @@ namespace Netch.Forms
}
catch (Exception exception)
{
Log.Error(exception, "更新未处理异常");
Log.Error(exception, "Unhandled Update error");
NotifyTip(exception.Message, info: false);
}
finally
@@ -498,7 +514,7 @@ namespace Netch.Forms
private void fAQToolStripMenuItem_Click(object sender, EventArgs e)
{
Utils.Utils.Open("https://netch.org/#/docs/zh-CN/faq");
Utils.Utils.Open("https://docs.netch.org");
}
#endregion
@@ -545,7 +561,8 @@ namespace Netch.Forms
State = State.Started;
Task.Run(Bandwidth.NetTraffic).Forget();
NatTestAsync().Forget();
DiscoveryNatTypeAsync().Forget();
HttpConnectAsync().Forget();
if (Global.Settings.MinimizeWhenStarted)
Minimize();
@@ -578,7 +595,7 @@ namespace Netch.Forms
private void SettingsButton_Click(object sender, EventArgs e)
{
var oldSettings = Global.Settings.Clone();
var oldSettings = Global.Settings.ShallowCopy();
Hide();
new SettingForm().ShowDialog();
@@ -592,7 +609,7 @@ namespace Netch.Forms
}
if (oldSettings.DetectionTick != Global.Settings.DetectionTick)
ServerHelper.DelayTestHelper.UpdateInterval();
DelayTestHelper.UpdateTick(true);
if (oldSettings.ProfileCount != Global.Settings.ProfileCount)
LoadProfiles();
@@ -663,7 +680,7 @@ namespace Netch.Forms
}
else
{
await ServerHelper.DelayTestHelper.TestAllDelayAsync();
await DelayTestHelper.PerformTestAsync(true);
Enable();
}
}
@@ -761,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;
}
}
@@ -793,7 +811,7 @@ namespace Netch.Forms
return;
}
ModeHelper.Delete((Mode)ModeComboBox.SelectedItem);
ModeService.Delete((Mode)ModeComboBox.SelectedItem);
SelectLastMode();
}
@@ -990,12 +1008,13 @@ namespace Netch.Forms
EditServerPictureBox.Enabled = DeleteModePictureBox.Enabled = DeleteServerPictureBox.Enabled = enabled;
// 启动需要禁用的控件
UninstallServiceToolStripMenuItem.Enabled = UpdateServersFromSubscribeLinksToolStripMenuItem.Enabled = enabled;
ServerToolStripMenuItem.Enabled = ModeToolStripMenuItem.Enabled =
SubscriptionToolStripMenuItem.Enabled = UninstallServiceToolStripMenuItem.Enabled = enabled;
}
_state = value;
ServerHelper.DelayTestHelper.Enabled = IsWaiting(_state);
DelayTestHelper.Enabled = IsWaiting(_state);
StatusText();
switch (value)
@@ -1025,7 +1044,7 @@ namespace Netch.Forms
ProfileGroupBox.Enabled = false;
BandwidthState(false);
NatTypeStatusText();
ConnectivityStatusVisible(false);
break;
case State.Stopped:
ControlButton.Enabled = true;
@@ -1053,18 +1072,17 @@ namespace Netch.Forms
private async Task StopCoreAsync()
{
State = State.Stopping;
_discoveryNatCts?.Cancel();
_httpConnectCts?.Cancel();
await MainController.StopAsync();
State = State.Stopped;
}
private bool IsWaiting()
{
return State == State.Waiting || State == State.Stopped;
}
private bool IsWaiting() => IsWaiting(_state);
private static bool IsWaiting(State state)
{
return state == State.Waiting || state == State.Stopped;
return state is State.Waiting or State.Stopped;
}
/// <summary>
@@ -1080,9 +1098,10 @@ namespace Netch.Forms
}
text ??= i18N.Translate(StateExtension.GetStatusString(State));
StatusLabel.Text = i18N.Translate("Status", ": ") + text;
if (_state == State.Started)
StatusLabel.Text += StatusPortInfoText.Value;
text += StatusPortInfoText.Value;
StatusLabel.Text = i18N.Translate("Status", ": ") + text;
}
public void BandwidthState(bool state)
@@ -1099,18 +1118,14 @@ namespace Netch.Forms
UsedBandwidthLabel.Visible /*= UploadSpeedLabel.Visible*/ = DownloadSpeedLabel.Visible = state;
}
private void NatTypeStatusText(string? text = null, string? country = null)
private void UpdateNatTypeStatusLabelText(string? text, string? country = null)
{
if (State != State.Started)
{
NatTypeStatusLabel.Text = "";
NatTypeStatusLabel.Visible = NatTypeStatusLightLabel.Visible = false;
return;
}
if (!string.IsNullOrEmpty(text))
{
NatTypeStatusLabel.Text = $"NAT{i18N.Translate(": ")}{text} {(!country.IsNullOrEmpty() ? $"[{country}]" : "")}";
if (country == null)
NatTypeStatusLabel.Text = $"NAT{i18N.Translate(": ")}{text} ";
else
NatTypeStatusLabel.Text = $"NAT{i18N.Translate(": ")}{text} [{country}]";
UpdateNatTypeLight(int.TryParse(text, out var natType) ? natType : -1);
}
@@ -1122,10 +1137,18 @@ namespace Netch.Forms
NatTypeStatusLabel.Visible = true;
}
private void ConnectivityStatusVisible(bool visible)
{
if (!visible)
HttpStatusLabel.Text = NatTypeStatusLabel.Text = "";
HttpStatusLabel.Visible = NatTypeStatusLabel.Visible = NatTypeStatusLightLabel.Visible = visible;
}
/// <summary>
/// 更新 NAT指示灯颜色
/// </summary>
/// <param name="natType"></param>
/// <param name="natType">NAT Type. keep default(-1) to Hide Light</param>
private void UpdateNatTypeLight(int natType = -1)
{
if (natType > 0 && natType < 5)
@@ -1148,46 +1171,81 @@ namespace Netch.Forms
}
}
private async void NatTypeStatusLabel_Click(object sender, EventArgs e)
private async void TcpStatusLabel_Click(object sender, EventArgs e)
{
if (_state == State.Started && !Monitor.IsEntered(_natTestLock))
await NatTestAsync();
await HttpConnectAsync();
}
private bool _natTestLock = true;
/// <summary>
/// 测试 NAT
/// </summary>
private async Task NatTestAsync()
private async void NatTypeStatusLabel_Click(object sender, EventArgs e)
{
if (!MainController.Mode!.TestNatRequired())
return;
await DiscoveryNatTypeAsync();
}
if (!_natTestLock)
return;
private CancellationTokenSource? _discoveryNatCts;
_natTestLock = false;
private async Task DiscoveryNatTypeAsync()
{
NatTypeStatusLabel.Enabled = false;
UpdateNatTypeStatusLabelText(i18N.Translate("Testing NAT Type"));
_discoveryNatCts = new CancellationTokenSource();
try
{
NatTypeStatusText(i18N.Translate("Testing NAT"));
var res = await MainController.DiscoveryNatTypeAsync(_discoveryNatCts.Token);
if (_discoveryNatCts.IsCancellationRequested)
return;
var (result, _, publicEnd) = await MainController.NTTController.StartAsync();
if (!string.IsNullOrEmpty(publicEnd))
if (!string.IsNullOrEmpty(res.PublicEnd))
{
var country = await Utils.Utils.GetCityCodeAsync(publicEnd!);
NatTypeStatusText(result, country);
var country = await Utils.Utils.GetCityCodeAsync(res.PublicEnd);
UpdateNatTypeStatusLabelText(res.Result, country);
if (int.TryParse(res.Result, out var natType))
UpdateNatTypeLight(natType);
else
UpdateNatTypeLight();
}
else
{
NatTypeStatusText(result ?? "Error");
UpdateNatTypeStatusLabelText(res.Result ?? "Error");
NatTypeStatusLightLabel.Visible = false;
}
}
finally
{
_natTestLock = true;
_discoveryNatCts.Dispose();
_discoveryNatCts = null;
NatTypeStatusLabel.Enabled = true;
}
}
private CancellationTokenSource? _httpConnectCts;
private async Task HttpConnectAsync()
{
HttpStatusLabel.Enabled = false;
_httpConnectCts = new CancellationTokenSource();
try
{
var res = await MainController.HttpConnectAsync(_httpConnectCts.Token);
if (_httpConnectCts.IsCancellationRequested)
return;
if (res != null)
HttpStatusLabel.Text = $"HTTP{i18N.Translate(": ")}{res}ms";
else
HttpStatusLabel.Text = $"HTTP{i18N.Translate(": ", "Timeout")}";
HttpStatusLabel.Visible = true;
}
finally
{
_httpConnectCts.Dispose();
_httpConnectCts = null;
HttpStatusLabel.Enabled = true;
}
}
@@ -1209,7 +1267,7 @@ namespace Netch.Forms
if (!IsWaiting())
{
_resumeFlag = true;
Log.Information("操作系统即将挂起,自动停止");
Log.Information("OS Suspend, Stop");
ControlButton_Click(null, null);
}
@@ -1218,7 +1276,7 @@ namespace Netch.Forms
if (_resumeFlag)
{
_resumeFlag = false;
Log.Information("操作系统即将从挂起状态继续,自动重启");
Log.Information("OS Resume, Restart");
ControlButton_Click(null, null);
}
@@ -1253,7 +1311,7 @@ namespace Netch.Forms
return;
}
State = State.Terminating;
// State = State.Terminating;
NotifyIcon.Visible = false;
Hide();
@@ -1445,6 +1503,7 @@ namespace Netch.Forms
}
case Mode item:
{
/*
// 绘制 模式Box 底色
e.Graphics.FillRectangle(Brushes.Gray, _numberBoxX, e.Bounds.Y, _numberBoxWidth, e.Bounds.Height);
@@ -1455,6 +1514,7 @@ namespace Netch.Forms
new Point(_numberBoxX + _numberBoxWrap, e.Bounds.Y),
Color.Black,
TextFormatFlags.Left);
*/
break;
}

View File

@@ -1,7 +1,7 @@
using Netch.Models;
using Netch.Utils;
using Netch.Utils;
using System;
using System.Windows.Forms;
using Netch.Enums;
namespace Netch.Forms
{

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

@@ -36,10 +36,7 @@ namespace Netch.Forms
this.PortGroupBox = new System.Windows.Forms.GroupBox();
this.Socks5PortLabel = new System.Windows.Forms.Label();
this.Socks5PortTextBox = new System.Windows.Forms.TextBox();
this.HTTPPortLabel = new System.Windows.Forms.Label();
this.HTTPPortTextBox = new System.Windows.Forms.TextBox();
this.AllowDevicesCheckBox = new System.Windows.Forms.CheckBox();
this.ResolveServerHostnameCheckBox = new System.Windows.Forms.CheckBox();
this.ServerPingTypeLabel = new System.Windows.Forms.Label();
this.ICMPingRadioBtn = new System.Windows.Forms.RadioButton();
this.TCPingRadioBtn = new System.Windows.Forms.RadioButton();
@@ -54,14 +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.DNSHijackCheckBox = new System.Windows.Forms.CheckBox();
this.DNSHijackHostTextBox = new System.Windows.Forms.TextBox();
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.RedirectorSSCheckBox = 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();
@@ -101,6 +100,7 @@ namespace Netch.Forms
this.MinimizeWhenStartedCheckBox = new System.Windows.Forms.CheckBox();
this.RunAtStartupCheckBox = new System.Windows.Forms.CheckBox();
this.CheckUpdateWhenOpenedCheckBox = new System.Windows.Forms.CheckBox();
this.NoSupportDialogCheckBox = new System.Windows.Forms.CheckBox();
this.CheckBetaUpdateCheckBox = new System.Windows.Forms.CheckBox();
this.UpdateServersWhenOpenedCheckBox = new System.Windows.Forms.CheckBox();
this.AioDNSTabPage = new System.Windows.Forms.TabPage();
@@ -144,7 +144,6 @@ namespace Netch.Forms
//
this.GeneralTabPage.BackColor = System.Drawing.SystemColors.ButtonFace;
this.GeneralTabPage.Controls.Add(this.PortGroupBox);
this.GeneralTabPage.Controls.Add(this.ResolveServerHostnameCheckBox);
this.GeneralTabPage.Controls.Add(this.ServerPingTypeLabel);
this.GeneralTabPage.Controls.Add(this.ICMPingRadioBtn);
this.GeneralTabPage.Controls.Add(this.TCPingRadioBtn);
@@ -169,8 +168,6 @@ namespace Netch.Forms
//
this.PortGroupBox.Controls.Add(this.Socks5PortLabel);
this.PortGroupBox.Controls.Add(this.Socks5PortTextBox);
this.PortGroupBox.Controls.Add(this.HTTPPortLabel);
this.PortGroupBox.Controls.Add(this.HTTPPortTextBox);
this.PortGroupBox.Controls.Add(this.AllowDevicesCheckBox);
this.PortGroupBox.Location = new System.Drawing.Point(8, 6);
this.PortGroupBox.Name = "PortGroupBox";
@@ -196,23 +193,6 @@ namespace Netch.Forms
this.Socks5PortTextBox.TabIndex = 1;
this.Socks5PortTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// HTTPPortLabel
//
this.HTTPPortLabel.AutoSize = true;
this.HTTPPortLabel.Location = new System.Drawing.Point(9, 54);
this.HTTPPortLabel.Name = "HTTPPortLabel";
this.HTTPPortLabel.Size = new System.Drawing.Size(38, 17);
this.HTTPPortLabel.TabIndex = 2;
this.HTTPPortLabel.Text = "HTTP";
//
// HTTPPortTextBox
//
this.HTTPPortTextBox.Location = new System.Drawing.Point(120, 51);
this.HTTPPortTextBox.Name = "HTTPPortTextBox";
this.HTTPPortTextBox.Size = new System.Drawing.Size(90, 23);
this.HTTPPortTextBox.TabIndex = 3;
this.HTTPPortTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// AllowDevicesCheckBox
//
this.AllowDevicesCheckBox.AutoSize = true;
@@ -224,20 +204,10 @@ namespace Netch.Forms
this.AllowDevicesCheckBox.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
this.AllowDevicesCheckBox.UseVisualStyleBackColor = true;
//
// ResolveServerHostnameCheckBox
//
this.ResolveServerHostnameCheckBox.AutoSize = true;
this.ResolveServerHostnameCheckBox.Location = new System.Drawing.Point(267, 15);
this.ResolveServerHostnameCheckBox.Name = "ResolveServerHostnameCheckBox";
this.ResolveServerHostnameCheckBox.Size = new System.Drawing.Size(176, 21);
this.ResolveServerHostnameCheckBox.TabIndex = 1;
this.ResolveServerHostnameCheckBox.Text = "Resolve Server Hostname";
this.ResolveServerHostnameCheckBox.UseVisualStyleBackColor = true;
//
// ServerPingTypeLabel
//
this.ServerPingTypeLabel.AutoSize = true;
this.ServerPingTypeLabel.Location = new System.Drawing.Point(267, 44);
this.ServerPingTypeLabel.Location = new System.Drawing.Point(267, 15);
this.ServerPingTypeLabel.Name = "ServerPingTypeLabel";
this.ServerPingTypeLabel.Size = new System.Drawing.Size(86, 17);
this.ServerPingTypeLabel.TabIndex = 2;
@@ -246,7 +216,7 @@ namespace Netch.Forms
// ICMPingRadioBtn
//
this.ICMPingRadioBtn.AutoSize = true;
this.ICMPingRadioBtn.Location = new System.Drawing.Point(268, 63);
this.ICMPingRadioBtn.Location = new System.Drawing.Point(268, 34);
this.ICMPingRadioBtn.Name = "ICMPingRadioBtn";
this.ICMPingRadioBtn.Size = new System.Drawing.Size(75, 21);
this.ICMPingRadioBtn.TabIndex = 3;
@@ -257,7 +227,7 @@ namespace Netch.Forms
// TCPingRadioBtn
//
this.TCPingRadioBtn.AutoSize = true;
this.TCPingRadioBtn.Location = new System.Drawing.Point(366, 64);
this.TCPingRadioBtn.Location = new System.Drawing.Point(366, 35);
this.TCPingRadioBtn.Name = "TCPingRadioBtn";
this.TCPingRadioBtn.Size = new System.Drawing.Size(66, 21);
this.TCPingRadioBtn.TabIndex = 4;
@@ -354,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.DNSHijackCheckBox);
this.NFTabPage.Controls.Add(this.DNSHijackHostTextBox);
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.RedirectorSSCheckBox);
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";
@@ -370,90 +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;
//
// DNSHijackCheckBox
//
this.DNSHijackCheckBox.AutoSize = true;
this.DNSHijackCheckBox.Location = new System.Drawing.Point(15, 50);
this.DNSHijackCheckBox.Name = "DNSHijackCheckBox";
this.DNSHijackCheckBox.Size = new System.Drawing.Size(196, 21);
this.DNSHijackCheckBox.TabIndex = 2;
this.DNSHijackCheckBox.Text = "Handle process\'s DNS Hijack";
this.DNSHijackCheckBox.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, 48);
this.DNSHijackHostTextBox.Name = "DNSHijackHostTextBox";
this.DNSHijackHostTextBox.Size = new System.Drawing.Size(191, 23);
this.DNSHijackHostTextBox.TabIndex = 3;
this.DNSHijackHostTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
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(13, 80);
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 = 4;
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(30, 110);
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 = 5;
this.ICMPDelayLabel.Text = "ICMP Delay(ms)";
this.ICMPDelayLabel.TabIndex = 3;
this.ICMPDelayLabel.Text = "ICMP delay(ms)";
//
// ICMPDelayTextBox
//
this.ICMPDelayTextBox.Location = new System.Drawing.Point(237, 107);
this.ICMPDelayTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", this.FilterICMPCheckBox, "Checked", true));
this.ICMPDelayTextBox.Location = new System.Drawing.Point(216, 80);
this.ICMPDelayTextBox.Name = "ICMPDelayTextBox";
this.ICMPDelayTextBox.ReadOnly = true;
this.ICMPDelayTextBox.Size = new System.Drawing.Size(98, 23);
this.ICMPDelayTextBox.TabIndex = 6;
this.ICMPDelayTextBox.TabIndex = 4;
this.ICMPDelayTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// RedirectorSSCheckBox
// FilterDNSCheckBox
//
this.RedirectorSSCheckBox.AutoSize = true;
this.RedirectorSSCheckBox.Location = new System.Drawing.Point(15, 140);
this.RedirectorSSCheckBox.Name = "RedirectorSSCheckBox";
this.RedirectorSSCheckBox.Size = new System.Drawing.Size(265, 21);
this.RedirectorSSCheckBox.TabIndex = 7;
this.RedirectorSSCheckBox.Text = "Redirector built-in Shadowsocks support";
this.RedirectorSSCheckBox.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.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.Enabled = false;
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 = 8;
this.ChildProcessHandleCheckBox.Text = "Child Process Handle";
this.ChildProcessHandleCheckBox.TabIndex = 9;
this.ChildProcessHandleCheckBox.Text = "Handle child process";
this.ChildProcessHandleCheckBox.UseVisualStyleBackColor = true;
//
// WinTUNTabPage
@@ -562,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);
//
@@ -773,6 +767,7 @@ namespace Netch.Forms
this.OtherTabPage.Controls.Add(this.MinimizeWhenStartedCheckBox);
this.OtherTabPage.Controls.Add(this.RunAtStartupCheckBox);
this.OtherTabPage.Controls.Add(this.CheckUpdateWhenOpenedCheckBox);
this.OtherTabPage.Controls.Add(this.NoSupportDialogCheckBox);
this.OtherTabPage.Controls.Add(this.CheckBetaUpdateCheckBox);
this.OtherTabPage.Controls.Add(this.UpdateServersWhenOpenedCheckBox);
this.OtherTabPage.Location = new System.Drawing.Point(4, 29);
@@ -785,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;
@@ -796,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;
@@ -807,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;
@@ -818,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;
@@ -828,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;
@@ -838,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;
@@ -846,13 +841,23 @@ namespace Netch.Forms
this.CheckUpdateWhenOpenedCheckBox.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
this.CheckUpdateWhenOpenedCheckBox.UseVisualStyleBackColor = true;
//
// NoSupportDialogCheckBox
//
this.NoSupportDialogCheckBox.AutoSize = true;
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;
this.NoSupportDialogCheckBox.Text = "Disable Support Warning";
this.NoSupportDialogCheckBox.UseVisualStyleBackColor = true;
//
// 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 = 6;
this.CheckBetaUpdateCheckBox.TabIndex = 7;
this.CheckBetaUpdateCheckBox.Text = "Check Beta update";
this.CheckBetaUpdateCheckBox.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
this.CheckBetaUpdateCheckBox.UseVisualStyleBackColor = true;
@@ -860,10 +865,10 @@ 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 = 7;
this.UpdateServersWhenOpenedCheckBox.TabIndex = 8;
this.UpdateServersWhenOpenedCheckBox.Text = "Update Servers when opened";
this.UpdateServersWhenOpenedCheckBox.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
this.UpdateServersWhenOpenedCheckBox.UseVisualStyleBackColor = true;
@@ -1008,11 +1013,8 @@ namespace Netch.Forms
private System.Windows.Forms.TabPage v2rayTabPage;
private System.Windows.Forms.GroupBox PortGroupBox;
private System.Windows.Forms.CheckBox AllowDevicesCheckBox;
private System.Windows.Forms.Label HTTPPortLabel;
private System.Windows.Forms.TextBox HTTPPortTextBox;
private System.Windows.Forms.Label Socks5PortLabel;
private System.Windows.Forms.TextBox Socks5PortTextBox;
private System.Windows.Forms.CheckBox ResolveServerHostnameCheckBox;
private System.Windows.Forms.GroupBox WinTUNGroupBox;
private System.Windows.Forms.CheckBox ProxyDNSCheckBox;
private System.Windows.Forms.CheckBox UseCustomDNSCheckBox;
@@ -1025,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;
@@ -1070,15 +1072,18 @@ namespace Netch.Forms
private System.Windows.Forms.TextBox OtherDNSTextBox;
private System.Windows.Forms.TextBox ChinaDNSTextBox;
private System.Windows.Forms.TextBox DNSHijackHostTextBox;
private System.Windows.Forms.CheckBox RedirectorSSCheckBox;
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();
@@ -26,29 +20,19 @@ namespace Netch.Forms
#region General
BindTextBox<ushort>(Socks5PortTextBox,
p => p.ToString() != HTTPPortTextBox.Text,
p => Global.Settings.Socks5LocalPort = p,
Global.Settings.Socks5LocalPort);
BindTextBox<ushort>(HTTPPortTextBox,
p => p.ToString() != Socks5PortTextBox.Text,
p => Global.Settings.HTTPLocalPort = p,
Global.Settings.HTTPLocalPort);
BindTextBox<ushort>(Socks5PortTextBox, p => true, p => Global.Settings.Socks5LocalPort = p, Global.Settings.Socks5LocalPort);
BindCheckBox(AllowDevicesCheckBox,
c => Global.Settings.LocalAddress = AllowDevicesCheckBox.Checked ? "0.0.0.0" : "127.0.0.1",
Global.Settings.LocalAddress switch { "127.0.0.1" => false, "0.0.0.0" => true, _ => false });
BindCheckBox(ResolveServerHostnameCheckBox, c => Global.Settings.ResolveServerHostname = c, Global.Settings.ResolveServerHostname);
BindRadioBox(ICMPingRadioBtn, _ => { }, !Global.Settings.ServerTCPing);
BindRadioBox(TCPingRadioBtn, c => Global.Settings.ServerTCPing = c, Global.Settings.ServerTCPing);
BindTextBox<int>(ProfileCountTextBox, i => i > -1, i => Global.Settings.ProfileCount = i, Global.Settings.ProfileCount);
BindTextBox<int>(DetectionTickTextBox,
i => ServerHelper.DelayTestHelper.Range.InRange(i),
i => DelayTestHelper.Range.InRange(i),
i => Global.Settings.DetectionTick = i,
Global.Settings.DetectionTick);
@@ -99,24 +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(DNSHijackCheckBox, b => Global.Settings.Redirector.DNSHijack = b, Global.Settings.Redirector.DNSHijack);
BindTextBox(DNSHijackHostTextBox, s => true, s => Global.Settings.Redirector.DNSHijackHost = s, Global.Settings.Redirector.DNSHijackHost);
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(ICMPDelayTextBox, s => int.TryParse(s, out _), s => { }, Global.Settings.Redirector.ICMPDelay);
BindTextBox<int>(ICMPDelayTextBox, s => true, s => Global.Settings.Redirector.ICMPDelay = s, Global.Settings.Redirector.ICMPDelay);
BindCheckBox(RedirectorSSCheckBox, s => Global.Settings.Redirector.RedirectorSS = s, Global.Settings.Redirector.RedirectorSS);
BindCheckBox(FilterDNSCheckBox, b => Global.Settings.Redirector.FilterDNS = b, Global.Settings.Redirector.FilterDNS);
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
@@ -205,6 +190,8 @@ namespace Netch.Forms
BindCheckBox(UpdateServersWhenOpenedCheckBox, b => Global.Settings.UpdateServersWhenOpened = b, Global.Settings.UpdateServersWhenOpened);
BindCheckBox(NoSupportDialogCheckBox, b => Global.Settings.NoSupportDialog = b, Global.Settings.NoSupportDialog);
#endregion
#region AioDNS
@@ -247,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);
@@ -258,8 +245,7 @@ namespace Netch.Forms
#region Save
foreach (var pair in _saveActions)
pair.Value.Invoke(pair.Key);
SaveBinds();
#endregion
@@ -269,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

@@ -1,6 +1,6 @@
namespace Netch.Forms
{
partial class SubscribeForm
partial class SubscriptionForm
{
/// <summary>
/// Required designer variable.
@@ -29,24 +29,23 @@
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SubscribeForm));
this.AddSubscriptionBox = new System.Windows.Forms.GroupBox();
this.RemarkLabel = new System.Windows.Forms.Label();
this.RemarkTextBox = new System.Windows.Forms.TextBox();
this.LinkLabel = new System.Windows.Forms.Label();
this.LinkTextBox = new System.Windows.Forms.TextBox();
this.UserAgentLabel = new System.Windows.Forms.Label();
this.UserAgentTextBox = new System.Windows.Forms.TextBox();
this.UnselectButton = new System.Windows.Forms.Button();
this.AddButton = new System.Windows.Forms.Button();
this.UserAgentLabel = new System.Windows.Forms.Label();
this.LinkTextBox = new System.Windows.Forms.TextBox();
this.LinkLabel = new System.Windows.Forms.Label();
this.RemarkTextBox = new System.Windows.Forms.TextBox();
this.RemarkLabel = new System.Windows.Forms.Label();
this.SubscribeLinkListView = new System.Windows.Forms.ListView();
this.SubscriptionLinkListView = new System.Windows.Forms.ListView();
this.EnableColumnHeader = new System.Windows.Forms.ColumnHeader();
this.RemarkColumnHeader = new System.Windows.Forms.ColumnHeader();
this.LinkColumnHeader = new System.Windows.Forms.ColumnHeader();
this.UserAgentHeader = new System.Windows.Forms.ColumnHeader();
this.pContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
this.DeleteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.deleteServerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.DeleteServersToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.CopyLinkToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.MainTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.AddSubscriptionBox.SuspendLayout();
@@ -56,14 +55,14 @@
//
// AddSubscriptionBox
//
this.AddSubscriptionBox.Controls.Add(this.RemarkLabel);
this.AddSubscriptionBox.Controls.Add(this.RemarkTextBox);
this.AddSubscriptionBox.Controls.Add(this.LinkLabel);
this.AddSubscriptionBox.Controls.Add(this.LinkTextBox);
this.AddSubscriptionBox.Controls.Add(this.UserAgentLabel);
this.AddSubscriptionBox.Controls.Add(this.UserAgentTextBox);
this.AddSubscriptionBox.Controls.Add(this.UnselectButton);
this.AddSubscriptionBox.Controls.Add(this.AddButton);
this.AddSubscriptionBox.Controls.Add(this.UserAgentLabel);
this.AddSubscriptionBox.Controls.Add(this.LinkTextBox);
this.AddSubscriptionBox.Controls.Add(this.LinkLabel);
this.AddSubscriptionBox.Controls.Add(this.RemarkTextBox);
this.AddSubscriptionBox.Controls.Add(this.RemarkLabel);
this.AddSubscriptionBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.AddSubscriptionBox.Location = new System.Drawing.Point(8, 248);
this.AddSubscriptionBox.Name = "AddSubscriptionBox";
@@ -71,6 +70,47 @@
this.AddSubscriptionBox.TabIndex = 1;
this.AddSubscriptionBox.TabStop = false;
//
// RemarkLabel
//
this.RemarkLabel.AutoSize = true;
this.RemarkLabel.Location = new System.Drawing.Point(11, 19);
this.RemarkLabel.Name = "RemarkLabel";
this.RemarkLabel.Size = new System.Drawing.Size(53, 17);
this.RemarkLabel.TabIndex = 1;
this.RemarkLabel.Text = "Remark";
//
// RemarkTextBox
//
this.RemarkTextBox.Location = new System.Drawing.Point(109, 16);
this.RemarkTextBox.Name = "RemarkTextBox";
this.RemarkTextBox.Size = new System.Drawing.Size(545, 23);
this.RemarkTextBox.TabIndex = 2;
//
// LinkLabel
//
this.LinkLabel.AutoSize = true;
this.LinkLabel.Location = new System.Drawing.Point(11, 48);
this.LinkLabel.Name = "LinkLabel";
this.LinkLabel.Size = new System.Drawing.Size(31, 17);
this.LinkLabel.TabIndex = 3;
this.LinkLabel.Text = "Link";
//
// LinkTextBox
//
this.LinkTextBox.Location = new System.Drawing.Point(109, 45);
this.LinkTextBox.Name = "LinkTextBox";
this.LinkTextBox.Size = new System.Drawing.Size(545, 23);
this.LinkTextBox.TabIndex = 4;
//
// UserAgentLabel
//
this.UserAgentLabel.AutoSize = true;
this.UserAgentLabel.Location = new System.Drawing.Point(11, 77);
this.UserAgentLabel.Name = "UserAgentLabel";
this.UserAgentLabel.Size = new System.Drawing.Size(74, 17);
this.UserAgentLabel.TabIndex = 5;
this.UserAgentLabel.Text = "User-Agent";
//
// UserAgentTextBox
//
this.UserAgentTextBox.Location = new System.Drawing.Point(109, 74);
@@ -98,68 +138,28 @@
this.AddButton.UseVisualStyleBackColor = true;
this.AddButton.Click += new System.EventHandler(this.AddButton_Click);
//
// UserAgentLabel
// SubscriptionLinkListView
//
this.UserAgentLabel.AutoSize = true;
this.UserAgentLabel.Location = new System.Drawing.Point(11, 77);
this.UserAgentLabel.Name = "UserAgentLabel";
this.UserAgentLabel.Size = new System.Drawing.Size(74, 17);
this.UserAgentLabel.TabIndex = 5;
this.UserAgentLabel.Text = "User-Agent";
//
// LinkTextBox
//
this.LinkTextBox.Location = new System.Drawing.Point(109, 45);
this.LinkTextBox.Name = "LinkTextBox";
this.LinkTextBox.Size = new System.Drawing.Size(545, 23);
this.LinkTextBox.TabIndex = 4;
//
// LinkLabel
//
this.LinkLabel.AutoSize = true;
this.LinkLabel.Location = new System.Drawing.Point(11, 48);
this.LinkLabel.Name = "LinkLabel";
this.LinkLabel.Size = new System.Drawing.Size(31, 17);
this.LinkLabel.TabIndex = 3;
this.LinkLabel.Text = "Link";
//
// RemarkTextBox
//
this.RemarkTextBox.Location = new System.Drawing.Point(109, 16);
this.RemarkTextBox.Name = "RemarkTextBox";
this.RemarkTextBox.Size = new System.Drawing.Size(545, 23);
this.RemarkTextBox.TabIndex = 2;
//
// RemarkLabel
//
this.RemarkLabel.AutoSize = true;
this.RemarkLabel.Location = new System.Drawing.Point(11, 19);
this.RemarkLabel.Name = "RemarkLabel";
this.RemarkLabel.Size = new System.Drawing.Size(53, 17);
this.RemarkLabel.TabIndex = 1;
this.RemarkLabel.Text = "Remark";
//
// SubscribeLinkListView
//
this.SubscribeLinkListView.AllowColumnReorder = true;
this.SubscribeLinkListView.CheckBoxes = true;
this.SubscribeLinkListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[]
{
this.EnableColumnHeader, this.RemarkColumnHeader, this.LinkColumnHeader, this.UserAgentHeader
});
this.SubscribeLinkListView.Dock = System.Windows.Forms.DockStyle.Fill;
this.SubscribeLinkListView.FullRowSelect = true;
this.SubscribeLinkListView.HideSelection = false;
this.SubscribeLinkListView.Location = new System.Drawing.Point(8, 8);
this.SubscribeLinkListView.MultiSelect = false;
this.SubscribeLinkListView.Name = "SubscribeLinkListView";
this.SubscribeLinkListView.Size = new System.Drawing.Size(668, 234);
this.SubscribeLinkListView.TabIndex = 0;
this.SubscribeLinkListView.UseCompatibleStateImageBehavior = false;
this.SubscribeLinkListView.View = System.Windows.Forms.View.Details;
this.SubscribeLinkListView.ItemChecked += new System.Windows.Forms.ItemCheckedEventHandler(this.SubscribeLinkListView_ItemChecked);
this.SubscribeLinkListView.SelectedIndexChanged += new System.EventHandler(this.SubscribeLinkListView_SelectedIndexChanged);
this.SubscribeLinkListView.MouseUp += new System.Windows.Forms.MouseEventHandler(this.SubscribeLinkListView_MouseUp);
this.SubscriptionLinkListView.AllowColumnReorder = true;
this.SubscriptionLinkListView.CheckBoxes = true;
this.SubscriptionLinkListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.EnableColumnHeader,
this.RemarkColumnHeader,
this.LinkColumnHeader,
this.UserAgentHeader});
this.SubscriptionLinkListView.Dock = System.Windows.Forms.DockStyle.Fill;
this.SubscriptionLinkListView.FullRowSelect = true;
this.SubscriptionLinkListView.HideSelection = false;
this.SubscriptionLinkListView.Location = new System.Drawing.Point(8, 8);
this.SubscriptionLinkListView.MultiSelect = false;
this.SubscriptionLinkListView.Name = "SubscriptionLinkListView";
this.SubscriptionLinkListView.Size = new System.Drawing.Size(668, 234);
this.SubscriptionLinkListView.TabIndex = 0;
this.SubscriptionLinkListView.UseCompatibleStateImageBehavior = false;
this.SubscriptionLinkListView.View = System.Windows.Forms.View.Details;
this.SubscriptionLinkListView.ItemChecked += new System.Windows.Forms.ItemCheckedEventHandler(this.SubscriptionLinkListView_ItemChecked);
this.SubscriptionLinkListView.SelectedIndexChanged += new System.EventHandler(this.SubscriptionLinkListView_SelectedIndexChanged);
this.SubscriptionLinkListView.MouseUp += new System.Windows.Forms.MouseEventHandler(this.SubscriptionLinkListView_MouseUp);
//
// EnableColumnHeader
//
@@ -182,39 +182,39 @@
//
// pContextMenuStrip
//
this.pContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[]
{
this.DeleteToolStripMenuItem, this.deleteServerToolStripMenuItem, this.CopyLinkToolStripMenuItem
});
this.pContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.DeleteToolStripMenuItem,
this.DeleteServersToolStripMenuItem,
this.CopyLinkToolStripMenuItem});
this.pContextMenuStrip.Name = "pContextMenuStrip";
this.pContextMenuStrip.Size = new System.Drawing.Size(151, 70);
this.pContextMenuStrip.Size = new System.Drawing.Size(161, 70);
//
// DeleteToolStripMenuItem
//
this.DeleteToolStripMenuItem.Name = "DeleteToolStripMenuItem";
this.DeleteToolStripMenuItem.Size = new System.Drawing.Size(150, 22);
this.DeleteToolStripMenuItem.Size = new System.Drawing.Size(160, 22);
this.DeleteToolStripMenuItem.Text = "Delete";
this.DeleteToolStripMenuItem.Click += new System.EventHandler(this.DeleteToolStripMenuItem_Click);
//
// deleteServerToolStripMenuItem
// DeleteServersToolStripMenuItem
//
this.deleteServerToolStripMenuItem.Name = "deleteServerToolStripMenuItem";
this.deleteServerToolStripMenuItem.Size = new System.Drawing.Size(150, 22);
this.deleteServerToolStripMenuItem.Text = "DeleteServer";
this.deleteServerToolStripMenuItem.Click += new System.EventHandler(this.deleteServerToolStripMenuItem_Click);
this.DeleteServersToolStripMenuItem.Name = "DeleteServersToolStripMenuItem";
this.DeleteServersToolStripMenuItem.Size = new System.Drawing.Size(160, 22);
this.DeleteServersToolStripMenuItem.Text = "Delete Servers";
this.DeleteServersToolStripMenuItem.Click += new System.EventHandler(this.DeleteServersToolStripMenuItem_Click);
//
// CopyLinkToolStripMenuItem
//
this.CopyLinkToolStripMenuItem.Name = "CopyLinkToolStripMenuItem";
this.CopyLinkToolStripMenuItem.Size = new System.Drawing.Size(150, 22);
this.CopyLinkToolStripMenuItem.Text = "CopyLink";
this.CopyLinkToolStripMenuItem.Size = new System.Drawing.Size(160, 22);
this.CopyLinkToolStripMenuItem.Text = "Copy link";
this.CopyLinkToolStripMenuItem.Click += new System.EventHandler(this.CopyLinkToolStripMenuItem_Click);
//
// MainTableLayoutPanel
//
this.MainTableLayoutPanel.ColumnCount = 1;
this.MainTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.MainTableLayoutPanel.Controls.Add(this.SubscribeLinkListView, 0, 0);
this.MainTableLayoutPanel.Controls.Add(this.SubscriptionLinkListView, 0, 0);
this.MainTableLayoutPanel.Controls.Add(this.AddSubscriptionBox, 0, 1);
this.MainTableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.MainTableLayoutPanel.Location = new System.Drawing.Point(0, 0);
@@ -227,25 +227,26 @@
this.MainTableLayoutPanel.Size = new System.Drawing.Size(684, 391);
this.MainTableLayoutPanel.TabIndex = 11;
//
// SubscribeForm
// SubscriptionForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.ClientSize = new System.Drawing.Size(684, 391);
this.Controls.Add(this.MainTableLayoutPanel);
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) (134)));
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
this.MaximizeBox = false;
this.Name = "SubscribeForm";
this.Name = "SubscriptionForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Subscribe";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.SubscribeForm_FormClosing);
this.Text = "Subscription";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.SubscriptionForm_FormClosing);
this.AddSubscriptionBox.ResumeLayout(false);
this.AddSubscriptionBox.PerformLayout();
this.pContextMenuStrip.ResumeLayout(false);
this.MainTableLayoutPanel.ResumeLayout(false);
this.ResumeLayout(false);
}
private System.Windows.Forms.ColumnHeader EnableColumnHeader;
@@ -257,7 +258,7 @@
private System.Windows.Forms.Label LinkLabel;
private System.Windows.Forms.TextBox RemarkTextBox;
private System.Windows.Forms.Button AddButton;
private System.Windows.Forms.ListView SubscribeLinkListView;
private System.Windows.Forms.ListView SubscriptionLinkListView;
private System.Windows.Forms.ColumnHeader RemarkColumnHeader;
private System.Windows.Forms.ColumnHeader LinkColumnHeader;
private System.Windows.Forms.ContextMenuStrip pContextMenuStrip;
@@ -269,6 +270,6 @@
#endregion
private System.Windows.Forms.ToolStripMenuItem deleteServerToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem DeleteServersToolStripMenuItem;
}
}

View File

@@ -1,15 +1,15 @@
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
using System;
using System;
using System.Linq;
using System.Windows.Forms;
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
namespace Netch.Forms
{
public partial class SubscribeForm : Form
public partial class SubscriptionForm : Form
{
public SubscribeForm()
public SubscriptionForm()
{
InitializeComponent();
Icon = Resources.icon;
@@ -17,33 +17,33 @@ namespace Netch.Forms
i18N.TranslateForm(this);
i18N.TranslateForm(pContextMenuStrip);
InitSubscribeLink();
LoadSubscriptionLinks();
}
private int SelectedIndex
{
get
{
if (SubscribeLinkListView.MultiSelect)
if (SubscriptionLinkListView.MultiSelect)
throw new Exception();
return SubscribeLinkListView.SelectedIndices.Count == 0 ? -1 : SubscribeLinkListView.SelectedIndices[0];
return SubscriptionLinkListView.SelectedIndices.Count == 0 ? -1 : SubscriptionLinkListView.SelectedIndices[0];
}
}
#region EventHandler
private void SubscribeLinkListView_MouseUp(object sender, MouseEventArgs e)
private void SubscriptionLinkListView_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
if (SelectedIndex != -1)
pContextMenuStrip.Show(SubscribeLinkListView, e.Location);
pContextMenuStrip.Show(SubscriptionLinkListView, e.Location);
}
/// <summary>
/// 选中/取消选中
/// </summary>
private void SubscribeLinkListView_SelectedIndexChanged(object sender, EventArgs e)
private void SubscriptionLinkListView_SelectedIndexChanged(object sender, EventArgs e)
{
SetEditingGroup(SelectedIndex);
}
@@ -51,13 +51,13 @@ namespace Netch.Forms
/// <summary>
/// 订阅启/禁用
/// </summary>
private void SubscribeLinkListView_ItemChecked(object sender, ItemCheckedEventArgs e)
private void SubscriptionLinkListView_ItemChecked(object sender, ItemCheckedEventArgs e)
{
var index = e.Item.Index;
Global.Settings.SubscribeLink[index].Enable = SubscribeLinkListView.Items[index].Checked;
Global.Settings.Subscription[index].Enable = SubscriptionLinkListView.Items[index].Checked;
}
private async void SubscribeForm_FormClosing(object sender, FormClosingEventArgs e)
private async void SubscriptionForm_FormClosing(object sender, FormClosingEventArgs e)
{
await Configuration.SaveAsync();
}
@@ -94,13 +94,13 @@ namespace Netch.Forms
if (SelectedIndex == -1)
{
if (Global.Settings.SubscribeLink.Any(link => link.Remark.Equals(RemarkTextBox.Text)))
if (Global.Settings.Subscription.Any(link => link.Remark.Equals(RemarkTextBox.Text)))
{
MessageBoxX.Show("Remark Name Duplicate!");
MessageBoxX.Show(i18N.Translate("Subscription with the specified remark already exists"));
return;
}
Global.Settings.SubscribeLink.Add(new SubscribeLink
Global.Settings.Subscription.Add(new Subscription
{
Enable = true,
Remark = RemarkTextBox.Text,
@@ -110,7 +110,7 @@ namespace Netch.Forms
}
else
{
var subscribeLink = Global.Settings.SubscribeLink[SelectedIndex];
var subscribeLink = Global.Settings.Subscription[SelectedIndex];
RenameServers(subscribeLink.Remark, RemarkTextBox.Text);
subscribeLink.Link = LinkTextBox.Text;
@@ -118,7 +118,7 @@ namespace Netch.Forms
subscribeLink.UserAgent = UserAgentTextBox.Text;
}
InitSubscribeLink();
LoadSubscriptionLinks();
}
#endregion
@@ -131,24 +131,24 @@ namespace Netch.Forms
confirm: true) != DialogResult.OK)
return;
var subscribeLink = Global.Settings.SubscribeLink[SelectedIndex];
var subscribeLink = Global.Settings.Subscription[SelectedIndex];
DeleteServers(subscribeLink.Remark);
Global.Settings.SubscribeLink.Remove(subscribeLink);
Global.Settings.Subscription.Remove(subscribeLink);
InitSubscribeLink();
LoadSubscriptionLinks();
}
private void deleteServerToolStripMenuItem_Click(object sender, EventArgs e)
private void DeleteServersToolStripMenuItem_Click(object sender, EventArgs e)
{
if (MessageBoxX.Show(i18N.Translate("Confirm deletion?"), confirm: true) != DialogResult.OK)
return;
DeleteServers(Global.Settings.SubscribeLink[SelectedIndex].Remark);
DeleteServers(Global.Settings.Subscription[SelectedIndex].Remark);
}
private void CopyLinkToolStripMenuItem_Click(object sender, EventArgs e)
{
Clipboard.SetText(Global.Settings.SubscribeLink[SelectedIndex].Link);
Clipboard.SetText(Global.Settings.Subscription[SelectedIndex].Link);
}
#endregion
@@ -166,12 +166,12 @@ namespace Netch.Forms
server.Group = newGroup;
}
private void InitSubscribeLink()
private void LoadSubscriptionLinks()
{
SubscribeLinkListView.Items.Clear();
SubscriptionLinkListView.Items.Clear();
foreach (var item in Global.Settings.SubscribeLink)
SubscribeLinkListView.Items.Add(new ListViewItem(new[]
foreach (var item in Global.Settings.Subscription)
SubscriptionLinkListView.Items.Add(new ListViewItem(new[]
{
"",
item.Remark,
@@ -202,7 +202,7 @@ namespace Netch.Forms
return;
}
var item = Global.Settings.SubscribeLink[index];
var item = Global.Settings.Subscription[index];
AddSubscriptionBox.Text = item.Remark;
RemarkTextBox.Text = item.Remark;
LinkTextBox.Text = item.Link;

View File

@@ -0,0 +1,63 @@
<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">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<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>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="pContextMenuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

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

@@ -2,9 +2,11 @@ using System;
using System.Collections.Generic;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Windows.Forms;
using Netch.Forms;
using Netch.Models;
using Netch.Models.Modes;
namespace Netch
{
@@ -42,7 +44,7 @@ namespace Netch
public static JsonSerializerOptions NewCustomJsonSerializerOptions() => new()
{
WriteIndented = true,
IgnoreNullValues = true,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
}

View File

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

View File

@@ -10,7 +10,7 @@ namespace Netch.Interfaces
public string? LocalAddress { get; set; }
public Task<Socks5> StartAsync(Server s);
public Task<Socks5LocalServer> StartAsync(Server s);
}
public static class ServerControllerExtension

View File

@@ -37,8 +37,8 @@ namespace Netch.Interops
public enum NameList
{
TYPE_REST,
TYPE_ADDR,
TYPE_LIST,
TYPE_LISN,
TYPE_CDNS,
TYPE_ODNS
}

View File

@@ -1,15 +0,0 @@
using System.Runtime.InteropServices;
namespace Netch.Interops
{
public static class NFAPI
{
private const string nfapinet_bin = "nfapinet.dll";
[DllImport(nfapinet_bin, CallingConvention = CallingConvention.Cdecl)]
public static extern NF_STATUS nf_registerDriver(string driverName);
[DllImport(nfapinet_bin, CallingConvention = CallingConvention.Cdecl)]
public static extern NF_STATUS nf_unRegisterDriver(string driverName);
}
}

View File

@@ -1,11 +0,0 @@
namespace Netch.Interops
{
public enum NF_STATUS : int
{
NF_STATUS_SUCCESS = 0,
NF_STATUS_FAIL = -1,
NF_STATUS_INVALID_ENDPOINT_ID = -2,
NF_STATUS_NOT_INITIALIZED = -3,
NF_STATUS_IO_ERROR = -4
}
}

View File

@@ -8,38 +8,35 @@ namespace Netch.Interops
{
public enum NameList
{
TYPE_FILTERLOOPBACK,
TYPE_FILTERICMP,
TYPE_FILTERTCP,
TYPE_FILTERUDP,
AIO_FILTERLOOPBACK,
AIO_FILTERINTRANET, // LAN
AIO_FILTERPARENT,
AIO_FILTERICMP,
AIO_FILTERTCP,
AIO_FILTERUDP,
AIO_FILTERDNS,
TYPE_CLRNAME,
TYPE_ADDNAME,
TYPE_BYPNAME,
AIO_ICMPING,
TYPE_DNSHOST,
AIO_DNSONLY,
AIO_DNSPROX,
AIO_DNSHOST,
AIO_DNSPORT,
TYPE_TCPLISN,
TYPE_TCPTYPE,
TYPE_TCPHOST,
TYPE_TCPUSER,
TYPE_TCPPASS,
TYPE_TCPMETH,
TYPE_TCPPROT,
TYPE_TCPPRPA,
TYPE_TCPOBFS,
TYPE_TCPOBPA,
AIO_TGTHOST,
AIO_TGTPORT,
AIO_TGTUSER,
AIO_TGTPASS,
TYPE_UDPLISN,
TYPE_UDPTYPE,
TYPE_UDPHOST,
TYPE_UDPUSER,
TYPE_UDPPASS,
TYPE_UDPMETH,
TYPE_UDPPROT,
TYPE_UDPPRPA,
TYPE_UDPOBFS,
TYPE_UDPOBPA
AIO_CLRNAME,
AIO_ADDNAME,
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)
@@ -58,10 +55,14 @@ namespace Netch.Interops
return await Task.Run(aio_free).ConfigureAwait(false);
}
public const int UdpNameListOffset = (int)NameList.TYPE_UDPLISN - (int)NameList.TYPE_TCPLISN;
private const string Redirector_bin = "Redirector.bin";
[DllImport(Redirector_bin, CallingConvention = CallingConvention.Cdecl)]
public static extern bool aio_register([MarshalAs(UnmanagedType.LPWStr)] string value);
[DllImport(Redirector_bin, CallingConvention = CallingConvention.Cdecl)]
public static extern bool aio_unregister([MarshalAs(UnmanagedType.LPWStr)] string value);
[DllImport(Redirector_bin, CallingConvention = CallingConvention.Cdecl)]
private static extern bool aio_dial(NameList name, [MarshalAs(UnmanagedType.LPWStr)] string 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

@@ -0,0 +1,23 @@
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
using Netch.Models;
using Netch.Utils;
namespace Netch.JsonConverter
{
public class ServerConverterWithTypeDiscriminator : JsonConverter<Server>
{
public override Server Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var jsonElement = JsonSerializer.Deserialize<JsonElement>(ref reader);
var type = ServerHelper.GetTypeByTypeName(jsonElement.GetProperty("Type").GetString()!);
return (Server)jsonElement.Deserialize(type)!;
}
public override void Write(Utf8JsonWriter writer, Server value, JsonSerializerOptions options)
{
JsonSerializer.Serialize<object>(writer, value, options);
}
}
}

49
Netch/Models/Arguments.cs Normal file
View File

@@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Netch.Utils;
namespace Netch.Models
{
public static class Arguments
{
public static string Format(IEnumerable<object?> a)
{
var arguments = a.ToList();
if (arguments.Count % 2 != 0)
throw new FormatException("missing last argument value");
var tokens = new List<string>();
for (var i = 0; i < arguments.Count; i += 2)
{
var keyObj = arguments[i];
var valueObj = arguments[i + 1];
if (keyObj is not string key)
throw new FormatException($"argument key at array index {i} is not string");
switch (valueObj)
{
case SpecialArgument.Flag:
tokens.Add(key);
break;
case null:
case string value when value.IsNullOrWhiteSpace():
continue;
default:
tokens.Add(key);
tokens.Add(valueObj.ToString()!);
break;
}
}
return string.Join(' ', tokens);
}
}
public enum SpecialArgument
{
Flag
}
}

View File

@@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections.Generic;
namespace Netch.Models.GitHubRelease
{

View File

@@ -1,133 +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)}";
}
}
public static class ModeExtension
{
/// 是否会转发 UDP
public static bool TestNatRequired(this Mode mode)
{
return mode.Type is ModeType.Process && Global.Settings.Redirector.FilterProtocol.HasFlag(PortType.UDP) ||
mode.Type is ModeType.BypassRuleIPs;
}
}
}

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

@@ -0,0 +1,13 @@
using System;
namespace Netch.Models.Modes
{
[Flags]
public enum ModeFeature
{
SupportSocks5 = 0,
SupportIPv4 = 0,
SupportSocks5Auth = 0b_0001,
SupportIPv6 = 0b_0100
}
}

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

@@ -0,0 +1,9 @@
namespace Netch.Models
{
public struct NatTypeTestResult
{
public string? Result;
public string? LocalEnd;
public string? PublicEnd;
}
}

View File

@@ -1,120 +0,0 @@
using System;
using System.Linq;
using System.Reflection;
namespace Netch.Models
{
public abstract class ParameterBase
{
// null value par
private readonly bool _full;
protected readonly string ParametersSeparate = " ";
protected readonly string Separate = " ";
protected readonly string VerbPrefix = "-";
protected readonly string FullPrefix = "--";
protected ParameterBase()
{
_full = !GetType().IsDefined(typeof(VerbAttribute));
}
public override string ToString()
{
var parameters = GetType().GetProperties().Select(PropToParameter).Where(s => s != null).Cast<string>();
return string.Join(ParametersSeparate, parameters).Trim();
}
private string? PropToParameter(PropertyInfo p)
{
// prefix
bool full;
if (p.IsDefined(typeof(VerbAttribute)))
full = false;
else if (p.IsDefined(typeof(FullAttribute)))
full = true;
else
full = _full;
var prefix = full ? FullPrefix : VerbPrefix;
// key
var key = p.GetCustomAttribute<RealNameAttribute>()?.Name ?? p.Name;
// build
var value = p.GetValue(this);
switch (value)
{
case bool b:
return b ? $"{prefix}{key}" : null;
default:
if (string.IsNullOrWhiteSpace(value?.ToString()))
return p.IsDefined(typeof(OptionalAttribute)) ? null : throw new RequiredArgumentValueInvalidException(p.Name, this, null);
if (p.IsDefined(typeof(QuoteAttribute)))
value = $"\"{value}\"";
return $"{prefix}{key}{Separate}{value}";
}
}
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class)]
public class VerbAttribute : Attribute
{
// Don't use verb and full both on one class or property
// if you did, will take verb
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class)]
public class FullAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Property)]
public class OptionalAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Property)]
public class QuoteAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Property)]
public class RealNameAttribute : Attribute
{
public string Name { get; }
public RealNameAttribute(string name)
{
Name = name;
}
}
[Serializable]
public class RequiredArgumentValueInvalidException : Exception
{
public string? ArgumentName { get; }
public object? ArgumentObject { get; }
private readonly string? _message;
private const string DefaultMessage = "{0}'s Argument \"{1}\" value invalid. A required argument's value can't be null or empty.";
public override string Message => _message ?? string.Format(DefaultMessage, ArgumentObject!.GetType(), ArgumentName);
public RequiredArgumentValueInvalidException()
{
_message = "Some Argument value invalid. A required argument value's can't be null or empty.";
}
public RequiredArgumentValueInvalidException(string argumentName, object argumentObject, string? message)
{
ArgumentName = argumentName;
ArgumentObject = argumentObject;
_message = message;
}
}
}

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

@@ -1,5 +1,5 @@
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using Netch.Utils;
@@ -42,11 +42,7 @@ namespace Netch.Models
/// <summary>
/// 代理类型
/// </summary>
public virtual string Type { get; } = string.Empty;
[JsonExtensionData]
// ReSharper disable once CollectionNeverUpdated.Global
public Dictionary<string, object> ExtensionData { get; set; } = new();
public abstract string Type { get; }
public object Clone()
{
@@ -61,7 +57,7 @@ namespace Netch.Models
{
var remark = string.IsNullOrWhiteSpace(Remark) ? $"{Hostname}:{Port}" : Remark;
var shortName = Type.IsNullOrEmpty() ? "WTF" : ServerHelper.GetUtilByTypeName(Type).ShortName;
var shortName = ServerHelper.GetUtilByTypeName(Type).ShortName;
return $"[{shortName}][{Group}] {remark}";
}
@@ -113,9 +109,10 @@ namespace Netch.Models
public static class ServerExtension
{
public static async Task<string> AutoResolveHostnameAsync(this Server server)
public static async Task<string> AutoResolveHostnameAsync(this Server server, AddressFamily inet = AddressFamily.Unspecified)
{
return Global.Settings.ResolveServerHostname ? (await DnsUtils.LookupAsync(server.Hostname))!.ToString() : server.Hostname;
// ! MainController cached
return (await DnsUtils.LookupAsync(server.Hostname, inet))!.ToString();
}
public static bool IsInGroup(this Server server)

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

@@ -1,122 +1,10 @@
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using System.Linq;
using System.Text.Json;
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; } = true;
/// <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; } = false;
}
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";
[JsonIgnore]
public int ICMPDelay { get; } = 0;
public bool FilterICMP { get; set; } = false;
/// <summary>
/// 是否使用RDR内置SS
/// </summary>
public bool RedirectorSS { get; set; } = false;
/// <summary>
/// 是否代理子进程
/// </summary>
public bool ChildProcessHandle { get; set; } = false;
}
/// <summary>
/// 用于读取和写入的配置的类
/// </summary>
@@ -196,11 +84,6 @@ namespace Netch.Models
/// </summary>
public int RequestTimeout { get; set; } = 10000;
/// <summary>
/// 解析服务器主机名
/// </summary>
public bool ResolveServerHostname { get; set; } = true;
/// <summary>
/// 是否开机启动软件
/// </summary>
@@ -249,7 +132,7 @@ namespace Netch.Models
/// <summary>
/// 订阅链接列表
/// </summary>
public List<SubscribeLink> SubscribeLink { get; set; } = new();
public List<Subscription> Subscription { get; set; } = new();
/// <summary>
/// TUNTAP 适配器配置
@@ -263,7 +146,23 @@ namespace Netch.Models
public V2rayConfig V2RayConfig { get; set; } = new();
public Setting Clone()
public bool NoSupportDialog { get; set; } = false;
#region Migration
[Obsolete]
public JsonElement SubscribeLink
{
set
{
if (Subscription == null! || !Subscription.Any())
Subscription = value.Deserialize<List<Subscription>>()!;
}
}
#endregion
public Setting ShallowCopy()
{
return (Setting)MemberwiseClone();
}

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

@@ -1,6 +1,6 @@
namespace Netch.Models
{
public class SubscribeLink
public class Subscription
{
/// <summary>
/// 启用状态

View File

@@ -1,30 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\common.props" />
<PropertyGroup>
<OutputType>WinExe</OutputType>
<Configurations>Debug;Release</Configurations>
<UseWindowsForms>true</UseWindowsForms>
<UseWPF>true</UseWPF>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<StartupObject>Netch.Netch</StartupObject>
<ApplicationManifest>App.manifest</ApplicationManifest>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<ApplicationIcon>Resources\Netch.ico</ApplicationIcon>
<IsPackable>false</IsPackable>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<NoWarn>VSTHRD100</NoWarn>
<EnableNETAnalyzers>false</EnableNETAnalyzers>
<AnalysisMode>Default</AnalysisMode>
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net5.0-windows</TargetFramework>
<RuntimeIdentifiers>win-x64</RuntimeIdentifiers>
<Configurations>Debug;Release</Configurations>
<Platforms>x64</Platforms>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
@@ -39,57 +32,47 @@
<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.70" 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>
<PackageReference Include="Nullable.Extended.Analyzer" Version="1.2.4089">
<PackageReference Include="Nullable.Extended.Analyzer" Version="1.10.4539">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Serilog" Version="2.10.0" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="4.1.2" />
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
<PackageReference Include="Serilog.Sinks.Debug" Version="2.0.0" Condition="'$(Configuration)'=='Debug'" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="System.Drawing.Common" Version="5.0.2" />
<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="TaskScheduler" Version="2.9.1" />
<PackageReference Include="Microsoft-WindowsAPICodePack-Shell" Version="1.1.4" />
<PackageReference Include="WindowsFirewallHelper" Version="2.0.4.70-beta2" />
<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" />
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Update="Properties\Settings.Designer.cs">
<DesignTimeSharedInput>True</DesignTimeSharedInput>
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
</Compile>
<Compile Update="Forms\Mode\RouteForm.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Update="Forms\SyncGlobalCheckBox.cs">
<SubType>UserControl</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<None Update="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<None Remove="NativeMethods.txt" />
</ItemGroup>
<Target Condition="'$(PublishSingleFile)' == 'true'" AfterTargets="_ComputeFilesToBundle" Name="RemoveDupeAssemblies">

View File

@@ -3,6 +3,8 @@ using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Versioning;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
@@ -10,6 +12,7 @@ using Windows.Win32;
using Windows.Win32.Foundation;
using Microsoft.VisualStudio.Threading;
using Netch.Controllers;
using Netch.Enums;
using Netch.Forms;
using Netch.Services;
using Netch.Utils;
@@ -22,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; }
@@ -42,6 +45,13 @@ namespace Netch
var binPath = Path.Combine(Global.NetchDir, "bin");
Environment.SetEnvironmentVariable("PATH", $"{Environment.GetEnvironmentVariable("PATH")};{binPath}");
if (!Directory.Exists("bin") || !Directory.EnumerateFileSystemEntries("bin").Any())
{
i18N.Load("System");
MessageBoxX.Show(i18N.Translate("Please extract all files then run the program!"));
Environment.Exit(2);
}
Updater.CleanOld(Global.NetchDir);
// 预创建目录
@@ -83,13 +93,9 @@ namespace Netch
// 加载语言
i18N.Load(Global.Settings.Language);
if (!Directory.Exists("bin") || !Directory.EnumerateFileSystemEntries("bin").Any())
{
MessageBoxX.Show(i18N.Translate("Please extract all files then run the program!"));
Environment.Exit(2);
}
Task.Run(LogEnvironment).Forget();
CheckClr();
CheckOS();
// 绑定错误捕获
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
@@ -105,11 +111,54 @@ namespace Netch
private static void LogEnvironment()
{
Log.Information("Netch Version: {Version}", $"{UpdateChecker.Owner}/{UpdateChecker.Repo}@{UpdateChecker.Version}");
Log.Information("Environment: {OSVersion}", Environment.OSVersion);
Log.Information("OS: {OSVersion}", Environment.OSVersion);
Log.Information("SHA256: {Hash}", $"{Utils.Utils.SHA256CheckSum(Global.NetchExecutable)}");
Log.Information("System Language: {Language}", CultureInfo.CurrentCulture.Name);
#if RELEASE
if (Log.IsEnabled(LogEventLevel.Debug))
Log.Debug("Third-party Drivers:\n{Drivers}", string.Join("\n", SystemInfo.SystemDrivers(false)));
{
// 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()
{
var framework = Assembly.GetExecutingAssembly().GetCustomAttribute<TargetFrameworkAttribute>()?.FrameworkName;
if (framework == null)
{
Log.Warning("TargetFrameworkAttribute null");
return;
}
var frameworkName = new FrameworkName(framework);
if (frameworkName.Version.Major != Environment.Version.Major)
{
Log.Information("CLR: {Version}", Environment.Version);
Flags.NoSupport = true;
if (!Global.Settings.NoSupportDialog)
MessageBoxX.Show(
i18N.TranslateFormat("{0} won't get developers' support, Please do not report any issues or seek help from developers.",
"CLR " + Environment.Version),
LogLevel.WARNING);
}
}
private static void CheckOS()
{
if (Environment.OSVersion.Version.Build < 17763)
{
Flags.NoSupport = true;
if (!Global.Settings.NoSupportDialog)
MessageBoxX.Show(
i18N.TranslateFormat("{0} won't get developers' support, Please do not report any issues or seek help from developers.",
Environment.OSVersion),
LogLevel.WARNING);
}
}
private static void InitConsole()
@@ -127,13 +176,13 @@ namespace Netch
Log.Logger = new LoggerConfiguration()
#if DEBUG
.MinimumLevel.Verbose()
.WriteTo.Async(c => c.Debug(outputTemplate: Constants.OutputTemplate))
#else
.MinimumLevel.Debug()
#endif
.WriteTo.Async(c => c.File(Path.Combine(Global.NetchDir, Constants.LogFile),
outputTemplate: Constants.OutputTemplate,
rollOnFileSizeLimit: false))
.WriteTo.Console(outputTemplate: Constants.OutputTemplate)
.MinimumLevel.Override(@"Microsoft", LogEventLevel.Information)
.Enrich.FromLogContext()
.CreateLogger();
@@ -141,7 +190,7 @@ namespace Netch
private static void Application_OnException(object sender, ThreadExceptionEventArgs e)
{
Log.Error(e.Exception, "未处理异常");
Log.Error(e.Exception, "Unhandled error");
}
private static void Application_OnExit(object? sender, EventArgs eventArgs)

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

@@ -1,26 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace Netch.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.4.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}

View File

@@ -1,7 +0,0 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View File

@@ -15,12 +15,12 @@
"Stopping": "正在停止中",
"Stopped": "已停止",
"Starting {0}": "正在启动 {0}",
"Testing NAT": "正在测试 NAT",
"Testing NAT Type": "正在测试 NAT 类型",
"Setup Route Table Rule": "配置路由规则",
"Test failed": "测试失败",
"Starting update subscription": "正在更新订阅",
"Subscription updated": "订阅更新完毕",
"Register driver": "正在注册驱动",
"Updating servers": "正在更新服务器",
"Servers updated": "服务器更新完毕",
"Installing netfilter2 driver": "正在安装 netfilter2 驱动",
"Server": "服务器",
"Import Servers From Clipboard": "从剪贴板导入服务器",
@@ -28,10 +28,10 @@
"Netch is now minimized to the notification bar, double click this icon to restore.": "Netch 已最小化至通知栏,双击此图标恢复窗口",
"New version available": "发现新版本",
"Already latest version": "已经是最新版本",
"New version found failed": "寻找新版本失败",
"Check for update failed": "检查更新失败",
"Mode": "模式",
"Help": "帮助",
"Check for updates": "检查更新",
"Check for update": "检查更新",
"Download and install now?": "立即下载并安装?",
"Start downloading new version": "开始下载新版本",
"Download update failed": "下载更新错误",
@@ -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": "用户名",
@@ -64,16 +68,16 @@
"Plugin": "插件",
"Plugin Options": "插件参数",
"Subscribe": "订阅",
"Manage Subscribe Links": "管理订阅链接",
"Update Servers From Subscribe Links": "从订阅链接更新服务器",
"Subscription": "订阅",
"Manage Subscriptions": "管理订阅",
"Update Servers": "更新服务器",
"No subscription link": "没有任何一条订阅链接",
"Updating {0}": "正在更新 {0}",
"Update {1} server(s) from {0}": "从 {0} 更新 {1} 个服务器",
"Update servers error from {0}": "从 {0} 更新服务器失败",
"Update {1} server(s) from {0}": "从 {0} 更新 {1} 个服务器",
"Update servers failed from {0}": "从 {0} 更新服务器失败",
"Confirm deletion?": "确认删除?",
"DeleteServer": "删除订阅节点",
"CopyLink": "复制链接",
"Delete Servers": "删除订阅节点",
"Copy link": "复制链接",
"Status": "状态",
"Link": "链接",
"Unselect": "取消选择",
@@ -103,17 +107,20 @@
"Please select a mode first": "请先选择一个模式",
"Please enter a profile name first": "请先为该配置设置一个名称",
"No saved profile here. Save a profile first by Ctrl+Click on the button": "当前按钮下没有保存配置,请先使用 CTRL + 左键 点击该按钮保存一个配置",
"Lookup Server hostname failed": "解析服务器主机名失败",
"Used": "已使用",
"Testing": "测试中",
"Remark": "备注",
"Filename": "文件名",
"Use Custom Filename": "使用自定义文件名",
"Add": "添加",
"Scan": "扫描",
"Save": "保存",
"Modify": "修改",
"Select": "选择",
"Validation": "验证",
"Action": "动作",
"Select a folder": "选择一个目录",
"Please enter an process name (xxx.exe)": "请输入一个进程名xxx.exe",
"Rule does not conform to C++ regular expression syntax": "规则不符合 C++ 正则表达式语法",
@@ -124,6 +131,7 @@
"Please enter a mode remark": "请输入模式的备注",
"File already exists.\n Please Change the filename": "文件名已存在,请修改文件名",
"Please enter a mode filename": "请输入模式的文件名",
"Above rules does not conform to C++ regular expression syntax": "以上规则不符合 C++ 正则表达式语法",
"Proxy Rule IPs": "代理规则 IP",
"Bypass Rule IPs": "绕过规则 IP",
@@ -132,6 +140,7 @@
"Delete or not ? Will clean up the corresponding group of items in the server list": "是否删除?将会清理服务器列表中对应组的项目",
"Remark can not be empty": "备注不可为空",
"Link can not be empty": "链接不可为空",
"Subscription with the specified remark already exists": "带有指定备注的订阅已存在",
"Link must start with http:// or https://": "链接必须以 http:// 或 https:// 开头",
"Settings": "设置",
@@ -142,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": "退出时停止",
@@ -150,19 +159,24 @@
"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 延迟(毫秒",
"Redirector built-in Shadowsocks support": "Redirector 内建 Shadowsocks 支持",
"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": "延迟测试协议",
"Detection Tick(sec)": "检测心跳(秒)",
"STUN Server": "STUN 服务器",
"Language": "语言",
"Resolve Server Hostname": "解析服务器主机名",
"FullCone Support (Required Server Xray-core v1.3.0+)": "FullCone 支持(需服务端 Xray-core v1.3.0+",
"Disable Support Warning": "停用支持警告",
"Profile": "配置名",
"Profiles": "配置",
@@ -172,5 +186,8 @@
"Exit": "退出",
"The {0} port is in use.": "{0} 端口已被占用",
"The {0} port is reserved by system.": "{0} 端口是系统保留端口"
"The {0} port is reserved by system.": "{0} 端口是系统保留端口",
"{0} won't get developers' support, Please do not report any issues or seek help from developers.": "{0} 将不会得到开发者的支持,请不要报告任何问题或寻求开发人员的帮助。",
"No Support": "不受支持"
}

View File

@@ -1,74 +0,0 @@
using System.Collections.Generic;
using System.Net;
using System.Threading.Tasks;
using Netch.Controllers;
using Netch.Interfaces;
using Netch.Models;
namespace Netch.Servers.Shadowsocks
{
public class SSController : Guard, IServerController
{
public SSController() : base("Shadowsocks.exe")
{
}
protected override IEnumerable<string> StartedKeywords => new[] { "listening at" };
protected override IEnumerable<string> FailedKeywords => new[] { "Invalid config path", "usage", "plugin service exit unexpectedly" };
public override string Name => "Shadowsocks";
public ushort? Socks5LocalPort { get; set; }
public string? LocalAddress { get; set; }
public async Task<Socks5> StartAsync(Server s)
{
var server = (Shadowsocks)s;
var command = new SSParameter
{
s = await server.AutoResolveHostnameAsync(),
p = server.Port,
b = this.LocalAddress(),
l = this.Socks5LocalPort(),
m = server.EncryptMethod,
k = server.Password,
u = true,
plugin = server.Plugin,
plugin_opts = server.PluginOption
};
await StartGuardAsync(command.ToString());
return new Socks5Bridge(IPAddress.Loopback.ToString(), this.Socks5LocalPort(), server.Hostname);
}
[Verb]
private class SSParameter : ParameterBase
{
public string? s { get; set; }
public ushort? p { get; set; }
public string? b { get; set; }
public ushort? l { get; set; }
public string? m { get; set; }
public string? k { get; set; }
public bool u { get; set; }
[Full] [Optional] public string? plugin { get; set; }
[Full]
[Optional]
[RealName("plugin-opts")]
public string? plugin_opts { get; set; }
[Full] [Quote] [Optional] public string? acl { get; set; }
}
}
}

View File

@@ -0,0 +1,44 @@
using System.Collections.Generic;
using System.Net;
using System.Threading.Tasks;
using Netch.Controllers;
using Netch.Interfaces;
using Netch.Models;
namespace Netch.Servers
{
public class ShadowsocksController : Guard, IServerController
{
public ShadowsocksController() : base("Shadowsocks.exe")
{
}
protected override IEnumerable<string> StartedKeywords => new[] { "listening at" };
protected override IEnumerable<string> FailedKeywords => new[] { "error", "failed to start plguin" };
public override string Name => "Shadowsocks";
public ushort? Socks5LocalPort { get; set; }
public string? LocalAddress { get; set; }
public async Task<Socks5LocalServer> StartAsync(Server s)
{
var server = (ShadowsocksServer)s;
var arguments = new object?[]
{
"-s", $"{await server.AutoResolveHostnameAsync()}:{server.Port}",
"-b", $"{this.LocalAddress()}:{this.Socks5LocalPort()}",
"-m", server.EncryptMethod,
"-k", server.Password,
"--plugin", server.Plugin,
"--plugin-opts", server.PluginOption
};
await StartGuardAsync(Arguments.Format(arguments));
return new Socks5LocalServer(IPAddress.Loopback.ToString(), this.Socks5LocalPort(), server.Hostname);
}
}
}

View File

@@ -1,13 +1,13 @@
using Netch.Forms;
using Netch.Utils;
namespace Netch.Servers.Shadowsocks.Form
namespace Netch.Servers
{
public class ShadowsocksForm : ServerForm
{
public ShadowsocksForm(Shadowsocks? server = default)
public ShadowsocksForm(ShadowsocksServer? server = default)
{
server ??= new Shadowsocks();
server ??= new ShadowsocksServer();
Server = server;
CreateTextBox("Password", "Password", s => !s.IsNullOrWhiteSpace(), s => server.Password = s, server.Password);
CreateComboBox("EncryptMethod", "Encrypt Method", SSGlobal.EncryptMethods, s => server.EncryptMethod = s, server.EncryptMethod);

View File

@@ -1,9 +1,9 @@
using System.Collections.Generic;
using Netch.Models;
namespace Netch.Servers.Shadowsocks
namespace Netch.Servers
{
public class Shadowsocks : Server
public class ShadowsocksServer : Server
{
public override string Type { get; } = "SS";
public override string MaskedData()

View File

@@ -6,14 +6,12 @@ using System.Text.RegularExpressions;
using System.Web;
using Netch.Interfaces;
using Netch.Models;
using Netch.Servers.Shadowsocks.Form;
using Netch.Servers.Shadowsocks.Models.SSD;
using Netch.Utils;
using Serilog;
namespace Netch.Servers.Shadowsocks
namespace Netch.Servers
{
public class SSUtil : IServerUtil
public class ShadowsocksUtil : IServerUtil
{
public ushort Priority { get; } = 1;
@@ -25,11 +23,11 @@ namespace Netch.Servers.Shadowsocks
public string[] UriScheme { get; } = { "ss", "ssd" };
public Type ServerType { get; } = typeof(Shadowsocks);
public Type ServerType { get; } = typeof(ShadowsocksServer);
public void Edit(Server s)
{
new ShadowsocksForm((Shadowsocks)s).ShowDialog();
new ShadowsocksForm((ShadowsocksServer)s).ShowDialog();
}
public void Create()
@@ -39,7 +37,7 @@ namespace Netch.Servers.Shadowsocks
public string GetShareLink(Server s)
{
var server = (Shadowsocks)s;
var server = (ShadowsocksServer)s;
// ss://method:password@server:port#Remark
return "ss://" + ShareLink.URLSafeBase64Encode($"{server.EncryptMethod}:{server.Password}@{server.Hostname}:{server.Port}") + "#" +
HttpUtility.UrlEncode(server.Remark);
@@ -47,7 +45,7 @@ namespace Netch.Servers.Shadowsocks
public IServerController GetController()
{
return new SSController();
return new ShadowsocksController();
}
public IEnumerable<Server> ParseUri(string text)
@@ -63,10 +61,10 @@ namespace Netch.Servers.Shadowsocks
public bool CheckServer(Server s)
{
var server = (Shadowsocks)s;
var server = (ShadowsocksServer)s;
if (!SSGlobal.EncryptMethods.Contains(server.EncryptMethod))
{
Log.Warning("不支持的 SS 加密方式:{Method}", server.EncryptMethod);
Log.Warning("Unsupported SS Encrypt Method: {Method}", server.EncryptMethod);
return false;
}
@@ -75,9 +73,9 @@ namespace Netch.Servers.Shadowsocks
public IEnumerable<Server> ParseSsdUri(string s)
{
var json = JsonSerializer.Deserialize<Main>(ShareLink.URLSafeBase64Decode(s.Substring(6)))!;
var json = JsonSerializer.Deserialize<SSDJObject>(ShareLink.URLSafeBase64Decode(s.Substring(6)))!;
return json.servers.Select(server => new Shadowsocks
return json.servers.Select(server => new ShadowsocksServer
{
Remark = server.remarks,
Hostname = server.server,
@@ -92,9 +90,9 @@ namespace Netch.Servers.Shadowsocks
.Where(CheckServer);
}
public Shadowsocks ParseSsUri(string text)
public ShadowsocksServer ParseSsUri(string text)
{
var data = new Shadowsocks();
var data = new ShadowsocksServer();
text = text.Replace("/?", "?");
if (text.Contains("#"))

View File

@@ -1,9 +1,9 @@
#nullable disable
using System.Collections.Generic;
namespace Netch.Servers.Shadowsocks.Models.SSD
namespace Netch.Servers
{
public class Main
public class SSDJObject
{
/// <summary>
/// 机场名
@@ -38,6 +38,6 @@ namespace Netch.Servers.Shadowsocks.Models.SSD
/// <summary>
/// 服务器数组
/// </summary>
public List<SSDServer> servers;
public List<SSDServerJObject> servers;
}
}

View File

@@ -1,7 +1,7 @@
#nullable disable
namespace Netch.Servers.Shadowsocks.Models.SSD
namespace Netch.Servers
{
public class SSDServer
public class SSDServerJObject
{
/// <summary>
/// 加密方式

View File

@@ -1,6 +1,10 @@
#nullable disable
namespace Netch.Servers.Shadowsocks.Models
namespace Netch.Servers
{
/// <summary>
/// Import Shadowsocks Server from Json Configuration
/// <see cref="Utils.ShareLink.ParseText"/>
/// </summary>
public class ShadowsocksConfig
{
public string server { get; set; }

View File

@@ -1,88 +0,0 @@
using System.Collections.Generic;
using System.Net;
using System.Threading.Tasks;
using Netch.Controllers;
using Netch.Interfaces;
using Netch.Models;
namespace Netch.Servers.ShadowsocksR
{
public class SSRController : Guard, IServerController
{
public SSRController() : base("ShadowsocksR.exe")
{
}
protected override IEnumerable<string> StartedKeywords => new[] { "listening at" };
protected override IEnumerable<string> FailedKeywords => new[] { "Invalid config path", "usage" };
public override string Name => "ShadowsocksR";
public ushort? Socks5LocalPort { get; set; }
public string? LocalAddress { get; set; }
public async Task<Socks5> StartAsync(Server s)
{
var server = (ShadowsocksR)s;
var command = new SSRParameter
{
s = await server.AutoResolveHostnameAsync(),
p = server.Port,
k = server.Password,
m = server.EncryptMethod,
t = "120",
O = server.Protocol,
G = server.ProtocolParam,
o = server.OBFS,
g = server.OBFSParam,
b = this.LocalAddress(),
l = this.Socks5LocalPort(),
u = true
};
await StartGuardAsync(command.ToString());
return new Socks5Bridge(IPAddress.Loopback.ToString(), this.Socks5LocalPort(),server.Hostname);
}
[Verb]
class SSRParameter : ParameterBase
{
public string? s { get; set; }
public ushort? p { get; set; }
[Quote]
public string? k { get; set; }
public string? m { get; set; }
public string? t { get; set; }
[Optional]
public string? O { get; set; }
[Optional]
public string? G { get; set; }
[Optional]
public string? o { get; set; }
[Optional]
public string? g { get; set; }
public string? b { get; set; }
public ushort? l { get; set; }
public bool u { get; set; }
[Full]
[Quote]
[Optional]
public string? acl { get; set; }
}
}
}

View File

@@ -0,0 +1,50 @@
using System.Collections.Generic;
using System.Net;
using System.Threading.Tasks;
using Netch.Controllers;
using Netch.Interfaces;
using Netch.Models;
namespace Netch.Servers
{
public class ShadowsocksRController : Guard, IServerController
{
public ShadowsocksRController() : base("ShadowsocksR.exe")
{
}
protected override IEnumerable<string> StartedKeywords => new[] { "listening at" };
protected override IEnumerable<string> FailedKeywords => new[] { "Invalid config path", "usage" };
public override string Name => "ShadowsocksR";
public ushort? Socks5LocalPort { get; set; }
public string? LocalAddress { get; set; }
public async Task<Socks5LocalServer> StartAsync(Server s)
{
var server = (ShadowsocksRServer)s;
var arguments = new object?[]
{
"-s", await server.AutoResolveHostnameAsync(),
"-p", server.Port,
"-k", server.Password,
"-m", server.EncryptMethod,
"-t", 120,
"-O", server.Protocol,
"-G", server.ProtocolParam,
"-o", server.OBFS,
"-g", server.OBFSParam,
"-b", this.LocalAddress(),
"-l", this.Socks5LocalPort(),
"-u", SpecialArgument.Flag
};
await StartGuardAsync(Arguments.Format(arguments));
return new Socks5LocalServer(IPAddress.Loopback.ToString(), this.Socks5LocalPort(), server.Hostname);
}
}
}

View File

@@ -1,13 +1,13 @@
using Netch.Forms;
using Netch.Utils;
namespace Netch.Servers.ShadowsocksR.Form
namespace Netch.Servers
{
public class ShadowsocksRForm : ServerForm
{
public ShadowsocksRForm(ShadowsocksR? server = default)
public ShadowsocksRForm(ShadowsocksRServer? server = default)
{
server ??= new ShadowsocksR();
server ??= new ShadowsocksRServer();
Server = server;
CreateTextBox("Password", "Password", s => !s.IsNullOrWhiteSpace(), s => server.Password = s, server.Password);
CreateComboBox("EncryptMethod", "Encrypt Method", SSRGlobal.EncryptMethods, s => server.EncryptMethod = s, server.EncryptMethod);

View File

@@ -1,9 +1,9 @@
using System.Collections.Generic;
using Netch.Models;
namespace Netch.Servers.ShadowsocksR
namespace Netch.Servers
{
public class ShadowsocksR : Server
public class ShadowsocksRServer : Server
{
public override string Type { get; } = "SSR";
public override string MaskedData()

View File

@@ -3,14 +3,12 @@ using System.Collections.Generic;
using System.Text.RegularExpressions;
using Netch.Interfaces;
using Netch.Models;
using Netch.Servers.Shadowsocks;
using Netch.Servers.ShadowsocksR.Form;
using Netch.Utils;
using Serilog;
namespace Netch.Servers.ShadowsocksR
namespace Netch.Servers
{
public class SSRUtil : IServerUtil
public class ShadowsocksRUtil : IServerUtil
{
public ushort Priority { get; } = 1;
@@ -22,11 +20,11 @@ namespace Netch.Servers.ShadowsocksR
public string[] UriScheme { get; } = { "ssr" };
public Type ServerType { get; } = typeof(ShadowsocksR);
public Type ServerType { get; } = typeof(ShadowsocksRServer);
public void Edit(Server s)
{
new ShadowsocksRForm((ShadowsocksR)s).ShowDialog();
new ShadowsocksRForm((ShadowsocksRServer)s).ShowDialog();
}
public void Create()
@@ -36,7 +34,7 @@ namespace Netch.Servers.ShadowsocksR
public string GetShareLink(Server s)
{
var server = (ShadowsocksR)s;
var server = (ShadowsocksRServer)s;
// https://github.com/shadowsocksr-backup/shadowsocks-rss/wiki/SSR-QRcode-scheme
// ssr://base64(host:port:protocol:method:obfs:base64pass/?obfsparam=base64param&protoparam=base64param&remarks=base64remarks&group=base64group&udpport=0&uot=0)
@@ -50,7 +48,7 @@ namespace Netch.Servers.ShadowsocksR
public IServerController GetController()
{
return new SSRController();
return new ShadowsocksRController();
}
/// <summary>
@@ -113,7 +111,7 @@ namespace Netch.Servers.ShadowsocksR
if (SSGlobal.EncryptMethods.Contains(method) && protocol == "origin" && obfs == "plain")
return new[]
{
new Shadowsocks.Shadowsocks
new ShadowsocksServer
{
Hostname = serverAddr,
Port = serverPort,
@@ -126,7 +124,7 @@ namespace Netch.Servers.ShadowsocksR
return new[]
{
new ShadowsocksR
new ShadowsocksRServer
{
Hostname = serverAddr,
Port = serverPort,
@@ -144,22 +142,22 @@ namespace Netch.Servers.ShadowsocksR
public bool CheckServer(Server s)
{
var server = (ShadowsocksR)s;
var server = (ShadowsocksRServer)s;
if (!SSRGlobal.EncryptMethods.Contains(server.EncryptMethod))
{
Log.Error("不支持的 SSR 加密方式:{Method}", server.EncryptMethod);
Log.Error("Unsupported ShadowsocksR Encrypt method: {Method}", server.EncryptMethod);
return false;
}
if (!SSRGlobal.Protocols.Contains(server.Protocol))
{
Log.Error("不支持的 SSR 协议:{Protocol}", server.Protocol);
Log.Error("Unsupported ShadowsocksR Protocol: {Protocol}", server.Protocol);
return false;
}
if (!SSRGlobal.OBFSs.Contains(server.OBFS))
{
Log.Error("不支持的 SSR 混淆:{Obfs}", server.OBFS);
Log.Error("Unsupported ShadowsocksR Obfs: {Obfs}", server.OBFS);
return false;
}

View File

@@ -1,19 +0,0 @@
using System.Threading.Tasks;
using Netch.Models;
namespace Netch.Servers
{
public class S5Controller : V2rayController
{
public override string Name { get; } = "Socks5";
public override async Task<Socks5> StartAsync(Server s)
{
var server = (Socks5)s;
if (server.Auth())
await base.StartAsync(s);
return server;
}
}
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Threading.Tasks;
using Netch.Models;
namespace Netch.Servers
{
public class Socks5Controller : V2rayController
{
public override string Name { get; } = "Socks5";
public override async Task<Socks5LocalServer> StartAsync(Server s)
{
var server = (Socks5Server)s;
if (!server.Auth())
throw new ArgumentException();
return await base.StartAsync(s);
}
}
}

View File

@@ -4,9 +4,9 @@ namespace Netch.Servers
{
public class Socks5Form : ServerForm
{
public Socks5Form(Socks5? server = default)
public Socks5Form(Socks5Server? server = default)
{
server ??= new Socks5();
server ??= new Socks5Server();
Server = server;
CreateTextBox("Username", "Username", s => true, s => server.Username = s, server.Username);
CreateTextBox("Password", "Password", s => true, s => server.Password = s, server.Password);

View File

@@ -5,10 +5,12 @@
/// Encrypted proxy client's local socks5 server
/// (<see cref="RemoteHostname"/> property is used for saving remote address/hostname for special use)
/// </summary>
public class Socks5Bridge : Socks5
public class Socks5LocalServer : Socks5Server
{
public Socks5Bridge(string hostname, ushort port, string remoteHostname) : base(hostname, port)
public Socks5LocalServer(string hostname, ushort port, string remoteHostname)
{
Hostname = hostname;
Port = port;
RemoteHostname = remoteHostname;
}

View File

@@ -2,17 +2,17 @@
namespace Netch.Servers
{
public class Socks5 : Server
public class Socks5Server : Server
{
/// <summary>
/// 密码
/// </summary>
public string? Password;
public string? Password { get; set; }
/// <summary>
/// 账号
/// </summary>
public string? Username;
public string? Username { get; set; }
public override string Type { get; } = "Socks5";
@@ -21,17 +21,17 @@ namespace Netch.Servers
return $"Auth: {Auth()}";
}
public Socks5()
public Socks5Server()
{
}
public Socks5(string hostname, ushort port)
public Socks5Server(string hostname, ushort port)
{
Hostname = hostname;
Port = port;
}
public Socks5(string hostname, ushort port, string username, string password) : this(hostname, port)
public Socks5Server(string hostname, ushort port, string username, string password) : this(hostname, port)
{
Username = username;
Password = password;

View File

@@ -6,7 +6,7 @@ using Netch.Models;
namespace Netch.Servers
{
public class S5Util : IServerUtil
public class Socks5Util : IServerUtil
{
public ushort Priority { get; } = 0;
@@ -18,11 +18,11 @@ namespace Netch.Servers
public string[] UriScheme { get; } = { };
public Type ServerType { get; } = typeof(Socks5);
public Type ServerType { get; } = typeof(Socks5Server);
public void Edit(Server s)
{
new Socks5Form((Socks5)s).ShowDialog();
new Socks5Form((Socks5Server)s).ShowDialog();
}
public void Create()
@@ -32,7 +32,7 @@ namespace Netch.Servers
public string GetShareLink(Server s)
{
var server = (Socks5)s;
var server = (Socks5Server)s;
// https://t.me/socks?server=1.1.1.1&port=443
return $"https://t.me/socks?server={server.Hostname}&port={server.Port}" +
$"{(!string.IsNullOrWhiteSpace(server.Username) ? $"&user={server.Username}" : "")}" +
@@ -41,7 +41,7 @@ namespace Netch.Servers
public IServerController GetController()
{
return new S5Controller();
return new Socks5Controller();
}
public IEnumerable<Server> ParseUri(string text)
@@ -55,7 +55,7 @@ namespace Netch.Servers
if (!dict.ContainsKey("server") || !dict.ContainsKey("port"))
throw new FormatException();
var data = new Socks5
var data = new Socks5Server
{
Hostname = dict["server"],
Port = ushort.Parse(dict["port"])

View File

@@ -1,7 +1,7 @@
#nullable disable
using System.Collections.Generic;
namespace Netch.Servers.Models
namespace Netch.Servers
{
public class TrojanConfig
{

View File

@@ -6,7 +6,6 @@ using System.Threading.Tasks;
using Netch.Controllers;
using Netch.Interfaces;
using Netch.Models;
using Netch.Servers.Models;
using Netch.Utils;
namespace Netch.Servers
@@ -27,9 +26,9 @@ namespace Netch.Servers
public string? LocalAddress { get; set; }
public async Task<Socks5> StartAsync(Server s)
public async Task<Socks5LocalServer> StartAsync(Server s)
{
var server = (Trojan)s;
var server = (TrojanServer)s;
var trojanConfig = new TrojanConfig
{
local_addr = this.LocalAddress(),
@@ -42,7 +41,7 @@ namespace Netch.Servers
},
ssl = new TrojanSSL
{
sni = server.Host.ValueOrDefault() ?? (Global.Settings.ResolveServerHostname ? server.Hostname : "")
sni = server.Host.ValueOrDefault() ?? server.Hostname
}
};
@@ -52,7 +51,7 @@ namespace Netch.Servers
}
await StartGuardAsync("-c ..\\data\\last.json");
return new Socks5Bridge(IPAddress.Loopback.ToString(), this.Socks5LocalPort(), server.Hostname);
return new Socks5LocalServer(IPAddress.Loopback.ToString(), this.Socks5LocalPort(), server.Hostname);
}
}
}

View File

@@ -1,12 +1,12 @@
using Netch.Forms;
namespace Netch.Servers.Form
namespace Netch.Servers
{
public class TrojanForm : ServerForm
{
public TrojanForm(Trojan? server = default)
public TrojanForm(TrojanServer? server = default)
{
server ??= new Trojan();
server ??= new TrojanServer();
Server = server;
CreateTextBox("Password", "Password", s => true, s => server.Password = s, server.Password);
CreateTextBox("Host", "Host", s => true, s => server.Host = s, server.Host);

View File

@@ -2,7 +2,7 @@ using Netch.Models;
namespace Netch.Servers
{
public class Trojan : Server
public class TrojanServer : Server
{
public override string Type { get; } = "Trojan";
public override string MaskedData()

View File

@@ -4,7 +4,6 @@ using System.Text.RegularExpressions;
using System.Web;
using Netch.Interfaces;
using Netch.Models;
using Netch.Servers.Form;
namespace Netch.Servers
{
@@ -20,11 +19,11 @@ namespace Netch.Servers
public string[] UriScheme { get; } = { "trojan" };
public Type ServerType { get; } = typeof(Trojan);
public Type ServerType { get; } = typeof(TrojanServer);
public void Edit(Server s)
{
new TrojanForm((Trojan)s).ShowDialog();
new TrojanForm((TrojanServer)s).ShowDialog();
}
public void Create()
@@ -34,7 +33,7 @@ namespace Netch.Servers
public string GetShareLink(Server s)
{
var server = (Trojan)s;
var server = (TrojanServer)s;
return $"trojan://{HttpUtility.UrlEncode(server.Password)}@{server.Hostname}:{server.Port}#{server.Remark}";
}
@@ -45,7 +44,7 @@ namespace Netch.Servers
public IEnumerable<Server> ParseUri(string text)
{
var data = new Trojan();
var data = new TrojanServer();
text = text.Replace("/?", "?");
if (text.Contains("#"))

View File

@@ -1,9 +1,6 @@
namespace Netch.Servers.Models
namespace Netch.Servers
{
/// <summary>
/// 使用 v2rayN 定义的 VMess 链接格式
/// </summary>
public class V2rayNSharing
public class V2rayNJObject
{
/// <summary>
/// 链接版本

View File

@@ -1,7 +1,7 @@
#nullable disable
// ReSharper disable InconsistentNaming
namespace Netch.Servers.V2ray.Models
namespace Netch.Servers
{
public struct V2rayConfig
{

View File

@@ -1,12 +1,10 @@
using System.Threading.Tasks;
using Netch.Models;
using Netch.Servers.V2ray.Models;
using Netch.Utils;
using V2rayConfig = Netch.Servers.V2ray.Models.V2rayConfig;
#pragma warning disable VSTHRD200
namespace Netch.Servers.Utils
namespace Netch.Servers
{
public static class V2rayConfigUtils
{
@@ -44,7 +42,7 @@ namespace Netch.Servers.Utils
switch (server)
{
case Socks5 socks5:
case Socks5Server socks5:
{
outbound.protocol = "socks";
outbound.settings.servers = new object[]
@@ -71,7 +69,7 @@ namespace Netch.Servers.Utils
outbound.mux.concurrency = -1;
break;
}
case VLESS vless:
case VLESSServer vless:
{
outbound.protocol = "vless";
outbound.settings.vnext = new[]
@@ -107,7 +105,7 @@ namespace Netch.Servers.Utils
break;
}
case VMess vmess:
case VMessServer vmess:
{
outbound.protocol = "vmess";
outbound.settings.vnext = new[]
@@ -139,7 +137,7 @@ namespace Netch.Servers.Utils
return outbound;
}
private static StreamSettings boundStreamSettings(VMess server)
private static StreamSettings boundStreamSettings(VMessServer server)
{
// https://xtls.github.io/config/transports
@@ -154,7 +152,7 @@ namespace Netch.Servers.Utils
var tlsSettings = new TlsSettings
{
allowInsecure = Global.Settings.V2RayConfig.AllowInsecure,
serverName = server.ServerName.ValueOrDefault() ?? server.Hostname
serverName = server.ServerName.ValueOrDefault() ?? server.Host.SplitOrDefault()?[0]
};
switch (server.TLSSecureType)

View File

@@ -6,7 +6,6 @@ using System.Threading.Tasks;
using Netch.Controllers;
using Netch.Interfaces;
using Netch.Models;
using Netch.Servers.Utils;
namespace Netch.Servers
{
@@ -28,7 +27,7 @@ namespace Netch.Servers
public string? LocalAddress { get; set; }
public virtual async Task<Socks5> StartAsync(Server s)
public virtual async Task<Socks5LocalServer> StartAsync(Server s)
{
await using (var fileStream = new FileStream(Constants.TempConfig, FileMode.Create, FileAccess.Write, FileShare.Read))
{
@@ -36,7 +35,7 @@ namespace Netch.Servers
}
await StartGuardAsync("-config ..\\data\\last.json");
return new Socks5Bridge(IPAddress.Loopback.ToString(), this.Socks5LocalPort(), s.Hostname);
return new Socks5LocalServer(IPAddress.Loopback.ToString(), this.Socks5LocalPort(), s.Hostname);
}
}
}

View File

@@ -13,7 +13,7 @@ namespace Netch.Servers
public static IEnumerable<Server> ParseVUri(string text)
{
var scheme = ShareLink.GetUriScheme(text).ToLower();
var server = scheme switch { "vmess" => new VMess(), "vless" => new VLESS(), _ => throw new ArgumentOutOfRangeException() };
var server = scheme switch { "vmess" => new VMessServer(), "vless" => new VLESSServer(), _ => throw new ArgumentOutOfRangeException() };
if (text.Contains("#"))
{
server.Remark = Uri.UnescapeDataString(text.Split('#')[1]);
@@ -58,7 +58,7 @@ namespace Netch.Servers
{
server.ServerName = parameter.Get("sni") ?? "";
if (server.TLSSecureType == "xtls")
((VLESS)server).Flow = parameter.Get("flow") ?? "";
((VLESSServer)server).Flow = parameter.Get("flow") ?? "";
}
}
@@ -77,7 +77,7 @@ namespace Netch.Servers
public static string GetVShareLink(Server s, string scheme = "vmess")
{
// https://github.com/XTLS/Xray-core/issues/91
var server = (VMess)s;
var server = (VMessServer)s;
var parameter = new Dictionary<string, string>();
// protocol-specific fields
parameter.Add("type", server.TransferProtocol);
@@ -138,7 +138,7 @@ namespace Netch.Servers
if (server.TLSSecureType == "xtls")
{
var flow = ((VLESS)server).Flow;
var flow = ((VLESSServer)server).Flow;
if (!flow.IsNullOrWhiteSpace())
parameter.Add("flow", flow!.Replace("-udp443", ""));
}

View File

@@ -1,13 +1,13 @@
using System.Collections.Generic;
using Netch.Forms;
namespace Netch.Servers.VLESSForm
namespace Netch.Servers
{
internal class VLESSForm : ServerForm
{
public VLESSForm(VLESS? server = default)
public VLESSForm(VLESSServer? server = default)
{
server ??= new VLESS();
server ??= new VLESSServer();
Server = server;
CreateTextBox("Sni", "ServerName(Sni)", s => true, s => server.ServerName = s, server.ServerName);
CreateTextBox("UUID", "UUID", s => true, s => server.UserID = s, server.UserID);

View File

@@ -2,7 +2,7 @@ using System.Collections.Generic;
namespace Netch.Servers
{
public class VLESS : VMess
public class VLESSServer : VMessServer
{
public override string Type { get; } = "VLESS";

View File

@@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using Netch.Interfaces;
using Netch.Models;
using Netch.Servers;
namespace Netch.Servers
{
@@ -18,16 +17,16 @@ namespace Netch.Servers
public string[] UriScheme { get; } = { "vless" };
public Type ServerType { get; } = typeof(VLESS);
public Type ServerType { get; } = typeof(VLESSServer);
public void Edit(Server s)
{
new VLESSForm.VLESSForm((VLESS)s).ShowDialog();
new VLESSForm((VLESSServer)s).ShowDialog();
}
public void Create()
{
new VLESSForm.VLESSForm().ShowDialog();
new VLESSForm().ShowDialog();
}
public string GetShareLink(Server s)

Some files were not shown because too many files have changed in this diff Show More