mirror of
https://github.com/netchx/netch.git
synced 2026-05-11 23:45:06 +08:00
Compare commits
87 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a853b9831f | ||
|
|
3d37b042f6 | ||
|
|
1f9607ba1e | ||
|
|
8443772b75 | ||
|
|
aaad1697b3 | ||
|
|
35688003d5 | ||
|
|
19afbf1993 | ||
|
|
3cd0b59bf6 | ||
|
|
b26aecf7e8 | ||
|
|
18f71d3862 | ||
|
|
0bd0d06867 | ||
|
|
96001500f0 | ||
|
|
11ab1b89af | ||
|
|
811e2828fb | ||
|
|
68a2e4b705 | ||
|
|
8e83359e39 | ||
|
|
d2b6d182ff | ||
|
|
019044c275 | ||
|
|
df48eb3067 | ||
|
|
6bfcae453f | ||
|
|
7d55af2101 | ||
|
|
9172ede7c2 | ||
|
|
fb8aa548ac | ||
|
|
46643a3f5e | ||
|
|
99752d7a44 | ||
|
|
004b84ceda | ||
|
|
d15206b803 | ||
|
|
754753300d | ||
|
|
aa021aaf79 | ||
|
|
c50ca563b2 | ||
|
|
a1fdf7ead2 | ||
|
|
c9da7197ba | ||
|
|
5ff26e97b4 | ||
|
|
06049cb06f | ||
|
|
8cf765de92 | ||
|
|
2b53a7ca9e | ||
|
|
c7c0a2a698 | ||
|
|
1d072214ee | ||
|
|
135ff642bd | ||
|
|
4c274a1888 | ||
|
|
59cfc071cc | ||
|
|
8cf32e5d37 | ||
|
|
7a1e5b58b9 | ||
|
|
651fbb6ff9 | ||
|
|
45bf31e9f3 | ||
|
|
f7c9ab4028 | ||
|
|
717dc55055 | ||
|
|
a0c4dd3192 | ||
|
|
325ad430fe | ||
|
|
4b374d3898 | ||
|
|
b6afeab187 | ||
|
|
6e499c3948 | ||
|
|
5bfcbab543 | ||
|
|
fe69c5a67b | ||
|
|
1c974d295b | ||
|
|
a544bd1a26 | ||
|
|
3bfe03b99b | ||
|
|
1fa18ce787 | ||
|
|
f7ad2baa52 | ||
|
|
447a25457b | ||
|
|
3a8351e6e4 | ||
|
|
eb30300b24 | ||
|
|
0b8373a21e | ||
|
|
8a551b715e | ||
|
|
34814fe7f5 | ||
|
|
528abe3fdd | ||
|
|
a10410dafd | ||
|
|
2ca98a94d5 | ||
|
|
ac2e5e943e | ||
|
|
0957514e05 | ||
|
|
35b9f168ff | ||
|
|
ce15e9468e | ||
|
|
4c8508a838 | ||
|
|
f931adb005 | ||
|
|
d4f829d4bd | ||
|
|
51d4ba0fdb | ||
|
|
ca0870889a | ||
|
|
ac3e39e9cd | ||
|
|
84765ab96d | ||
|
|
a18851af15 | ||
|
|
42366abcca | ||
|
|
cec8358922 | ||
|
|
db8e964351 | ||
|
|
ad3053298a | ||
|
|
669ca4902f | ||
|
|
272bf61b0f | ||
|
|
0051e7bb50 |
@@ -1,7 +1,7 @@
|
||||
root = true
|
||||
# http://editorconfig.org/
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# all files
|
||||
[*]
|
||||
@@ -32,6 +32,7 @@ resharper_csharp_blank_lines_around_field = 0
|
||||
resharper_csharp_blank_lines_around_invocable = 0
|
||||
resharper_csharp_blank_lines_around_type = 0
|
||||
resharper_csharp_int_align_comments = true
|
||||
resharper_csharp_keep_blank_lines_in_declarations = 1
|
||||
resharper_csharp_max_line_length = 368
|
||||
resharper_csharp_wrap_lines = false
|
||||
resharper_place_expr_accessor_on_single_line = true
|
||||
|
||||
@@ -6,7 +6,6 @@ namespace Netch.Controllers
|
||||
{
|
||||
public class DNSController : IController
|
||||
{
|
||||
|
||||
public string Name { get; } = "DNS Service";
|
||||
|
||||
/// <summary>
|
||||
@@ -15,13 +14,14 @@ namespace Netch.Controllers
|
||||
/// <returns></returns>
|
||||
public bool Start()
|
||||
{
|
||||
if (!aiodns_dial(Encoding.UTF8.GetBytes(Path.GetFullPath(Global.Settings.AioDNS.RulePath)),
|
||||
Encoding.UTF8.GetBytes($"{Global.Settings.AioDNS.ChinaDNS}:53"),
|
||||
Encoding.UTF8.GetBytes($"{Global.Settings.AioDNS.OtherDNS}:53"))
|
||||
)
|
||||
return false;
|
||||
return
|
||||
aiodns_init();
|
||||
aiodns_dial((int) NameList.TYPE_REST, null);
|
||||
aiodns_dial((int) NameList.TYPE_ADDR, Encoding.UTF8.GetBytes($"{Global.Settings.LocalAddress}:53"));
|
||||
aiodns_dial((int) NameList.TYPE_LIST, Encoding.UTF8.GetBytes(Path.GetFullPath(Global.Settings.AioDNS.RulePath)));
|
||||
aiodns_dial((int) NameList.TYPE_CDNS, Encoding.UTF8.GetBytes($"{Global.Settings.AioDNS.ChinaDNS}:53"));
|
||||
aiodns_dial((int) NameList.TYPE_ODNS, Encoding.UTF8.GetBytes($"{Global.Settings.AioDNS.OtherDNS}:53"));
|
||||
aiodns_dial((int) NameList.TYPE_METH, Encoding.UTF8.GetBytes(Global.Settings.AioDNS.Protocol));
|
||||
|
||||
return aiodns_init();
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
@@ -32,7 +32,7 @@ namespace Netch.Controllers
|
||||
#region NativeMethods
|
||||
|
||||
[DllImport("aiodns.bin", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern bool aiodns_dial(byte[] chinacon, byte[] chinadns, byte[] otherdns);
|
||||
public static extern bool aiodns_dial(int name, byte[] value);
|
||||
|
||||
[DllImport("aiodns.bin", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern bool aiodns_init();
|
||||
@@ -40,6 +40,16 @@ namespace Netch.Controllers
|
||||
[DllImport("aiodns.bin", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void aiodns_free();
|
||||
|
||||
enum NameList : int
|
||||
{
|
||||
TYPE_REST,
|
||||
TYPE_ADDR,
|
||||
TYPE_LIST,
|
||||
TYPE_CDNS,
|
||||
TYPE_ODNS,
|
||||
TYPE_METH
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -14,12 +14,12 @@ namespace Netch.Controllers
|
||||
{
|
||||
public abstract class Guard
|
||||
{
|
||||
public abstract string Name { get; protected set; }
|
||||
public virtual string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 主程序名
|
||||
/// </summary>
|
||||
public abstract string MainFile { get; protected set; }
|
||||
public virtual string MainFile { get; protected set; }
|
||||
|
||||
protected State State { get; set; } = State.Waiting;
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace Netch.Controllers
|
||||
/// 程序输出的编码,
|
||||
/// 调用于基类的 <see cref="OnOutputDataReceived"/>
|
||||
/// </summary>
|
||||
protected string InstanceOutputEncoding { get; set; } = "gbk";
|
||||
protected Encoding InstanceOutputEncoding { get; set; } = Encoding.GetEncoding("gbk");
|
||||
|
||||
/// <summary>
|
||||
/// 停止进程
|
||||
@@ -83,7 +83,7 @@ namespace Netch.Controllers
|
||||
/// 仅初始化 <see cref="Instance"/>,不设定事件处理方法
|
||||
/// </summary>
|
||||
/// <param name="argument"></param>
|
||||
protected void InitInstance(string argument)
|
||||
protected virtual void InitInstance(string argument)
|
||||
{
|
||||
Instance = new Process
|
||||
{
|
||||
@@ -93,16 +93,16 @@ namespace Netch.Controllers
|
||||
WorkingDirectory = $"{Global.NetchDir}\\bin",
|
||||
Arguments = argument,
|
||||
CreateNoWindow = true,
|
||||
RedirectStandardError = RedirectStd,
|
||||
RedirectStandardInput = RedirectStd,
|
||||
RedirectStandardOutput = RedirectStd,
|
||||
UseShellExecute = !RedirectStd,
|
||||
RedirectStandardOutput = RedirectStd,
|
||||
StandardOutputEncoding = RedirectStd ? InstanceOutputEncoding : null,
|
||||
RedirectStandardError = RedirectStd,
|
||||
StandardErrorEncoding = RedirectStd ? InstanceOutputEncoding : null,
|
||||
WindowStyle = ProcessWindowStyle.Hidden
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 默认行为启动主程序
|
||||
/// </summary>
|
||||
@@ -192,15 +192,13 @@ namespace Netch.Controllers
|
||||
if (e.Data == null)
|
||||
return;
|
||||
|
||||
var info = Encoding.GetEncoding(InstanceOutputEncoding).GetBytes(e.Data);
|
||||
var str = Encoding.UTF8.GetString(info);
|
||||
Write(str);
|
||||
Write(e.Data);
|
||||
// 检查启动
|
||||
if (State == State.Starting)
|
||||
{
|
||||
if (StartedKeywords.Any(s => str.Contains(s)))
|
||||
if (StartedKeywords.Any(s => e.Data.Contains(s)))
|
||||
State = State.Started;
|
||||
else if (StoppedKeywords.Any(s => str.Contains(s)))
|
||||
else if (StoppedKeywords.Any(s => e.Data.Contains(s)))
|
||||
State = State.Stopped;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,14 @@ using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using WindowsProxy;
|
||||
using Microsoft.Win32;
|
||||
using Netch.Forms;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.Socks5;
|
||||
using Netch.Servers.Trojan;
|
||||
using Netch.Utils;
|
||||
using Netch.Utils.HttpProxyHandler;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
@@ -13,7 +17,7 @@ namespace Netch.Controllers
|
||||
{
|
||||
public const string IEProxyExceptions = "localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*";
|
||||
|
||||
public PrivoxyController pPrivoxyController = new PrivoxyController();
|
||||
public PrivoxyController pPrivoxyController = new();
|
||||
|
||||
private string prevBypass, prevHTTP, prevPAC;
|
||||
private bool prevEnabled;
|
||||
@@ -32,11 +36,25 @@ namespace Netch.Controllers
|
||||
try
|
||||
{
|
||||
if (pPrivoxyController.Start(MainController.Server, mode))
|
||||
{
|
||||
Global.Job.AddProcess(pPrivoxyController.Instance);
|
||||
}
|
||||
|
||||
if (mode.Type == 3) NativeMethods.SetGlobal($"127.0.0.1:{Global.Settings.HTTPLocalPort}", IEProxyExceptions);
|
||||
if (mode.Type == 3)
|
||||
{
|
||||
if (MainController.Server is Socks5 or Trojan && mode.BypassChina)
|
||||
{
|
||||
//启动PAC服务器
|
||||
PACServerHandle.InitPACServer("127.0.0.1");
|
||||
}
|
||||
else
|
||||
{
|
||||
using var service = new ProxyService
|
||||
{
|
||||
Server = $"127.0.0.1:{Global.Settings.HTTPLocalPort}",
|
||||
Bypass = IEProxyExceptions
|
||||
};
|
||||
service.Global();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -49,6 +67,48 @@ namespace Netch.Controllers
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
var tasks = new[]
|
||||
{
|
||||
Task.Run(pPrivoxyController.Stop),
|
||||
Task.Run(() =>
|
||||
{
|
||||
using var service = new ProxyService();
|
||||
try
|
||||
{
|
||||
PACServerHandle.Stop();
|
||||
if (prevEnabled)
|
||||
{
|
||||
if (prevHTTP != "")
|
||||
{
|
||||
service.Server = prevHTTP;
|
||||
service.Bypass = prevBypass;
|
||||
service.Global();
|
||||
}
|
||||
if (prevPAC != "")
|
||||
{
|
||||
service.AutoConfigUrl = prevPAC;
|
||||
service.Pac();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
service.Direct();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Error($"{Name} 控制器出错:\n" + e);
|
||||
}
|
||||
})
|
||||
};
|
||||
Task.WaitAll(tasks);
|
||||
}
|
||||
|
||||
private void RecordPrevious()
|
||||
{
|
||||
try
|
||||
@@ -77,29 +137,5 @@ namespace Netch.Controllers
|
||||
prevPAC = prevHTTP = prevBypass = "";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
var tasks = new[]
|
||||
{
|
||||
Task.Factory.StartNew(pPrivoxyController.Stop),
|
||||
Task.Factory.StartNew(() =>
|
||||
{
|
||||
if (prevEnabled)
|
||||
{
|
||||
if (prevHTTP != "")
|
||||
NativeMethods.SetGlobal(prevHTTP, prevBypass);
|
||||
if (prevPAC != "")
|
||||
NativeMethods.SetURL(prevPAC);
|
||||
}
|
||||
else
|
||||
NativeMethods.SetDIRECT();
|
||||
})
|
||||
};
|
||||
Task.WaitAll(tasks);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,6 @@
|
||||
/// <summary>
|
||||
/// 停止
|
||||
/// </summary>
|
||||
public abstract void Stop();
|
||||
public void Stop();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Netch.Forms;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.Socks5;
|
||||
using Netch.Utils;
|
||||
@@ -12,6 +14,17 @@ namespace Netch.Controllers
|
||||
{
|
||||
public static class MainController
|
||||
{
|
||||
public static Mode Mode;
|
||||
|
||||
/// TCP or Both Server
|
||||
public static Server Server;
|
||||
|
||||
private static Server _udpServer;
|
||||
|
||||
public static readonly NTTController NTTController = new();
|
||||
private static IServerController _serverController;
|
||||
private static IServerController _udpServerController;
|
||||
|
||||
public static IServerController ServerController
|
||||
{
|
||||
get => _serverController;
|
||||
@@ -24,24 +37,14 @@ namespace Netch.Controllers
|
||||
set => _udpServerController = value;
|
||||
}
|
||||
|
||||
/// TCP or Both Server
|
||||
public static Server Server;
|
||||
|
||||
public static Server UdpServer
|
||||
{
|
||||
get => _udpServer ?? Server;
|
||||
set => _udpServer = value;
|
||||
}
|
||||
|
||||
private static Server _udpServer;
|
||||
public static IModeController ModeController { get; private set; }
|
||||
|
||||
public static bool NttTested;
|
||||
|
||||
private static readonly NTTController NTTController = new NTTController();
|
||||
private static IServerController _serverController;
|
||||
private static IServerController _udpServerController;
|
||||
|
||||
/// <summary>
|
||||
/// 启动
|
||||
/// </summary>
|
||||
@@ -52,11 +55,10 @@ namespace Netch.Controllers
|
||||
{
|
||||
Logging.Info($"启动主控制器: {server.Type} [{mode.Type}]{mode.Remark}");
|
||||
Server = server;
|
||||
Mode = mode;
|
||||
|
||||
if (server is Socks5 && mode.Type == 4)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 刷新DNS缓存
|
||||
NativeMethods.FlushDNSResolverCache();
|
||||
@@ -85,20 +87,13 @@ namespace Netch.Controllers
|
||||
if (!ModeHelper.SkipServerController(server, mode))
|
||||
{
|
||||
if (!await Task.Run(() => StartServer(server, mode, ref _serverController)))
|
||||
{
|
||||
throw new StartFailedException();
|
||||
}
|
||||
|
||||
StatusPortInfoText.UpdateShareLan();
|
||||
}
|
||||
|
||||
if (!await StartMode(mode))
|
||||
{
|
||||
throw new StartFailedException();
|
||||
}
|
||||
|
||||
if (mode.TestNatRequired())
|
||||
NatTest();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -111,7 +106,6 @@ namespace Netch.Controllers
|
||||
MessageBoxX.Show(e.Message + "\n\n" + i18N.Translate("Missing File or runtime components"), owner: Global.MainForm);
|
||||
break;
|
||||
case StartFailedException _:
|
||||
case PortInUseException _:
|
||||
break;
|
||||
default:
|
||||
Logging.Error($"主控制器未处理异常: {e}");
|
||||
@@ -136,31 +130,30 @@ namespace Netch.Controllers
|
||||
controller = ServerHelper.GetUtilByTypeName(server.Type).GetController();
|
||||
|
||||
if (controller is Guard instanceController)
|
||||
{
|
||||
Utils.Utils.KillProcessByName(instanceController.MainFile);
|
||||
}
|
||||
|
||||
PortCheckAndShowMessageBox(controller.Socks5LocalPort(), "Socks5");
|
||||
if (!PortCheckAndShowMessageBox(controller.Socks5LocalPort(), "Socks5"))
|
||||
return false;
|
||||
|
||||
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", controller.Name));
|
||||
if (controller.Start(in server, mode))
|
||||
{
|
||||
if (controller is Guard guard)
|
||||
{
|
||||
if (guard.Instance != null)
|
||||
{
|
||||
Global.Job.AddProcess(guard.Instance);
|
||||
}
|
||||
}
|
||||
Task.Run(() =>
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
Global.Job.AddProcess(guard.Instance);
|
||||
});
|
||||
|
||||
if (server is Socks5 socks5)
|
||||
{
|
||||
if (socks5.Auth())
|
||||
UsingPorts.Add(StatusPortInfoText.Socks5Port = controller.Socks5LocalPort());
|
||||
StatusPortInfoText.Socks5Port = controller.Socks5LocalPort();
|
||||
}
|
||||
else
|
||||
{
|
||||
UsingPorts.Add(StatusPortInfoText.Socks5Port = controller.Socks5LocalPort());
|
||||
StatusPortInfoText.Socks5Port = controller.Socks5LocalPort();
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -174,26 +167,18 @@ namespace Netch.Controllers
|
||||
ModeController = ModeHelper.GetModeControllerByType(mode.Type, out var port, out var portName, out var portType);
|
||||
|
||||
if (ModeController == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (port != null)
|
||||
{
|
||||
PortCheckAndShowMessageBox((ushort) port, portName, portType);
|
||||
UsingPorts.Add((ushort) port);
|
||||
}
|
||||
if (!PortCheckAndShowMessageBox((ushort) port, portName, portType))
|
||||
return false;
|
||||
|
||||
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ModeController.Name));
|
||||
if (await Task.Run(() => ModeController.Start(mode)))
|
||||
{
|
||||
if (ModeController is Guard guard)
|
||||
{
|
||||
if (guard.Instance != null)
|
||||
{
|
||||
Global.Job.AddProcess(guard.Instance);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -206,7 +191,6 @@ namespace Netch.Controllers
|
||||
/// </summary>
|
||||
public static async Task Stop()
|
||||
{
|
||||
UsingPorts.Clear();
|
||||
StatusPortInfoText.Reset();
|
||||
|
||||
_ = Task.Run(() => NTTController.Stop());
|
||||
@@ -214,53 +198,34 @@ namespace Netch.Controllers
|
||||
var tasks = new[]
|
||||
{
|
||||
Task.Run(() => ServerController?.Stop()),
|
||||
Task.Run(() => ModeController?.Stop()),
|
||||
Task.Run(() => ModeController?.Stop())
|
||||
};
|
||||
await Task.WhenAll(tasks);
|
||||
ModeController = null;
|
||||
ServerController = null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 检查端口是否被占用,
|
||||
/// 检查端口是否被占用,
|
||||
/// 被占用则弹窗提示, 确认后抛出异常
|
||||
/// </summary>
|
||||
/// <param name="port">检查的端口</param>
|
||||
/// <param name="portName">端口用途名称</param>
|
||||
/// <param name="portType"></param>
|
||||
/// <exception cref="PortInUseException"></exception>
|
||||
public static void PortCheckAndShowMessageBox(ushort port, string portName, PortType portType = PortType.Both)
|
||||
public static bool PortCheckAndShowMessageBox(ushort port, string portName, PortType portType = PortType.Both)
|
||||
{
|
||||
if (PortInUse(port, portType))
|
||||
try
|
||||
{
|
||||
CheckPort(port, portType);
|
||||
return true;
|
||||
}
|
||||
catch (PortInUseException)
|
||||
{
|
||||
MessageBoxX.Show(i18N.TranslateFormat("The {0} port is in use.", $"{portName} ({port})"));
|
||||
throw new PortInUseException();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试 NAT
|
||||
/// </summary>
|
||||
public static void NatTest()
|
||||
{
|
||||
NttTested = false;
|
||||
Task.Run(() =>
|
||||
catch (PortReservedException)
|
||||
{
|
||||
Global.MainForm.NatTypeStatusText(i18N.Translate("Starting NatTester"));
|
||||
// Thread.Sleep(1000);
|
||||
var (result, localEnd, publicEnd) = NTTController.Start();
|
||||
|
||||
if (!string.IsNullOrEmpty(publicEnd))
|
||||
{
|
||||
var country = Utils.Utils.GetCityCode(publicEnd);
|
||||
Global.MainForm.NatTypeStatusText(result, country);
|
||||
}
|
||||
else
|
||||
Global.MainForm.NatTypeStatusText(result ?? "Error");
|
||||
|
||||
NttTested = true;
|
||||
});
|
||||
MessageBoxX.Show(i18N.TranslateFormat("The {0} port is reserved by system.", $"{portName} ({port})"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.ServiceProcess;
|
||||
using System.Threading.Tasks;
|
||||
using Netch.Forms;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.Shadowsocks;
|
||||
using Netch.Servers.Socks5;
|
||||
@@ -15,14 +16,12 @@ namespace Netch.Controllers
|
||||
{
|
||||
public class NFController : IModeController
|
||||
{
|
||||
private static readonly ServiceController NFService = new ServiceController("netfilter2");
|
||||
private static readonly ServiceController NFService = new("netfilter2");
|
||||
|
||||
private static readonly string BinDriver = string.Empty;
|
||||
private static readonly string SystemDriver = $"{Environment.SystemDirectory}\\drivers\\netfilter2.sys";
|
||||
private static string _sysDns;
|
||||
|
||||
public string Name { get; } = "Redirector";
|
||||
|
||||
static NFController()
|
||||
{
|
||||
string fileName;
|
||||
@@ -47,6 +46,8 @@ namespace Netch.Controllers
|
||||
BinDriver = "bin\\" + fileName;
|
||||
}
|
||||
|
||||
public string Name { get; } = "Redirector";
|
||||
|
||||
public bool Start(in Mode mode)
|
||||
{
|
||||
if (!CheckDriver())
|
||||
@@ -55,8 +56,11 @@ namespace Netch.Controllers
|
||||
#region aio_dial
|
||||
|
||||
aio_dial((int) NameList.TYPE_FILTERLOOPBACK, "false");
|
||||
aio_dial((int) NameList.TYPE_FILTERTCP, "true");
|
||||
aio_dial((int) NameList.TYPE_TCPLISN, Global.Settings.RedirectorTCPPort.ToString());
|
||||
|
||||
if (Global.Settings.ProcessNoProxyForUdp && Global.Settings.ProcessNoProxyForTcp) MessageBoxX.Show("?");
|
||||
|
||||
//UDP
|
||||
if (Global.Settings.ProcessNoProxyForUdp)
|
||||
{
|
||||
aio_dial((int) NameList.TYPE_FILTERUDP, "false");
|
||||
@@ -68,6 +72,18 @@ namespace Netch.Controllers
|
||||
SetServer(PortType.Both);
|
||||
}
|
||||
|
||||
//TCP
|
||||
if (Global.Settings.ProcessNoProxyForTcp)
|
||||
{
|
||||
aio_dial((int) NameList.TYPE_FILTERTCP, "false");
|
||||
SetServer(PortType.UDP);
|
||||
}
|
||||
else
|
||||
{
|
||||
aio_dial((int) NameList.TYPE_FILTERTCP, "true");
|
||||
SetServer(PortType.Both);
|
||||
}
|
||||
|
||||
if (!CheckRule(mode.FullRule, out var list))
|
||||
{
|
||||
MessageBoxX.Show($"\"{string.Join("", list.Select(s => s + "\n"))}\" does not conform to C++ regular expression syntax");
|
||||
@@ -90,8 +106,19 @@ namespace Netch.Controllers
|
||||
return aio_init();
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
if (Global.Settings.ModifySystemDNS)
|
||||
//恢复系统DNS
|
||||
DNS.OutboundDNS = _sysDns;
|
||||
});
|
||||
|
||||
aio_free();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="rules"></param>
|
||||
/// <param name="incompatibleRule"></param>
|
||||
@@ -104,7 +131,6 @@ namespace Netch.Controllers
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="r"></param>
|
||||
/// <param name="clear"></param>
|
||||
@@ -146,9 +172,7 @@ namespace Netch.Controllers
|
||||
}
|
||||
|
||||
if (!File.Exists(SystemDriver))
|
||||
{
|
||||
return InstallDriver();
|
||||
}
|
||||
|
||||
var updateFlag = false;
|
||||
|
||||
@@ -163,18 +187,14 @@ namespace Netch.Controllers
|
||||
{
|
||||
// Installed greater than Bin
|
||||
if (systemResult.Major != binResult.Major)
|
||||
{
|
||||
// API breaking changes
|
||||
updateFlag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!systemFileVersion.Equals(binFileVersion))
|
||||
{
|
||||
updateFlag = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!updateFlag) return true;
|
||||
@@ -252,18 +272,6 @@ namespace Netch.Controllers
|
||||
aio_dial((int) NameList.TYPE_ADDNAME, @"NTT\.exe");
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
if (Global.Settings.ModifySystemDNS)
|
||||
//恢复系统DNS
|
||||
DNS.OutboundDNS = _sysDns;
|
||||
});
|
||||
|
||||
aio_free();
|
||||
}
|
||||
|
||||
#region NativeMethods
|
||||
|
||||
private const int UdpNameListOffset = (int) NameList.TYPE_UDPTYPE - (int) NameList.TYPE_TCPTYPE;
|
||||
@@ -284,7 +292,7 @@ namespace Netch.Controllers
|
||||
private static extern ulong aio_getDL();
|
||||
|
||||
|
||||
public enum NameList : int
|
||||
public enum NameList
|
||||
{
|
||||
TYPE_FILTERLOOPBACK,
|
||||
TYPE_FILTERTCP,
|
||||
@@ -348,7 +356,6 @@ namespace Netch.Controllers
|
||||
/// <returns>是否成功卸载</returns>
|
||||
public static bool UninstallDriver()
|
||||
{
|
||||
Global.MainForm.StatusText(i18N.TranslateFormat("Uninstalling {0}", "NF Service"));
|
||||
Logging.Info("卸载 NF 驱动");
|
||||
try
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Netch.Utils;
|
||||
@@ -8,7 +7,7 @@ namespace Netch.Controllers
|
||||
{
|
||||
public class NTTController : Guard, IController
|
||||
{
|
||||
public override string Name { get; protected set; } = "NTT";
|
||||
public override string Name { get; } = "NTT";
|
||||
public override string MainFile { get; protected set; } = "NTT.exe";
|
||||
|
||||
/// <summary>
|
||||
@@ -17,10 +16,10 @@ namespace Netch.Controllers
|
||||
/// <returns></returns>
|
||||
public (string, string, string) Start()
|
||||
{
|
||||
string localEnd=null;
|
||||
string publicEnd=null;
|
||||
string result =null;
|
||||
string bindingTest=null;
|
||||
string localEnd = null;
|
||||
string publicEnd = null;
|
||||
string result = null;
|
||||
string bindingTest = null;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Netch.Controllers
|
||||
RedirectStd = false;
|
||||
}
|
||||
|
||||
public override string Name { get; protected set; } = "Privoxy";
|
||||
public override string Name { get; } = "Privoxy";
|
||||
|
||||
public override string MainFile { get; protected set; } = "Privoxy.exe";
|
||||
|
||||
|
||||
@@ -15,7 +15,9 @@ namespace Netch.Controllers
|
||||
{
|
||||
public class TUNTAPController : Guard, IModeController
|
||||
{
|
||||
|
||||
private readonly List<string> _directIPs = new();
|
||||
|
||||
private readonly List<string> _proxyIPs = new();
|
||||
/// <summary>
|
||||
/// 服务器 IP 地址
|
||||
/// </summary>
|
||||
@@ -24,17 +26,17 @@ namespace Netch.Controllers
|
||||
/// <summary>
|
||||
/// 本地 DNS 服务控制器
|
||||
/// </summary>
|
||||
public DNSController DNSController = new DNSController();
|
||||
public DNSController DNSController = new();
|
||||
|
||||
public TUNTAPController()
|
||||
{
|
||||
StartedKeywords.Add("Running");
|
||||
StoppedKeywords.AddRange(new[] {"failed", "invalid vconfig file"});
|
||||
}
|
||||
|
||||
public override string Name { get; protected set; } = "tun2socks";
|
||||
public override string MainFile { get; protected set; } = "tun2socks.exe";
|
||||
|
||||
public override string Name { get; } = "tun2socks";
|
||||
|
||||
public bool Start(in Mode mode)
|
||||
{
|
||||
var server = MainController.Server;
|
||||
@@ -43,9 +45,7 @@ namespace Netch.Controllers
|
||||
|
||||
// 查找出口适配器
|
||||
if (!Utils.Utils.SearchOutboundAdapter())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 查找并安装 TAP 适配器
|
||||
if (!SearchTapAdapter())
|
||||
@@ -79,14 +79,8 @@ namespace Netch.Controllers
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
MainController.PortCheckAndShowMessageBox(53, "DNS");
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (!MainController.PortCheckAndShowMessageBox(53, "DNS"))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!DNSController.Start())
|
||||
{
|
||||
@@ -119,17 +113,13 @@ namespace Netch.Controllers
|
||||
{
|
||||
var tasks = new[]
|
||||
{
|
||||
Task.Factory.StartNew(StopInstance),
|
||||
Task.Factory.StartNew(ClearRouteTable),
|
||||
Task.Factory.StartNew(DNSController.Stop)
|
||||
Task.Run(StopInstance),
|
||||
Task.Run(ClearRouteTable),
|
||||
Task.Run(DNSController.Stop)
|
||||
};
|
||||
Task.WaitAll(tasks);
|
||||
}
|
||||
|
||||
private readonly List<string> _directIPs = new List<string>();
|
||||
|
||||
private readonly List<string> _proxyIPs = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// 设置绕行规则
|
||||
/// </summary>
|
||||
@@ -150,7 +140,6 @@ namespace Netch.Controllers
|
||||
|
||||
//处理 NAT 类型检测,由于协议的原因,无法仅通过域名确定需要代理的 IP,自己记录解析了返回的 IP,仅支持默认检测服务器
|
||||
if (Global.Settings.STUN_Server == "stun.stunprotocol.org")
|
||||
{
|
||||
try
|
||||
{
|
||||
Logging.Info("代理 → STUN 服务器 IP");
|
||||
@@ -166,23 +155,18 @@ namespace Netch.Controllers
|
||||
{
|
||||
Logging.Info("NAT 类型测试域名解析失败,将不会被添加到代理列表");
|
||||
}
|
||||
}
|
||||
|
||||
if (Global.Settings.TUNTAP.ProxyDNS)
|
||||
{
|
||||
Logging.Info("代理 → 自定义 DNS");
|
||||
if (Global.Settings.TUNTAP.UseCustomDNS)
|
||||
{
|
||||
RouteAction(Action.Create,
|
||||
Global.Settings.TUNTAP.DNS.Select(ip => $"{ip}/32"),
|
||||
RouteType.TUNTAP);
|
||||
}
|
||||
else
|
||||
{
|
||||
RouteAction(Action.Create,
|
||||
new[] {"1.1.1.1", "8.8.8.8", "9.9.9.9", "185.222.222.222"}.Select(ip => $"{ip}/32"),
|
||||
RouteType.TUNTAP);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -222,7 +206,6 @@ namespace Netch.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 清除绕行规则
|
||||
/// </summary>
|
||||
@@ -235,7 +218,6 @@ namespace Netch.Controllers
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public bool TestFakeDNS()
|
||||
{
|
||||
try
|
||||
@@ -303,26 +285,11 @@ namespace Netch.Controllers
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private enum RouteType
|
||||
{
|
||||
Outbound,
|
||||
TUNTAP
|
||||
}
|
||||
|
||||
private enum Action
|
||||
{
|
||||
Create,
|
||||
Delete
|
||||
}
|
||||
|
||||
private void RouteAction(Action action, in IEnumerable<string> ipNetworks, RouteType routeType,
|
||||
int metric = 0)
|
||||
{
|
||||
foreach (var address in ipNetworks)
|
||||
{
|
||||
RouteAction(action, address, routeType, metric);
|
||||
}
|
||||
}
|
||||
|
||||
private bool RouteAction(Action action, in string ipNetwork, RouteType routeType, int metric = 0)
|
||||
@@ -383,11 +350,21 @@ namespace Netch.Controllers
|
||||
}
|
||||
|
||||
if (!result)
|
||||
{
|
||||
Logging.Warning($"Failed to {action} Route on {routeType} Adapter: {ipNetwork} metric {metric}");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private enum RouteType
|
||||
{
|
||||
Outbound,
|
||||
TUNTAP
|
||||
}
|
||||
|
||||
private enum Action
|
||||
{
|
||||
Create,
|
||||
Delete
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,35 +1,38 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Netch.Models.GitHubRelease;
|
||||
using Netch.Utils;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
public class UpdateChecker
|
||||
public static class UpdateChecker
|
||||
{
|
||||
public const string Owner = @"NetchX";
|
||||
public const string Repo = @"Netch";
|
||||
|
||||
public const string Name = @"Netch";
|
||||
public const string Copyright = @"Copyright © 2019 - 2020";
|
||||
public const string Copyright = @"Copyright © 2019 - 2021";
|
||||
|
||||
public const string AssemblyVersion = @"1.6.9";
|
||||
public const string AssemblyVersion = @"1.7.4";
|
||||
private const string Suffix = @"";
|
||||
|
||||
public static readonly string Version = $"{AssemblyVersion}{(string.IsNullOrEmpty(Suffix) ? "" : $"-{Suffix}")}";
|
||||
|
||||
public string LatestVersionNumber;
|
||||
public string LatestVersionUrl;
|
||||
public Release LatestRelease;
|
||||
public static string LatestVersionNumber;
|
||||
public static string LatestVersionUrl;
|
||||
public static Release LatestRelease;
|
||||
|
||||
public event EventHandler NewVersionFound;
|
||||
public event EventHandler NewVersionFoundFailed;
|
||||
public event EventHandler NewVersionNotFound;
|
||||
public static event EventHandler NewVersionFound;
|
||||
public static event EventHandler NewVersionFoundFailed;
|
||||
public static event EventHandler NewVersionNotFound;
|
||||
|
||||
public async void Check(bool isPreRelease)
|
||||
public static async void Check(bool isPreRelease)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -46,12 +49,12 @@ namespace Netch.Controllers
|
||||
if (VersionUtil.CompareVersion(LatestRelease.tag_name, Version) > 0)
|
||||
{
|
||||
Logging.Info("发现新版本");
|
||||
NewVersionFound?.Invoke(this, new EventArgs());
|
||||
NewVersionFound?.Invoke(null, new EventArgs());
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Info("目前是最新版本");
|
||||
NewVersionNotFound?.Invoke(this, new EventArgs());
|
||||
NewVersionNotFound?.Invoke(null, new EventArgs());
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -59,12 +62,67 @@ namespace Netch.Controllers
|
||||
if (e is WebException)
|
||||
Logging.Warning($"获取新版本失败: {e.Message}");
|
||||
else
|
||||
{
|
||||
Logging.Warning(e.ToString());
|
||||
|
||||
NewVersionFoundFailed?.Invoke(null, new EventArgs());
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task UpdateNetch(DownloadProgressChangedEventHandler onDownloadProgressChanged)
|
||||
{
|
||||
using WebClient client = new();
|
||||
|
||||
var latestVersionDownloadUrl = LatestRelease.assets[0].browser_download_url;
|
||||
var tagPage = await client.DownloadStringTaskAsync(LatestVersionUrl);
|
||||
var match = Regex.Match(tagPage, @"<td .*>(?<sha256>.*)</td>", RegexOptions.Singleline);
|
||||
|
||||
// TODO Replace with regex get basename and sha256
|
||||
var fileName = Path.GetFileName(new Uri(latestVersionDownloadUrl).LocalPath);
|
||||
fileName = fileName.Insert(fileName.LastIndexOf('.'), LatestVersionNumber);
|
||||
var fileFullPath = Path.Combine(Global.NetchDir, "data", fileName);
|
||||
|
||||
var sha256 = match.Groups["sha256"].Value;
|
||||
|
||||
if (File.Exists(fileFullPath))
|
||||
{
|
||||
if (Utils.Utils.SHA256CheckSum(fileFullPath) == sha256)
|
||||
{
|
||||
RunUpdater();
|
||||
return;
|
||||
}
|
||||
|
||||
NewVersionFoundFailed?.Invoke(this, new EventArgs());
|
||||
File.Delete(fileFullPath);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
client.DownloadProgressChanged += onDownloadProgressChanged;
|
||||
await client.DownloadFileTaskAsync(new Uri(latestVersionDownloadUrl), fileFullPath);
|
||||
client.DownloadProgressChanged -= onDownloadProgressChanged;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new Exception(i18N.Translate("Download Update Failed", ": ") + e.Message);
|
||||
}
|
||||
|
||||
if (Utils.Utils.SHA256CheckSum(fileFullPath) != sha256)
|
||||
throw new Exception(i18N.Translate("The downloaded file has the wrong hash"));
|
||||
|
||||
RunUpdater();
|
||||
|
||||
void RunUpdater()
|
||||
{
|
||||
// if debugging process stopped, debugger will kill child processes!!!!
|
||||
// 调试进程结束,调试器将会杀死子进程
|
||||
// uncomment if(!Debugger.isAttach) block in NetchUpdater Project's main() method and attach to NetchUpdater process to debug
|
||||
// 在 NetchUpdater 项目的 main() 方法中取消注释 if(!Debugger.isAttach)块,并附加到 NetchUpdater 进程进行调试
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = Path.Combine(Global.NetchDir, "NetchUpdater.exe"),
|
||||
Arguments =
|
||||
$"{Global.Settings.UDPSocketPort} \"{fileFullPath}\" \"{Global.NetchDir}\""
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Controllers;
|
||||
using Netch.Models;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Forms
|
||||
{
|
||||
public partial class Dummy
|
||||
{
|
||||
}
|
||||
|
||||
partial class MainForm
|
||||
{
|
||||
private bool _isFirstCloseWindow = true;
|
||||
|
||||
private async void ControlFun()
|
||||
{
|
||||
Configuration.Save();
|
||||
if (State == State.Waiting || State == State.Stopped)
|
||||
{
|
||||
// 服务器、模式 需选择
|
||||
if (!(ServerComboBox.SelectedItem is Server server))
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("Please select a server first"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(ModeComboBox.SelectedItem is Models.Mode mode))
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("Please select a mode first"));
|
||||
return;
|
||||
}
|
||||
|
||||
// 清除模式搜索框文本选择
|
||||
ModeComboBox.Select(0, 0);
|
||||
|
||||
State = State.Starting;
|
||||
|
||||
if (await MainController.Start(server, mode))
|
||||
{
|
||||
State = State.Started;
|
||||
_ = Task.Run(() => { Bandwidth.NetTraffic(server, mode); });
|
||||
// 如果勾选启动后最小化
|
||||
if (Global.Settings.MinimizeWhenStarted)
|
||||
{
|
||||
WindowState = FormWindowState.Minimized;
|
||||
|
||||
if (_isFirstCloseWindow)
|
||||
{
|
||||
// 显示提示语
|
||||
NotifyTip(i18N.Translate("Netch is now minimized to the notification bar, double click this icon to restore."));
|
||||
_isFirstCloseWindow = false;
|
||||
}
|
||||
|
||||
Hide();
|
||||
}
|
||||
|
||||
if (Global.Settings.StartedTcping)
|
||||
{
|
||||
// 自动检测延迟
|
||||
_ = Task.Run(() =>
|
||||
{
|
||||
while (State == State.Started)
|
||||
{
|
||||
server.Test();
|
||||
// 重绘 ServerComboBox
|
||||
ServerComboBox.Invalidate();
|
||||
|
||||
Thread.Sleep(Global.Settings.StartedTcping_Interval * 1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
State = State.Stopped;
|
||||
StatusText(i18N.Translate("Start failed"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 停止
|
||||
State = State.Stopping;
|
||||
await MainController.Stop();
|
||||
State = State.Stopped;
|
||||
_ = Task.Run(TestServer);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnBandwidthUpdated(ulong download)
|
||||
{
|
||||
if (InvokeRequired)
|
||||
{
|
||||
BeginInvoke(new Action<ulong>(OnBandwidthUpdated), download);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
UsedBandwidthLabel.Text = $"{i18N.Translate("Used", ": ")}{Bandwidth.Compute(download)}";
|
||||
//UploadSpeedLabel.Text = $"↑: {Utils.Bandwidth.Compute(upload - LastUploadBandwidth)}/s";
|
||||
DownloadSpeedLabel.Text = $"↑↓: {Bandwidth.Compute(download - LastDownloadBandwidth)}/s";
|
||||
|
||||
//LastUploadBandwidth = upload;
|
||||
LastDownloadBandwidth = download;
|
||||
Refresh();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 上一次上传的流量
|
||||
/// </summary>
|
||||
public ulong LastUploadBandwidth;
|
||||
|
||||
/// <summary>
|
||||
/// 上一次下载的流量
|
||||
/// </summary>
|
||||
public ulong LastDownloadBandwidth;
|
||||
}
|
||||
}
|
||||
151
Netch/Forms/MainForm.Designer.cs
generated
151
Netch/Forms/MainForm.Designer.cs
generated
@@ -39,11 +39,13 @@
|
||||
this.SubscribeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.ManageSubscribeLinksToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.UpdateServersFromSubscribeLinksToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.OptionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.OpenDirectoryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.CleanDNSCacheToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.UpdateACLToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.updateACLWithProxyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.updatePACToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.UninstallServiceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.UninstallTapDriverToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.HelpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
@@ -87,17 +89,18 @@
|
||||
this.ProfileTable = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.ButtomControlContainerControl = new System.Windows.Forms.ContainerControl();
|
||||
this.removeNetchFirewallRulesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.MenuStrip.SuspendLayout();
|
||||
this.ConfigurationGroupBox.SuspendLayout();
|
||||
this.configLayoutPanel.SuspendLayout();
|
||||
this.tableLayoutPanel2.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.EditServerPictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.CopyLinkPictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.DeleteServerPictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.SpeedPictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize) (this.EditServerPictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize) (this.CopyLinkPictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize) (this.DeleteServerPictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize) (this.SpeedPictureBox)).BeginInit();
|
||||
this.tableLayoutPanel3.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.EditModePictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.DeleteModePictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize) (this.EditModePictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize) (this.DeleteModePictureBox)).BeginInit();
|
||||
this.StatusStrip.SuspendLayout();
|
||||
this.NotifyMenu.SuspendLayout();
|
||||
this.ProfileGroupBox.SuspendLayout();
|
||||
@@ -109,16 +112,10 @@
|
||||
//
|
||||
this.MenuStrip.BackColor = System.Drawing.SystemColors.Control;
|
||||
this.MenuStrip.ImageScalingSize = new System.Drawing.Size(20, 20);
|
||||
this.MenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.ServerToolStripMenuItem,
|
||||
this.ModeToolStripMenuItem,
|
||||
this.SubscribeToolStripMenuItem,
|
||||
this.OptionsToolStripMenuItem,
|
||||
this.HelpToolStripMenuItem,
|
||||
this.exitToolStripMenuItem,
|
||||
this.AboutToolStripButton,
|
||||
this.NewVersionLabel,
|
||||
this.VersionLabel});
|
||||
this.MenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[]
|
||||
{
|
||||
this.ServerToolStripMenuItem, this.ModeToolStripMenuItem, this.SubscribeToolStripMenuItem, this.OptionsToolStripMenuItem, this.HelpToolStripMenuItem, this.exitToolStripMenuItem, this.AboutToolStripButton, this.NewVersionLabel, this.VersionLabel
|
||||
});
|
||||
this.MenuStrip.Location = new System.Drawing.Point(0, 0);
|
||||
this.MenuStrip.Name = "MenuStrip";
|
||||
this.MenuStrip.RenderMode = System.Windows.Forms.ToolStripRenderMode.Professional;
|
||||
@@ -127,8 +124,10 @@
|
||||
//
|
||||
// ServerToolStripMenuItem
|
||||
//
|
||||
this.ServerToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.ImportServersFromClipboardToolStripMenuItem});
|
||||
this.ServerToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[]
|
||||
{
|
||||
this.ImportServersFromClipboardToolStripMenuItem
|
||||
});
|
||||
this.ServerToolStripMenuItem.Margin = new System.Windows.Forms.Padding(3, 0, 0, 1);
|
||||
this.ServerToolStripMenuItem.Name = "ServerToolStripMenuItem";
|
||||
this.ServerToolStripMenuItem.Size = new System.Drawing.Size(57, 21);
|
||||
@@ -143,9 +142,10 @@
|
||||
//
|
||||
// ModeToolStripMenuItem
|
||||
//
|
||||
this.ModeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.CreateProcessModeToolStripMenuItem,
|
||||
this.ReloadModesToolStripMenuItem});
|
||||
this.ModeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[]
|
||||
{
|
||||
this.CreateProcessModeToolStripMenuItem, 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);
|
||||
@@ -167,9 +167,10 @@
|
||||
//
|
||||
// SubscribeToolStripMenuItem
|
||||
//
|
||||
this.SubscribeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.ManageSubscribeLinksToolStripMenuItem,
|
||||
this.UpdateServersFromSubscribeLinksToolStripMenuItem});
|
||||
this.SubscribeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[]
|
||||
{
|
||||
this.ManageSubscribeLinksToolStripMenuItem, this.UpdateServersFromSubscribeLinksToolStripMenuItem, this.UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem
|
||||
});
|
||||
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);
|
||||
@@ -178,26 +179,30 @@
|
||||
// ManageSubscribeLinksToolStripMenuItem
|
||||
//
|
||||
this.ManageSubscribeLinksToolStripMenuItem.Name = "ManageSubscribeLinksToolStripMenuItem";
|
||||
this.ManageSubscribeLinksToolStripMenuItem.Size = new System.Drawing.Size(294, 22);
|
||||
this.ManageSubscribeLinksToolStripMenuItem.Size = new System.Drawing.Size(360, 22);
|
||||
this.ManageSubscribeLinksToolStripMenuItem.Text = "Manage Subscribe Links";
|
||||
this.ManageSubscribeLinksToolStripMenuItem.Click += new System.EventHandler(this.ManageSubscribeLinksToolStripMenuItem_Click);
|
||||
//
|
||||
// UpdateServersFromSubscribeLinksToolStripMenuItem
|
||||
//
|
||||
this.UpdateServersFromSubscribeLinksToolStripMenuItem.Name = "UpdateServersFromSubscribeLinksToolStripMenuItem";
|
||||
this.UpdateServersFromSubscribeLinksToolStripMenuItem.Size = new System.Drawing.Size(294, 22);
|
||||
this.UpdateServersFromSubscribeLinksToolStripMenuItem.Size = new System.Drawing.Size(360, 22);
|
||||
this.UpdateServersFromSubscribeLinksToolStripMenuItem.Text = "Update Servers From Subscribe Links";
|
||||
this.UpdateServersFromSubscribeLinksToolStripMenuItem.Click += new System.EventHandler(this.UpdateServersFromSubscribeLinksToolStripMenuItem_Click);
|
||||
//
|
||||
// UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem
|
||||
//
|
||||
this.UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem.Name = "UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem";
|
||||
this.UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem.Size = new System.Drawing.Size(360, 22);
|
||||
this.UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem.Text = "Update Servers From Subscribe Links With Proxy";
|
||||
this.UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem.Click += new System.EventHandler(this.UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem_Click);
|
||||
//
|
||||
// OptionsToolStripMenuItem
|
||||
//
|
||||
this.OptionsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.OpenDirectoryToolStripMenuItem,
|
||||
this.CleanDNSCacheToolStripMenuItem,
|
||||
this.UpdateACLToolStripMenuItem,
|
||||
this.updateACLWithProxyToolStripMenuItem,
|
||||
this.UninstallServiceToolStripMenuItem,
|
||||
this.UninstallTapDriverToolStripMenuItem});
|
||||
this.OptionsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[]
|
||||
{
|
||||
this.OpenDirectoryToolStripMenuItem, this.CleanDNSCacheToolStripMenuItem, this.UpdateACLToolStripMenuItem, this.updateACLWithProxyToolStripMenuItem, this.updatePACToolStripMenuItem, this.UninstallServiceToolStripMenuItem, this.UninstallTapDriverToolStripMenuItem, 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);
|
||||
@@ -206,50 +211,58 @@
|
||||
// OpenDirectoryToolStripMenuItem
|
||||
//
|
||||
this.OpenDirectoryToolStripMenuItem.Name = "OpenDirectoryToolStripMenuItem";
|
||||
this.OpenDirectoryToolStripMenuItem.Size = new System.Drawing.Size(220, 22);
|
||||
this.OpenDirectoryToolStripMenuItem.Size = new System.Drawing.Size(243, 22);
|
||||
this.OpenDirectoryToolStripMenuItem.Text = "Open Directory";
|
||||
this.OpenDirectoryToolStripMenuItem.Click += new System.EventHandler(this.OpenDirectoryToolStripMenuItem_Click);
|
||||
//
|
||||
// CleanDNSCacheToolStripMenuItem
|
||||
//
|
||||
this.CleanDNSCacheToolStripMenuItem.Name = "CleanDNSCacheToolStripMenuItem";
|
||||
this.CleanDNSCacheToolStripMenuItem.Size = new System.Drawing.Size(220, 22);
|
||||
this.CleanDNSCacheToolStripMenuItem.Size = new System.Drawing.Size(243, 22);
|
||||
this.CleanDNSCacheToolStripMenuItem.Text = "Clean DNS Cache";
|
||||
this.CleanDNSCacheToolStripMenuItem.Click += new System.EventHandler(this.CleanDNSCacheToolStripMenuItem_Click);
|
||||
//
|
||||
// UpdateACLToolStripMenuItem
|
||||
//
|
||||
this.UpdateACLToolStripMenuItem.Name = "UpdateACLToolStripMenuItem";
|
||||
this.UpdateACLToolStripMenuItem.Size = new System.Drawing.Size(220, 22);
|
||||
this.UpdateACLToolStripMenuItem.Size = new System.Drawing.Size(243, 22);
|
||||
this.UpdateACLToolStripMenuItem.Text = "Update ACL";
|
||||
this.UpdateACLToolStripMenuItem.Click += new System.EventHandler(this.updateACLToolStripMenuItem_Click);
|
||||
//
|
||||
// updateACLWithProxyToolStripMenuItem
|
||||
//
|
||||
this.updateACLWithProxyToolStripMenuItem.Name = "updateACLWithProxyToolStripMenuItem";
|
||||
this.updateACLWithProxyToolStripMenuItem.Size = new System.Drawing.Size(220, 22);
|
||||
this.updateACLWithProxyToolStripMenuItem.Size = new System.Drawing.Size(243, 22);
|
||||
this.updateACLWithProxyToolStripMenuItem.Text = "Update ACL with proxy";
|
||||
this.updateACLWithProxyToolStripMenuItem.Click += new System.EventHandler(this.updateACLWithProxyToolStripMenuItem_Click);
|
||||
//
|
||||
// updatePACToolStripMenuItem
|
||||
//
|
||||
this.updatePACToolStripMenuItem.Name = "updatePACToolStripMenuItem";
|
||||
this.updatePACToolStripMenuItem.Size = new System.Drawing.Size(243, 22);
|
||||
this.updatePACToolStripMenuItem.Text = "Update PAC";
|
||||
this.updatePACToolStripMenuItem.Click += new System.EventHandler(this.updatePACToolStripMenuItem_Click);
|
||||
//
|
||||
// UninstallServiceToolStripMenuItem
|
||||
//
|
||||
this.UninstallServiceToolStripMenuItem.Name = "UninstallServiceToolStripMenuItem";
|
||||
this.UninstallServiceToolStripMenuItem.Size = new System.Drawing.Size(220, 22);
|
||||
this.UninstallServiceToolStripMenuItem.Size = new System.Drawing.Size(243, 22);
|
||||
this.UninstallServiceToolStripMenuItem.Text = "Uninstall NF Service";
|
||||
this.UninstallServiceToolStripMenuItem.Click += new System.EventHandler(this.UninstallServiceToolStripMenuItem_Click);
|
||||
//
|
||||
// UninstallTapDriverToolStripMenuItem
|
||||
//
|
||||
this.UninstallTapDriverToolStripMenuItem.Name = "UninstallTapDriverToolStripMenuItem";
|
||||
this.UninstallTapDriverToolStripMenuItem.Size = new System.Drawing.Size(220, 22);
|
||||
this.UninstallTapDriverToolStripMenuItem.Size = new System.Drawing.Size(243, 22);
|
||||
this.UninstallTapDriverToolStripMenuItem.Text = "Uninstall TUN/TAP driver";
|
||||
this.UninstallTapDriverToolStripMenuItem.Click += new System.EventHandler(this.reinstallTapDriverToolStripMenuItem_Click);
|
||||
this.UninstallTapDriverToolStripMenuItem.Click += new System.EventHandler(this.UninstallTapDriverToolStripMenuItem_Click);
|
||||
//
|
||||
// HelpToolStripMenuItem
|
||||
//
|
||||
this.HelpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.CheckForUpdatesToolStripMenuItem,
|
||||
this.fAQToolStripMenuItem});
|
||||
this.HelpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[]
|
||||
{
|
||||
this.CheckForUpdatesToolStripMenuItem, 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);
|
||||
@@ -525,14 +538,10 @@
|
||||
// StatusStrip
|
||||
//
|
||||
this.StatusStrip.ImageScalingSize = new System.Drawing.Size(20, 20);
|
||||
this.StatusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.StatusLabel,
|
||||
this.UsedBandwidthLabel,
|
||||
this.DownloadSpeedLabel,
|
||||
this.UploadSpeedLabel,
|
||||
this.blankToolStripStatusLabel,
|
||||
this.NatTypeStatusLabel,
|
||||
this.NatTypeStatusLightLabel});
|
||||
this.StatusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[]
|
||||
{
|
||||
this.StatusLabel, this.UsedBandwidthLabel, this.DownloadSpeedLabel, this.UploadSpeedLabel, this.blankToolStripStatusLabel, this.NatTypeStatusLabel, this.NatTypeStatusLightLabel
|
||||
});
|
||||
this.StatusStrip.Location = new System.Drawing.Point(0, 272);
|
||||
this.StatusStrip.Name = "StatusStrip";
|
||||
this.StatusStrip.Size = new System.Drawing.Size(740, 22);
|
||||
@@ -595,7 +604,7 @@
|
||||
//
|
||||
// ControlButton
|
||||
//
|
||||
this.ControlButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.ControlButton.Anchor = ((System.Windows.Forms.AnchorStyles) ((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.ControlButton.Location = new System.Drawing.Point(631, 3);
|
||||
this.ControlButton.Name = "ControlButton";
|
||||
this.ControlButton.Size = new System.Drawing.Size(75, 27);
|
||||
@@ -607,7 +616,7 @@
|
||||
// NotifyIcon
|
||||
//
|
||||
this.NotifyIcon.ContextMenuStrip = this.NotifyMenu;
|
||||
this.NotifyIcon.Icon = ((System.Drawing.Icon)(resources.GetObject("NotifyIcon.Icon")));
|
||||
this.NotifyIcon.Icon = ((System.Drawing.Icon) (resources.GetObject("NotifyIcon.Icon")));
|
||||
this.NotifyIcon.Text = "Netch";
|
||||
this.NotifyIcon.Visible = true;
|
||||
this.NotifyIcon.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.NotifyIcon_MouseDoubleClick);
|
||||
@@ -615,9 +624,10 @@
|
||||
// NotifyMenu
|
||||
//
|
||||
this.NotifyMenu.ImageScalingSize = new System.Drawing.Size(20, 20);
|
||||
this.NotifyMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.ShowMainFormToolStripButton,
|
||||
this.ExitToolStripButton});
|
||||
this.NotifyMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[]
|
||||
{
|
||||
this.ShowMainFormToolStripButton, this.ExitToolStripButton
|
||||
});
|
||||
this.NotifyMenu.Name = "NotifyMenu";
|
||||
this.NotifyMenu.ShowItemToolTips = false;
|
||||
this.NotifyMenu.Size = new System.Drawing.Size(108, 48);
|
||||
@@ -638,7 +648,7 @@
|
||||
//
|
||||
// SettingsButton
|
||||
//
|
||||
this.SettingsButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.SettingsButton.Anchor = ((System.Windows.Forms.AnchorStyles) ((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.SettingsButton.Location = new System.Drawing.Point(1, 3);
|
||||
this.SettingsButton.Name = "SettingsButton";
|
||||
this.SettingsButton.Size = new System.Drawing.Size(72, 27);
|
||||
@@ -697,6 +707,13 @@
|
||||
this.ButtomControlContainerControl.TabStop = false;
|
||||
this.ButtomControlContainerControl.Text = "groupBox1";
|
||||
//
|
||||
// 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);
|
||||
//
|
||||
// MainForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
|
||||
@@ -707,9 +724,9 @@
|
||||
this.Controls.Add(this.MenuStrip);
|
||||
this.Controls.Add(this.StatusStrip);
|
||||
this.Controls.Add(this.flowLayoutPanel1);
|
||||
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, ((byte) (134)));
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.Icon = ((System.Drawing.Icon) (resources.GetObject("$this.Icon")));
|
||||
this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||
this.MaximizeBox = false;
|
||||
this.Name = "MainForm";
|
||||
@@ -724,13 +741,13 @@
|
||||
this.configLayoutPanel.ResumeLayout(false);
|
||||
this.configLayoutPanel.PerformLayout();
|
||||
this.tableLayoutPanel2.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.EditServerPictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.CopyLinkPictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.DeleteServerPictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.SpeedPictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize) (this.EditServerPictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize) (this.CopyLinkPictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize) (this.DeleteServerPictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize) (this.SpeedPictureBox)).EndInit();
|
||||
this.tableLayoutPanel3.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.EditModePictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.DeleteModePictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize) (this.EditModePictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize) (this.DeleteModePictureBox)).EndInit();
|
||||
this.StatusStrip.ResumeLayout(false);
|
||||
this.StatusStrip.PerformLayout();
|
||||
this.NotifyMenu.ResumeLayout(false);
|
||||
@@ -740,8 +757,8 @@
|
||||
this.ButtomControlContainerControl.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
private System.Windows.Forms.ToolStripMenuItem removeNetchFirewallRulesToolStripMenuItem;
|
||||
|
||||
private System.Windows.Forms.ToolStripButton AboutToolStripButton;
|
||||
private System.Windows.Forms.ToolStripMenuItem CleanDNSCacheToolStripMenuItem;
|
||||
@@ -791,6 +808,7 @@
|
||||
private System.Windows.Forms.ToolStripMenuItem UpdateACLToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem updateACLWithProxyToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem UpdateServersFromSubscribeLinksToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripStatusLabel UploadSpeedLabel;
|
||||
private System.Windows.Forms.ToolStripStatusLabel UsedBandwidthLabel;
|
||||
private System.Windows.Forms.ToolStripLabel NewVersionLabel;
|
||||
@@ -803,5 +821,6 @@
|
||||
|
||||
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
|
||||
private System.Windows.Forms.ContainerControl ButtomControlContainerControl;
|
||||
private System.Windows.Forms.ToolStripMenuItem updatePACToolStripMenuItem;
|
||||
}
|
||||
}
|
||||
@@ -1,344 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Controllers;
|
||||
using Netch.Forms.Mode;
|
||||
using Netch.Models;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Forms
|
||||
{
|
||||
partial class Dummy
|
||||
{
|
||||
}
|
||||
|
||||
partial class MainForm
|
||||
{
|
||||
#region MenuStrip
|
||||
|
||||
#region 服务器
|
||||
|
||||
private void ImportServersFromClipboardToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
var texts = Clipboard.GetText();
|
||||
if (!string.IsNullOrWhiteSpace(texts))
|
||||
{
|
||||
var servers = ShareLink.ParseText(texts);
|
||||
Global.Settings.Server.AddRange(servers);
|
||||
NotifyTip(i18N.TranslateFormat("Import {0} server(s) form Clipboard", servers.Count));
|
||||
|
||||
InitServer();
|
||||
Configuration.Save();
|
||||
}
|
||||
}
|
||||
|
||||
private void AddServerToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
var s = ((ToolStripMenuItem) sender).Text;
|
||||
|
||||
var start = s.IndexOf("[", StringComparison.Ordinal) + 1;
|
||||
var end = s.IndexOf("]", start, StringComparison.Ordinal);
|
||||
var result = s.Substring(start, end - start);
|
||||
|
||||
Hide();
|
||||
ServerHelper.GetUtilByFullName(result).Create();
|
||||
|
||||
InitServer();
|
||||
Configuration.Save();
|
||||
Show();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 模式
|
||||
|
||||
private void CreateProcessModeToolStripButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
Hide();
|
||||
new Process().ShowDialog();
|
||||
Show();
|
||||
}
|
||||
|
||||
private void ReloadModesToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Enabled = false;
|
||||
try
|
||||
{
|
||||
ModeHelper.Load();
|
||||
InitMode();
|
||||
NotifyTip(i18N.Translate("Modes have been reload"));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
finally
|
||||
{
|
||||
Enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 订阅
|
||||
|
||||
private void ManageSubscribeLinksToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Hide();
|
||||
new SubscribeForm().ShowDialog();
|
||||
InitServer();
|
||||
Show();
|
||||
}
|
||||
|
||||
private async void UpdateServersFromSubscribeLinksToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
await UpdateServersFromSubscribe();
|
||||
}
|
||||
|
||||
|
||||
private async Task UpdateServersFromSubscribe()
|
||||
{
|
||||
void DisableItems(bool v)
|
||||
{
|
||||
MenuStrip.Enabled = ConfigurationGroupBox.Enabled = ProfileGroupBox.Enabled = ControlButton.Enabled = v;
|
||||
}
|
||||
|
||||
if (Global.Settings.UseProxyToUpdateSubscription && ServerComboBox.SelectedIndex == -1)
|
||||
Global.Settings.UseProxyToUpdateSubscription = false;
|
||||
|
||||
if (Global.Settings.UseProxyToUpdateSubscription && ServerComboBox.SelectedIndex == -1)
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("Please select a server first"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (Global.Settings.SubscribeLink.Count <= 0)
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("No subscription link"));
|
||||
return;
|
||||
}
|
||||
|
||||
StatusText(i18N.Translate("Starting update subscription"));
|
||||
DisableItems(false);
|
||||
var useProxyToUpdateSubscription = Global.Settings.UseProxyToUpdateSubscription;
|
||||
try
|
||||
{
|
||||
string proxyServer = null;
|
||||
if (useProxyToUpdateSubscription)
|
||||
{
|
||||
var mode = new Models.Mode
|
||||
{
|
||||
Remark = "ProxyUpdate",
|
||||
Type = 5
|
||||
};
|
||||
await MainController.Start(ServerComboBox.SelectedItem as Server, mode);
|
||||
proxyServer = $"http://127.0.0.1:{Global.Settings.HTTPLocalPort}";
|
||||
}
|
||||
|
||||
await Subscription.UpdateServersAsync(proxyServer);
|
||||
|
||||
InitServer();
|
||||
Configuration.Save();
|
||||
StatusText(i18N.Translate("Subscription updated"));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (useProxyToUpdateSubscription)
|
||||
{
|
||||
try
|
||||
{
|
||||
await MainController.Stop();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
DisableItems(true);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 选项
|
||||
|
||||
private void CheckForUpdatesToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
void OnNewVersionNotFound(object o, EventArgs args)
|
||||
{
|
||||
_updater.NewVersionNotFound -= OnNewVersionNotFound;
|
||||
NotifyTip(i18N.Translate("Already latest version"));
|
||||
}
|
||||
|
||||
void OnNewVersionFoundFailed(object o, EventArgs args)
|
||||
{
|
||||
_updater.NewVersionFoundFailed -= OnNewVersionFoundFailed;
|
||||
NotifyTip(i18N.Translate("New version found failed"), info: false);
|
||||
}
|
||||
|
||||
_updater.NewVersionNotFound += OnNewVersionNotFound;
|
||||
_updater.NewVersionFoundFailed += OnNewVersionFoundFailed;
|
||||
CheckUpdate();
|
||||
});
|
||||
}
|
||||
|
||||
private void OpenDirectoryToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Utils.Utils.Open(".\\");
|
||||
}
|
||||
|
||||
private async void CleanDNSCacheToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
NativeMethods.FlushDNSResolverCache();
|
||||
DNS.Cache.Clear();
|
||||
});
|
||||
|
||||
StatusText(i18N.Translate("DNS cache cleanup succeeded"));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
private void updateACLWithProxyToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
UpdateACL(true);
|
||||
}
|
||||
|
||||
private void updateACLToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
UpdateACL(false);
|
||||
}
|
||||
|
||||
private async void UpdateACL(bool useProxy)
|
||||
{
|
||||
if (useProxy && ServerComboBox.SelectedIndex == -1)
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("Please select a server first"));
|
||||
return;
|
||||
}
|
||||
|
||||
Enabled = false;
|
||||
|
||||
NotifyTip(i18N.Translate("Updating in the background"));
|
||||
try
|
||||
{
|
||||
if (useProxy)
|
||||
{
|
||||
var mode = new Models.Mode
|
||||
{
|
||||
Remark = "ProxyUpdate",
|
||||
Type = 5
|
||||
};
|
||||
State = State.Starting;
|
||||
await MainController.Start(ServerComboBox.SelectedItem as Server, mode);
|
||||
}
|
||||
|
||||
var req = WebUtil.CreateRequest(Global.Settings.ACL);
|
||||
if (useProxy)
|
||||
req.Proxy = new WebProxy($"http://127.0.0.1:{Global.Settings.HTTPLocalPort}");
|
||||
|
||||
await WebUtil.DownloadFileAsync(req, Path.Combine(Global.NetchDir, "bin\\default.acl"));
|
||||
NotifyTip(i18N.Translate("ACL updated successfully"));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
NotifyTip(i18N.Translate("ACL update failed") + "\n" + e.Message, info: false);
|
||||
Logging.Error("更新 ACL 失败!" + e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (useProxy)
|
||||
{
|
||||
await MainController.Stop();
|
||||
State = State.Stopped;
|
||||
}
|
||||
|
||||
Enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private async void UninstallServiceToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Enabled = false;
|
||||
StatusText(i18N.TranslateFormat("Uninstalling {0}", "NF Service"));
|
||||
try
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
if (NFController.UninstallDriver())
|
||||
{
|
||||
StatusText(i18N.TranslateFormat("{0} has been uninstalled", "NF Service"));
|
||||
}
|
||||
});
|
||||
}
|
||||
finally
|
||||
{
|
||||
Enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private async void reinstallTapDriverToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
StatusText(i18N.TranslateFormat("Uninstalling {0}", "TUN/TAP driver"));
|
||||
Enabled = false;
|
||||
try
|
||||
{
|
||||
await Task.Run(TUNTAP.deltapall);
|
||||
StatusText(i18N.TranslateFormat("{0} has been uninstalled", "TUN/TAP driver"));
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Logging.Error($"卸载 TUN/TAP 适配器失败: {exception}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
State = State.Waiting;
|
||||
Enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Exit(true);
|
||||
}
|
||||
|
||||
private void VersionLabel_Click(object sender, EventArgs e)
|
||||
{
|
||||
Utils.Utils.Open($"https://github.com/{UpdateChecker.Owner}/{UpdateChecker.Repo}/releases");
|
||||
}
|
||||
|
||||
private void AboutToolStripButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
Hide();
|
||||
new AboutForm().ShowDialog();
|
||||
Show();
|
||||
}
|
||||
|
||||
private void fAQToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Utils.Utils.Open($"https://netch.org/#/docs/zh-CN/faq");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Controllers;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Forms
|
||||
{
|
||||
/// <summary lang="en">
|
||||
/// this class is used to disable Designer <para />
|
||||
/// </summary>
|
||||
/// <summary lang="zh">
|
||||
/// 此类用于禁用设计器
|
||||
/// </summary>
|
||||
[DesignerCategory("")]
|
||||
public partial class Dummy
|
||||
{
|
||||
}
|
||||
|
||||
partial class MainForm
|
||||
{
|
||||
private readonly UpdateChecker _updater = new UpdateChecker();
|
||||
|
||||
private void CheckUpdate()
|
||||
{
|
||||
_updater.NewVersionFound += (o, args) =>
|
||||
{
|
||||
NotifyTip($"{i18N.Translate(@"New version available", ": ")}{_updater.LatestVersionNumber}");
|
||||
NewVersionLabel.Visible = true;
|
||||
};
|
||||
_updater.Check(Global.Settings.CheckBetaUpdate);
|
||||
}
|
||||
|
||||
private async void NewVersionLabel_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (!_updater.LatestRelease.assets.Any())
|
||||
{
|
||||
Utils.Utils.Open(_updater.LatestVersionUrl);
|
||||
return;
|
||||
}
|
||||
|
||||
if (MessageBoxX.Show(i18N.Translate("Download and install now?"), confirm: true) != DialogResult.OK)
|
||||
return;
|
||||
NotifyTip(i18N.Translate("Start downloading new version"));
|
||||
|
||||
var latestVersionDownloadUrl = _updater.LatestRelease.assets[0].browser_download_url;
|
||||
var tagPage = await WebUtil.DownloadStringAsync(WebUtil.CreateRequest(_updater.LatestVersionUrl));
|
||||
var match = Regex.Match(tagPage, @"<td .*>(?<sha256>.*)</td>", RegexOptions.Singleline);
|
||||
|
||||
// TODO Replace with regex get basename and sha256
|
||||
var fileName = Path.GetFileName(new Uri(latestVersionDownloadUrl).LocalPath);
|
||||
fileName = fileName.Insert(fileName.LastIndexOf('.'), _updater.LatestVersionNumber);
|
||||
var fileFullPath = Path.Combine(Global.NetchDir, "data", fileName);
|
||||
|
||||
var sha256 = match.Groups["sha256"].Value;
|
||||
|
||||
try
|
||||
{
|
||||
if (File.Exists(fileFullPath))
|
||||
{
|
||||
if (Utils.Utils.SHA256CheckSum(fileFullPath) == sha256)
|
||||
{
|
||||
RunUpdater();
|
||||
return;
|
||||
}
|
||||
|
||||
File.Delete(fileFullPath);
|
||||
}
|
||||
|
||||
// TODO Replace "New Version Found" to Progress bar
|
||||
await WebUtil.DownloadFileAsync(WebUtil.CreateRequest(latestVersionDownloadUrl), fileFullPath);
|
||||
|
||||
if (Utils.Utils.SHA256CheckSum(fileFullPath) != sha256)
|
||||
{
|
||||
MessageBoxX.Show("The downloaded file has the wrong hash");
|
||||
return;
|
||||
}
|
||||
|
||||
RunUpdater();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
NotifyTip($"{i18N.Translate("Download update failed")}\n{exception.Message}");
|
||||
Logging.Error($"下载更新失败 {exception}");
|
||||
}
|
||||
|
||||
void RunUpdater()
|
||||
{
|
||||
// if debugging process stopped, debugger will kill child processes!!!!
|
||||
// 调试进程结束,调试器将会杀死子进程
|
||||
// uncomment if(!Debugger.isAttach) block in NetchUpdater Project's main() method and attach to NetchUpdater process to debug
|
||||
// 在 NetchUpdater 项目的 main() 方法中取消注释 if(!Debugger.isAttach)块,并附加到 NetchUpdater 进程进行调试
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = Path.Combine(Global.NetchDir, "NetchUpdater.exe"),
|
||||
Arguments =
|
||||
$"{Global.Settings.UDPSocketPort} \"{fileFullPath}\" \"{Global.NetchDir}\""
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,187 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Models;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Forms
|
||||
{
|
||||
public partial class Dummy
|
||||
{
|
||||
}
|
||||
|
||||
partial class MainForm
|
||||
{
|
||||
private int _configurationGroupBoxHeight;
|
||||
private int _profileConfigurationHeight;
|
||||
|
||||
private void InitProfile()
|
||||
{
|
||||
// Clear
|
||||
foreach (var button in ProfileButtons)
|
||||
button.Dispose();
|
||||
|
||||
ProfileButtons.Clear();
|
||||
ProfileTable.ColumnStyles.Clear();
|
||||
ProfileTable.RowStyles.Clear();
|
||||
|
||||
var numProfile = Global.Settings.ProfileCount;
|
||||
if (numProfile == 0)
|
||||
{
|
||||
// Hide Profile GroupBox, Change window size
|
||||
configLayoutPanel.RowStyles[2].SizeType = SizeType.Percent;
|
||||
configLayoutPanel.RowStyles[2].Height = 0;
|
||||
ProfileGroupBox.Visible = false;
|
||||
|
||||
ConfigurationGroupBox.Size = new Size(ConfigurationGroupBox.Size.Width, _configurationGroupBoxHeight - _profileConfigurationHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load Profiles
|
||||
ProfileTable.ColumnCount = numProfile;
|
||||
|
||||
while (Global.Settings.Profiles.Count < numProfile)
|
||||
{
|
||||
Global.Settings.Profiles.Add(new Profile());
|
||||
}
|
||||
|
||||
for (var i = 0; i < numProfile; ++i)
|
||||
{
|
||||
var b = new Button();
|
||||
b.Click += ProfileButton_Click;
|
||||
b.Dock = DockStyle.Fill;
|
||||
b.Text = !Global.Settings.Profiles[i].IsDummy ? Global.Settings.Profiles[i].ProfileName : i18N.Translate("None");
|
||||
|
||||
ProfileTable.Controls.Add(b, i, 0);
|
||||
ProfileButtons.Add(b);
|
||||
}
|
||||
|
||||
// equal column
|
||||
for (var i = 1; i <= ProfileTable.RowCount; i++)
|
||||
{
|
||||
ProfileTable.RowStyles.Add(new RowStyle(SizeType.Percent, 1));
|
||||
}
|
||||
|
||||
for (var i = 1; i <= ProfileTable.ColumnCount; i++)
|
||||
{
|
||||
ProfileTable.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 1));
|
||||
}
|
||||
|
||||
configLayoutPanel.RowStyles[2].SizeType = SizeType.AutoSize;
|
||||
ProfileGroupBox.Visible = true;
|
||||
ConfigurationGroupBox.Size = new Size(ConfigurationGroupBox.Size.Width, _configurationGroupBoxHeight);
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadProfile(int index)
|
||||
{
|
||||
var p = Global.Settings.Profiles[index];
|
||||
ProfileNameText.Text = p.ProfileName;
|
||||
ModeComboBox.ResetCompletionList();
|
||||
|
||||
if (p.IsDummy)
|
||||
throw new Exception("Profile not found.");
|
||||
|
||||
var server = ServerComboBox.Items.Cast<Server>().FirstOrDefault(s => s.Remark.Equals(p.ServerRemark));
|
||||
var mode = ModeComboBox.Items.Cast<Models.Mode>().FirstOrDefault(m => m.Remark.Equals(p.ModeRemark));
|
||||
|
||||
if (server == null)
|
||||
{
|
||||
throw new Exception("Server not found.");
|
||||
}
|
||||
|
||||
if (mode == null)
|
||||
{
|
||||
throw new Exception("Mode not found.");
|
||||
}
|
||||
|
||||
ServerComboBox.SelectedItem = server;
|
||||
ModeComboBox.SelectedItem = mode;
|
||||
}
|
||||
|
||||
private void SaveProfile(int index)
|
||||
{
|
||||
var selectedServer = (Server) ServerComboBox.SelectedItem;
|
||||
var selectedMode = (Models.Mode) ModeComboBox.SelectedItem;
|
||||
var name = ProfileNameText.Text;
|
||||
|
||||
Global.Settings.Profiles[index] = new Profile(selectedServer, selectedMode, name);
|
||||
}
|
||||
|
||||
private void RemoveProfile(int index)
|
||||
{
|
||||
Global.Settings.Profiles[index] = new Profile();
|
||||
}
|
||||
|
||||
|
||||
private List<Button> ProfileButtons = new List<Button>();
|
||||
|
||||
private async void ProfileButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
var index = ProfileButtons.IndexOf((Button) sender);
|
||||
|
||||
if (ModifierKeys == Keys.Control)
|
||||
{
|
||||
if (ServerComboBox.SelectedIndex == -1)
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("Please select a server first"));
|
||||
}
|
||||
else if (ModeComboBox.SelectedIndex == -1)
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("Please select a mode first"));
|
||||
}
|
||||
else if (ProfileNameText.Text == "")
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("Please enter a profile name first"));
|
||||
}
|
||||
else
|
||||
{
|
||||
SaveProfile(index);
|
||||
ProfileButtons[index].Text = ProfileNameText.Text;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (Global.Settings.Profiles[index].IsDummy)
|
||||
{
|
||||
MessageBoxX.Show(
|
||||
i18N.Translate("No saved profile here. Save a profile first by Ctrl+Click on the button"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (ModifierKeys == Keys.Shift)
|
||||
{
|
||||
if (MessageBoxX.Show(i18N.Translate("Remove this Profile?"), confirm: true) != DialogResult.OK) return;
|
||||
RemoveProfile(index);
|
||||
ProfileButtons[index].Text = i18N.Translate("None");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
LoadProfile(index);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
MessageBoxX.Show(exception.Message, LogLevel.ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
// start the profile
|
||||
ControlFun();
|
||||
if (State == State.Stopping || State == State.Stopped)
|
||||
{
|
||||
while (State != State.Stopped)
|
||||
{
|
||||
await Task.Delay(250);
|
||||
}
|
||||
|
||||
ControlFun();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,175 +0,0 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Forms
|
||||
{
|
||||
public partial class Dummy
|
||||
{
|
||||
}
|
||||
|
||||
partial class MainForm
|
||||
{
|
||||
#region Server
|
||||
|
||||
private void InitServer()
|
||||
{
|
||||
var comboBoxInitialized = _comboBoxInitialized;
|
||||
_comboBoxInitialized = false;
|
||||
|
||||
ServerComboBox.Items.Clear();
|
||||
ServerComboBox.Items.AddRange(Global.Settings.Server.ToArray());
|
||||
SelectLastServer();
|
||||
_comboBoxInitialized = comboBoxInitialized;
|
||||
}
|
||||
|
||||
private static void TestServer()
|
||||
{
|
||||
try
|
||||
{
|
||||
Parallel.ForEach(Global.Settings.Server, new ParallelOptions {MaxDegreeOfParallelism = 16},
|
||||
server => { server.Test(); });
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
public void SelectLastServer()
|
||||
{
|
||||
// 如果值合法,选中该位置
|
||||
if (Global.Settings.ServerComboBoxSelectedIndex > 0 &&
|
||||
Global.Settings.ServerComboBoxSelectedIndex < ServerComboBox.Items.Count)
|
||||
{
|
||||
ServerComboBox.SelectedIndex = Global.Settings.ServerComboBoxSelectedIndex;
|
||||
}
|
||||
// 如果值非法,且当前 ServerComboBox 中有元素,选择第一个位置
|
||||
else if (ServerComboBox.Items.Count > 0)
|
||||
{
|
||||
ServerComboBox.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
// 如果当前 ServerComboBox 中没元素,不做处理
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Mode
|
||||
|
||||
public void InitMode()
|
||||
{
|
||||
var comboBoxInitialized = _comboBoxInitialized;
|
||||
_comboBoxInitialized = false;
|
||||
|
||||
ModeComboBox.Items.Clear();
|
||||
ModeComboBox.Items.AddRange(Global.Modes.ToArray());
|
||||
ModeComboBox.Tag = null;
|
||||
SelectLastMode();
|
||||
_comboBoxInitialized = comboBoxInitialized;
|
||||
}
|
||||
|
||||
public void SelectLastMode()
|
||||
{
|
||||
// 如果值合法,选中该位置
|
||||
if (Global.Settings.ModeComboBoxSelectedIndex > 0 &&
|
||||
Global.Settings.ModeComboBoxSelectedIndex < ModeComboBox.Items.Count)
|
||||
{
|
||||
ModeComboBox.SelectedIndex = Global.Settings.ModeComboBoxSelectedIndex;
|
||||
}
|
||||
// 如果值非法,且当前 ModeComboBox 中有元素,选择第一个位置
|
||||
else if (ModeComboBox.Items.Count > 0)
|
||||
{
|
||||
ModeComboBox.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
// 如果当前 ModeComboBox 中没元素,不做处理
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Init at <see cref="MainForm_Load"/>
|
||||
/// </summary>
|
||||
private int _eWidth;
|
||||
|
||||
private void ComboBox_DrawItem(object sender, DrawItemEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!(sender is ComboBox cbx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 绘制背景颜色
|
||||
e.Graphics.FillRectangle(new SolidBrush(Color.White), e.Bounds);
|
||||
|
||||
if (e.Index < 0) return;
|
||||
|
||||
// 绘制 备注/名称 字符串
|
||||
e.Graphics.DrawString(cbx.Items[e.Index].ToString(), cbx.Font, new SolidBrush(Color.Black), e.Bounds);
|
||||
|
||||
switch (cbx.Items[e.Index])
|
||||
{
|
||||
case Models.Server item:
|
||||
{
|
||||
// 计算延迟底色
|
||||
SolidBrush brush;
|
||||
if (item.Delay > 200)
|
||||
brush = new SolidBrush(Color.Red);
|
||||
else if (item.Delay > 80)
|
||||
brush = new SolidBrush(Color.Yellow);
|
||||
else if (item.Delay >= 0)
|
||||
brush = new SolidBrush(Color.FromArgb(50, 255, 56));
|
||||
else
|
||||
brush = new SolidBrush(Color.Gray);
|
||||
|
||||
// 绘制延迟底色
|
||||
e.Graphics.FillRectangle(brush, _eWidth * 9, e.Bounds.Y, _eWidth, e.Bounds.Height);
|
||||
|
||||
// 绘制延迟字符串
|
||||
e.Graphics.DrawString(item.Delay.ToString(), cbx.Font, new SolidBrush(Color.Black),
|
||||
_eWidth * 9 + _eWidth / 30, e.Bounds.Y);
|
||||
break;
|
||||
}
|
||||
case Models.Mode item:
|
||||
{
|
||||
// 绘制 模式Box 底色
|
||||
e.Graphics.FillRectangle(new SolidBrush(Color.Gray), _eWidth * 9, e.Bounds.Y, _eWidth,
|
||||
e.Bounds.Height);
|
||||
|
||||
// 绘制 模式行数 字符串
|
||||
e.Graphics.DrawString(item.Rule.Count.ToString(), cbx.Font, new SolidBrush(Color.Black),
|
||||
_eWidth * 9 + _eWidth / 30, e.Bounds.Y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
private void AddAddServerToolStripMenuItems()
|
||||
{
|
||||
foreach (var serversUtil in ServerHelper.ServerUtils.Where(i => !string.IsNullOrEmpty(i.FullName)))
|
||||
{
|
||||
var fullName = serversUtil.FullName;
|
||||
var control = new ToolStripMenuItem
|
||||
{
|
||||
Name = $"Add{fullName}ServerToolStripMenuItem",
|
||||
Size = new Size(259, 22),
|
||||
Text = i18N.TranslateFormat("Add [{0}] Server", fullName),
|
||||
};
|
||||
_mainFormText.Add(control.Name, new[] {"Add [{0}] Server", fullName});
|
||||
control.Click += AddServerToolStripMenuItem_Click;
|
||||
ServerToolStripMenuItem.DropDownItems.Add(control);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,233 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using Netch.Models;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Forms
|
||||
{
|
||||
public partial class Dummy
|
||||
{
|
||||
}
|
||||
|
||||
partial class MainForm
|
||||
{
|
||||
private bool IsWaiting => State == State.Waiting || State == State.Stopped;
|
||||
|
||||
private State _state = State.Waiting;
|
||||
|
||||
/// <summary>
|
||||
/// 当前状态
|
||||
/// </summary>
|
||||
public State State
|
||||
{
|
||||
get => _state;
|
||||
private set
|
||||
{
|
||||
void StartDisableItems(bool enabled)
|
||||
{
|
||||
ServerComboBox.Enabled =
|
||||
ModeComboBox.Enabled =
|
||||
EditModePictureBox.Enabled =
|
||||
EditServerPictureBox.Enabled =
|
||||
DeleteModePictureBox.Enabled =
|
||||
DeleteServerPictureBox.Enabled = enabled;
|
||||
|
||||
// 启动需要禁用的控件
|
||||
UninstallServiceToolStripMenuItem.Enabled =
|
||||
UpdateACLToolStripMenuItem.Enabled =
|
||||
updateACLWithProxyToolStripMenuItem.Enabled =
|
||||
UpdateServersFromSubscribeLinksToolStripMenuItem.Enabled =
|
||||
UninstallTapDriverToolStripMenuItem.Enabled =
|
||||
ReloadModesToolStripMenuItem.Enabled = enabled;
|
||||
}
|
||||
|
||||
_state = value;
|
||||
|
||||
StatusText(i18N.Translate(StateExtension.GetStatusString(value)));
|
||||
switch (value)
|
||||
{
|
||||
case State.Waiting:
|
||||
ControlButton.Enabled = true;
|
||||
ControlButton.Text = i18N.Translate("Start");
|
||||
|
||||
break;
|
||||
case State.Starting:
|
||||
ControlButton.Enabled = false;
|
||||
ControlButton.Text = "...";
|
||||
|
||||
ProfileGroupBox.Enabled = false;
|
||||
StartDisableItems(false);
|
||||
break;
|
||||
case State.Started:
|
||||
ControlButton.Enabled = true;
|
||||
ControlButton.Text = i18N.Translate("Stop");
|
||||
|
||||
StatusTextAppend(StatusPortInfoText.Value);
|
||||
|
||||
ProfileGroupBox.Enabled = true;
|
||||
|
||||
UsedBandwidthLabel.Visible /*= UploadSpeedLabel.Visible*/ = DownloadSpeedLabel.Visible = Global.Flags.IsWindows10Upper;
|
||||
break;
|
||||
case State.Stopping:
|
||||
ControlButton.Enabled = false;
|
||||
ControlButton.Text = "...";
|
||||
|
||||
ProfileGroupBox.Enabled = false;
|
||||
UsedBandwidthLabel.Visible /*= UploadSpeedLabel.Visible*/ = DownloadSpeedLabel.Visible = false;
|
||||
NatTypeStatusText();
|
||||
break;
|
||||
case State.Stopped:
|
||||
ControlButton.Enabled = true;
|
||||
ControlButton.Text = i18N.Translate("Start");
|
||||
|
||||
LastUploadBandwidth = 0;
|
||||
LastDownloadBandwidth = 0;
|
||||
Bandwidth.Stop();
|
||||
|
||||
ProfileGroupBox.Enabled = true;
|
||||
StartDisableItems(true);
|
||||
break;
|
||||
case State.Terminating:
|
||||
Dispose();
|
||||
Environment.Exit(Environment.ExitCode);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void NatTypeStatusText(string text = "", string country = "")
|
||||
{
|
||||
if (InvokeRequired)
|
||||
{
|
||||
BeginInvoke(new Action<string, string>(NatTypeStatusText), text, country);
|
||||
return;
|
||||
}
|
||||
|
||||
if (State != State.Started)
|
||||
{
|
||||
NatTypeStatusLabel.Text = "";
|
||||
NatTypeStatusLabel.Visible = NatTypeStatusLightLabel.Visible = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(text))
|
||||
{
|
||||
NatTypeStatusLabel.Text = $"NAT{i18N.Translate(": ")}{text} {(country != string.Empty ? $"[{country}]" : "")}";
|
||||
|
||||
UpdateNatTypeLight(int.TryParse(text, out var natType) ? natType : -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
NatTypeStatusLabel.Text = $@"NAT{i18N.Translate(": ", "Test failed")}";
|
||||
}
|
||||
|
||||
NatTypeStatusLabel.Visible = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新 NAT指示灯颜色
|
||||
/// </summary>
|
||||
/// <param name="natType"></param>
|
||||
private void UpdateNatTypeLight(int natType = -1)
|
||||
{
|
||||
if (natType > 0 && natType < 5)
|
||||
{
|
||||
NatTypeStatusLightLabel.Visible = Global.Flags.IsWindows10Upper;
|
||||
Color c;
|
||||
switch (natType)
|
||||
{
|
||||
case 1:
|
||||
c = Color.LimeGreen;
|
||||
break;
|
||||
case 2:
|
||||
c = Color.Yellow;
|
||||
break;
|
||||
case 3:
|
||||
c = Color.Red;
|
||||
break;
|
||||
case 4:
|
||||
c = Color.Black;
|
||||
break;
|
||||
default:
|
||||
c = Color.Black;
|
||||
break;
|
||||
}
|
||||
|
||||
NatTypeStatusLightLabel.ForeColor = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
NatTypeStatusLightLabel.Visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新状态栏文本
|
||||
/// </summary>
|
||||
/// <param name="text"></param>
|
||||
public void StatusText(string text)
|
||||
{
|
||||
if (InvokeRequired)
|
||||
{
|
||||
BeginInvoke(new Action<string>(StatusText), text);
|
||||
return;
|
||||
}
|
||||
|
||||
StatusLabel.Text = i18N.Translate("Status", ": ") + text;
|
||||
}
|
||||
|
||||
public void StatusTextAppend(string text)
|
||||
{
|
||||
StatusLabel.Text += text;
|
||||
}
|
||||
|
||||
public static class StatusPortInfoText
|
||||
{
|
||||
private static ushort? _socks5Port;
|
||||
private static ushort? _httpPort;
|
||||
private static bool _shareLan;
|
||||
|
||||
public static ushort HttpPort
|
||||
{
|
||||
set => _httpPort = value;
|
||||
}
|
||||
|
||||
public static ushort Socks5Port
|
||||
{
|
||||
set => _socks5Port = value;
|
||||
}
|
||||
|
||||
public static void UpdateShareLan() => _shareLan = Global.Settings.LocalAddress != "127.0.0.1";
|
||||
|
||||
public static string Value
|
||||
{
|
||||
get
|
||||
{
|
||||
var strings = new List<string>();
|
||||
|
||||
if (_socks5Port != null)
|
||||
{
|
||||
strings.Add($"Socks5 {i18N.Translate("Local Port", ": ")}{_socks5Port}");
|
||||
}
|
||||
|
||||
if (_httpPort != null)
|
||||
{
|
||||
strings.Add($"HTTP {i18N.Translate("Local Port", ": ")}{_httpPort}");
|
||||
}
|
||||
|
||||
if (!strings.Any())
|
||||
return string.Empty;
|
||||
|
||||
return $" ({(_shareLan ? i18N.Translate("Allow other Devices to connect") + " " : "")}{string.Join(" | ", strings)})";
|
||||
}
|
||||
}
|
||||
|
||||
public static void Reset()
|
||||
{
|
||||
_httpPort = _socks5Port = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,11 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Models;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Utils
|
||||
namespace Netch.Forms
|
||||
{
|
||||
static class MessageBoxX
|
||||
public static class MessageBoxX
|
||||
{
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
@@ -34,11 +35,11 @@ namespace Netch.Utils
|
||||
};
|
||||
|
||||
return MessageBox.Show(
|
||||
owner: owner,
|
||||
text: text,
|
||||
caption: i18N.Translate(title),
|
||||
buttons: confirm ? MessageBoxButtons.OKCancel : MessageBoxButtons.OK,
|
||||
icon: msgIcon);
|
||||
owner,
|
||||
text,
|
||||
i18N.Translate(title),
|
||||
confirm ? MessageBoxButtons.OKCancel : MessageBoxButtons.OK,
|
||||
msgIcon);
|
||||
}
|
||||
}
|
||||
}
|
||||
582
Netch/Forms/SettingForm.Designer.cs
generated
582
Netch/Forms/SettingForm.Designer.cs
generated
File diff suppressed because it is too large
Load Diff
@@ -1,18 +1,20 @@
|
||||
using Netch.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Forms
|
||||
{
|
||||
public partial class SettingForm : Form
|
||||
{
|
||||
private readonly Dictionary<Control, Func<string, bool>> _checkActions = new();
|
||||
|
||||
private readonly Dictionary<Control, Action<Control>> _saveActions = new();
|
||||
public SettingForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
@@ -20,7 +22,6 @@ namespace Netch.Forms
|
||||
InitValue();
|
||||
}
|
||||
|
||||
|
||||
private void SettingForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
TUNTAPUseCustomDNSCheckBox_CheckedChanged(null, null);
|
||||
@@ -59,17 +60,26 @@ namespace Netch.Forms
|
||||
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);
|
||||
BindCheckBox(TcpingAtStartedCheckBox,
|
||||
b => Global.Settings.StartedTcping = b,
|
||||
Global.Settings.StartedTcping);
|
||||
BindTextBox<int>(DetectionIntervalTextBox,
|
||||
i => i >= 0,
|
||||
i => Global.Settings.StartedTcping_Interval = i,
|
||||
Global.Settings.StartedTcping_Interval);
|
||||
BindTextBox<int>(DetectionTickTextBox,
|
||||
i => ServerHelper.DelayTestHelper.Range.InRange(i),
|
||||
i => Global.Settings.DetectionTick = i,
|
||||
Global.Settings.DetectionTick);
|
||||
BindTextBox<int>(StartedPingIntervalTextBox,
|
||||
_ => true,
|
||||
i => Global.Settings.StartedPingInterval = i,
|
||||
Global.Settings.StartedPingInterval);
|
||||
|
||||
InitSTUN();
|
||||
|
||||
@@ -90,8 +100,6 @@ namespace Netch.Forms
|
||||
b => Global.Settings.ModifySystemDNS = b,
|
||||
Global.Settings.ModifySystemDNS);
|
||||
|
||||
ModifySystemDNSCheckBox_CheckedChanged(null, null);
|
||||
|
||||
BindTextBox(ModifiedDNSTextBox,
|
||||
s => DNS.TrySplit(s, out _, 2),
|
||||
s => Global.Settings.ModifiedDNS = s,
|
||||
@@ -105,6 +113,10 @@ namespace Netch.Forms
|
||||
s => Global.Settings.ProcessNoProxyForUdp = s,
|
||||
Global.Settings.ProcessNoProxyForUdp);
|
||||
|
||||
BindCheckBox(NoProxyForTcpCheckBox,
|
||||
s => Global.Settings.ProcessNoProxyForTcp = s,
|
||||
Global.Settings.ProcessNoProxyForTcp);
|
||||
|
||||
#endregion
|
||||
|
||||
#region TUN/TAP
|
||||
@@ -124,7 +136,6 @@ namespace Netch.Forms
|
||||
BindCheckBox(UseCustomDNSCheckBox,
|
||||
b => { Global.Settings.TUNTAP.UseCustomDNS = b; },
|
||||
Global.Settings.TUNTAP.UseCustomDNS);
|
||||
TUNTAPUseCustomDNSCheckBox_CheckedChanged(null, null);
|
||||
|
||||
BindTextBox(TUNTAPDNSTextBox,
|
||||
s => !UseCustomDNSCheckBox.Checked || DNS.TrySplit(s, out _, 2),
|
||||
@@ -160,6 +171,10 @@ namespace Netch.Forms
|
||||
|
||||
#region V2Ray
|
||||
|
||||
BindCheckBox(XrayConeCheckBox,
|
||||
b => Global.Settings.V2RayConfig.XrayCone = b,
|
||||
Global.Settings.V2RayConfig.XrayCone);
|
||||
|
||||
BindCheckBox(TLSAllowInsecureCheckBox,
|
||||
b => Global.Settings.V2RayConfig.AllowInsecure = b,
|
||||
Global.Settings.V2RayConfig.AllowInsecure);
|
||||
@@ -227,9 +242,9 @@ namespace Netch.Forms
|
||||
b => Global.Settings.CheckBetaUpdate = b,
|
||||
Global.Settings.CheckBetaUpdate);
|
||||
|
||||
BindCheckBox(UpdateSubscribeatWhenOpenedCheckBox,
|
||||
b => Global.Settings.UpdateSubscribeatWhenOpened = b,
|
||||
Global.Settings.UpdateSubscribeatWhenOpened);
|
||||
BindCheckBox(UpdateServersWhenOpenedCheckBox,
|
||||
b => Global.Settings.UpdateServersWhenOpened = b,
|
||||
Global.Settings.UpdateServersWhenOpened);
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -255,21 +270,14 @@ namespace Netch.Forms
|
||||
|
||||
private void TUNTAPUseCustomDNSCheckBox_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
TUNTAPDNSTextBox.Enabled = UseCustomDNSCheckBox.Checked;
|
||||
|
||||
if (UseCustomDNSCheckBox.Checked)
|
||||
{
|
||||
TUNTAPDNSTextBox.Text = Global.Settings.TUNTAP.DNS.Any()
|
||||
? DNS.Join(Global.Settings.TUNTAP.DNS)
|
||||
: "1.1.1.1";
|
||||
}
|
||||
else
|
||||
{
|
||||
TUNTAPDNSTextBox.Text = "AioDNS";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void InitSTUN()
|
||||
{
|
||||
try
|
||||
@@ -306,14 +314,13 @@ namespace Netch.Forms
|
||||
}
|
||||
|
||||
if (!flag)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CheckSTUN
|
||||
|
||||
var stunFlag = true;
|
||||
var errFlag = false;
|
||||
var stunServer = string.Empty;
|
||||
ushort stunServerPort = 3478;
|
||||
|
||||
@@ -324,16 +331,14 @@ namespace Netch.Forms
|
||||
stunServer = stun[0];
|
||||
if (stun.Length > 1)
|
||||
if (!ushort.TryParse(stun[1], out stunServerPort))
|
||||
{
|
||||
stunFlag = false;
|
||||
}
|
||||
errFlag = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
stunFlag = false;
|
||||
errFlag = true;
|
||||
}
|
||||
|
||||
if (!stunFlag)
|
||||
if (errFlag)
|
||||
{
|
||||
Utils.Utils.ChangeControlForeColor(STUN_ServerComboBox, Color.Red);
|
||||
return;
|
||||
@@ -341,14 +346,10 @@ namespace Netch.Forms
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Save
|
||||
|
||||
foreach (var pair in _saveActions)
|
||||
{
|
||||
pair.Value.Invoke(pair.Key);
|
||||
}
|
||||
|
||||
Global.Settings.STUN_Server = stunServer;
|
||||
Global.Settings.STUN_Server_Port = stunServerPort;
|
||||
@@ -417,17 +418,22 @@ namespace Netch.Forms
|
||||
private void BindCheckBox(CheckBox control, Action<bool> save, bool value)
|
||||
{
|
||||
control.Checked = value;
|
||||
_checkActions.Add(control, s => true);
|
||||
_saveActions.Add(control, c => save.Invoke(((CheckBox) c).Checked));
|
||||
}
|
||||
|
||||
private readonly Dictionary<Control, Func<string, bool>> _checkActions = new Dictionary<Control, Func<string, bool>>();
|
||||
|
||||
private readonly Dictionary<Control, Action<Control>> _saveActions = new Dictionary<Control, Action<Control>>();
|
||||
|
||||
private void ModifySystemDNSCheckBox_CheckedChanged(object sender, EventArgs e)
|
||||
private void BindRadioBox(RadioButton control, Action<bool> save, bool value)
|
||||
{
|
||||
ModifiedDNSTextBox.Enabled = ModifySystemDNSCheckBox.Checked;
|
||||
control.Checked = value;
|
||||
_saveActions.Add(control, c => save.Invoke(((RadioButton) c).Checked));
|
||||
}
|
||||
|
||||
private void NoProxyForUdpCheckBox_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (NoProxyForUdpCheckBox.Checked) NoProxyForTcpCheckBox.Checked = false;
|
||||
}
|
||||
|
||||
private void NoProxyForTcpCheckBox_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (NoProxyForTcpCheckBox.Checked) NoProxyForUdpCheckBox.Checked = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
102
Netch/Forms/SubscribeForm.Designer.cs
generated
102
Netch/Forms/SubscribeForm.Designer.cs
generated
@@ -32,7 +32,7 @@
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SubscribeForm));
|
||||
this.AddSubscriptionBox = new System.Windows.Forms.GroupBox();
|
||||
this.UserAgentTextBox = new System.Windows.Forms.TextBox();
|
||||
this.ClearButton = new System.Windows.Forms.Button();
|
||||
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();
|
||||
@@ -40,25 +40,24 @@
|
||||
this.RemarkTextBox = new System.Windows.Forms.TextBox();
|
||||
this.RemarkLabel = new System.Windows.Forms.Label();
|
||||
this.SubscribeLinkListView = 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.CopyLinkToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.UseSelectedServerCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.MainTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.ControlsPanel = new System.Windows.Forms.Panel();
|
||||
this.AddSubscriptionBox.SuspendLayout();
|
||||
this.pContextMenuStrip.SuspendLayout();
|
||||
this.MainTableLayoutPanel.SuspendLayout();
|
||||
this.ControlsPanel.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// AddSubscriptionBox
|
||||
//
|
||||
this.AddSubscriptionBox.Controls.Add(this.UserAgentTextBox);
|
||||
this.AddSubscriptionBox.Controls.Add(this.ClearButton);
|
||||
this.AddSubscriptionBox.Controls.Add(this.UnselectButton);
|
||||
this.AddSubscriptionBox.Controls.Add(this.AddButton);
|
||||
this.AddSubscriptionBox.Controls.Add(this.UserAgentLabel);
|
||||
this.AddSubscriptionBox.Controls.Add(this.LinkTextBox);
|
||||
@@ -66,9 +65,9 @@
|
||||
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, 214);
|
||||
this.AddSubscriptionBox.Location = new System.Drawing.Point(8, 248);
|
||||
this.AddSubscriptionBox.Name = "AddSubscriptionBox";
|
||||
this.AddSubscriptionBox.Size = new System.Drawing.Size(668, 141);
|
||||
this.AddSubscriptionBox.Size = new System.Drawing.Size(668, 135);
|
||||
this.AddSubscriptionBox.TabIndex = 1;
|
||||
this.AddSubscriptionBox.TabStop = false;
|
||||
//
|
||||
@@ -79,15 +78,15 @@
|
||||
this.UserAgentTextBox.Size = new System.Drawing.Size(545, 23);
|
||||
this.UserAgentTextBox.TabIndex = 6;
|
||||
//
|
||||
// ClearButton
|
||||
// UnselectButton
|
||||
//
|
||||
this.ClearButton.Location = new System.Drawing.Point(448, 103);
|
||||
this.ClearButton.Name = "ClearButton";
|
||||
this.ClearButton.Size = new System.Drawing.Size(87, 26);
|
||||
this.ClearButton.TabIndex = 7;
|
||||
this.ClearButton.Text = "Unselect";
|
||||
this.ClearButton.UseVisualStyleBackColor = true;
|
||||
this.ClearButton.Click += new System.EventHandler(this.ClearButton_Click);
|
||||
this.UnselectButton.Location = new System.Drawing.Point(448, 103);
|
||||
this.UnselectButton.Name = "UnselectButton";
|
||||
this.UnselectButton.Size = new System.Drawing.Size(87, 26);
|
||||
this.UnselectButton.TabIndex = 7;
|
||||
this.UnselectButton.Text = "Unselect";
|
||||
this.UnselectButton.UseVisualStyleBackColor = true;
|
||||
this.UnselectButton.Click += new System.EventHandler(this.UnselectButton_Click);
|
||||
//
|
||||
// AddButton
|
||||
//
|
||||
@@ -95,7 +94,7 @@
|
||||
this.AddButton.Name = "AddButton";
|
||||
this.AddButton.Size = new System.Drawing.Size(113, 26);
|
||||
this.AddButton.TabIndex = 7;
|
||||
this.AddButton.Text = "Add / Modify";
|
||||
this.AddButton.Text = "Add";
|
||||
this.AddButton.UseVisualStyleBackColor = true;
|
||||
this.AddButton.Click += new System.EventHandler(this.AddButton_Click);
|
||||
//
|
||||
@@ -143,19 +142,29 @@
|
||||
// SubscribeLinkListView
|
||||
//
|
||||
this.SubscribeLinkListView.AllowColumnReorder = true;
|
||||
this.SubscribeLinkListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {this.RemarkColumnHeader, this.LinkColumnHeader, this.UserAgentHeader});
|
||||
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, 200);
|
||||
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);
|
||||
//
|
||||
// EnableColumnHeader
|
||||
//
|
||||
this.EnableColumnHeader.Text = "Status";
|
||||
//
|
||||
// RemarkColumnHeader
|
||||
//
|
||||
this.RemarkColumnHeader.Text = "Remark";
|
||||
@@ -164,7 +173,7 @@
|
||||
// LinkColumnHeader
|
||||
//
|
||||
this.LinkColumnHeader.Text = "Link";
|
||||
this.LinkColumnHeader.Width = 400;
|
||||
this.LinkColumnHeader.Width = 364;
|
||||
//
|
||||
// UserAgentHeader
|
||||
//
|
||||
@@ -173,62 +182,51 @@
|
||||
//
|
||||
// pContextMenuStrip
|
||||
//
|
||||
this.pContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {this.DeleteToolStripMenuItem, this.CopyLinkToolStripMenuItem});
|
||||
this.pContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[]
|
||||
{
|
||||
this.DeleteToolStripMenuItem, this.deleteServerToolStripMenuItem, this.CopyLinkToolStripMenuItem
|
||||
});
|
||||
this.pContextMenuStrip.Name = "pContextMenuStrip";
|
||||
this.pContextMenuStrip.Size = new System.Drawing.Size(130, 48);
|
||||
this.pContextMenuStrip.Size = new System.Drawing.Size(151, 70);
|
||||
//
|
||||
// DeleteToolStripMenuItem
|
||||
//
|
||||
this.DeleteToolStripMenuItem.Name = "DeleteToolStripMenuItem";
|
||||
this.DeleteToolStripMenuItem.Size = new System.Drawing.Size(129, 22);
|
||||
this.DeleteToolStripMenuItem.Size = new System.Drawing.Size(150, 22);
|
||||
this.DeleteToolStripMenuItem.Text = "Delete";
|
||||
this.DeleteToolStripMenuItem.Click += new System.EventHandler(this.DeleteToolStripMenuItem_Click);
|
||||
//
|
||||
// deleteServerToolStripMenuItem
|
||||
//
|
||||
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);
|
||||
//
|
||||
// CopyLinkToolStripMenuItem
|
||||
//
|
||||
this.CopyLinkToolStripMenuItem.Name = "CopyLinkToolStripMenuItem";
|
||||
this.CopyLinkToolStripMenuItem.Size = new System.Drawing.Size(129, 22);
|
||||
this.CopyLinkToolStripMenuItem.Size = new System.Drawing.Size(150, 22);
|
||||
this.CopyLinkToolStripMenuItem.Text = "CopyLink";
|
||||
this.CopyLinkToolStripMenuItem.Click += new System.EventHandler(this.CopyLinkToolStripMenuItem_Click);
|
||||
//
|
||||
// UseSelectedServerCheckBox
|
||||
//
|
||||
this.UseSelectedServerCheckBox.AutoSize = true;
|
||||
this.UseSelectedServerCheckBox.Location = new System.Drawing.Point(3, 4);
|
||||
this.UseSelectedServerCheckBox.Name = "UseSelectedServerCheckBox";
|
||||
this.UseSelectedServerCheckBox.Size = new System.Drawing.Size(285, 21);
|
||||
this.UseSelectedServerCheckBox.TabIndex = 9;
|
||||
this.UseSelectedServerCheckBox.Text = "Use Selected Server To Update Subscription";
|
||||
this.UseSelectedServerCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// 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.AddSubscriptionBox, 0, 1);
|
||||
this.MainTableLayoutPanel.Controls.Add(this.ControlsPanel, 0, 2);
|
||||
this.MainTableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.MainTableLayoutPanel.Location = new System.Drawing.Point(0, 0);
|
||||
this.MainTableLayoutPanel.Name = "MainTableLayoutPanel";
|
||||
this.MainTableLayoutPanel.Padding = new System.Windows.Forms.Padding(5);
|
||||
this.MainTableLayoutPanel.RowCount = 3;
|
||||
this.MainTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 58.35777F));
|
||||
this.MainTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 41.64223F));
|
||||
this.MainTableLayoutPanel.RowCount = 2;
|
||||
this.MainTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 62.99213F));
|
||||
this.MainTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 37.00787F));
|
||||
this.MainTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 27F));
|
||||
this.MainTableLayoutPanel.Size = new System.Drawing.Size(684, 391);
|
||||
this.MainTableLayoutPanel.TabIndex = 11;
|
||||
//
|
||||
// ControlsPanel
|
||||
//
|
||||
this.ControlsPanel.Controls.Add(this.UseSelectedServerCheckBox);
|
||||
this.ControlsPanel.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.ControlsPanel.Location = new System.Drawing.Point(5, 358);
|
||||
this.ControlsPanel.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.ControlsPanel.Name = "ControlsPanel";
|
||||
this.ControlsPanel.Size = new System.Drawing.Size(674, 28);
|
||||
this.ControlsPanel.TabIndex = 2;
|
||||
//
|
||||
// SubscribeForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
|
||||
@@ -244,19 +242,16 @@
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "Subscribe";
|
||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.SubscribeForm_FormClosing);
|
||||
this.Load += new System.EventHandler(this.SubscribeForm_Load);
|
||||
this.AddSubscriptionBox.ResumeLayout(false);
|
||||
this.AddSubscriptionBox.PerformLayout();
|
||||
this.pContextMenuStrip.ResumeLayout(false);
|
||||
this.MainTableLayoutPanel.ResumeLayout(false);
|
||||
this.ControlsPanel.ResumeLayout(false);
|
||||
this.ControlsPanel.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
}
|
||||
private System.Windows.Forms.ColumnHeader EnableColumnHeader;
|
||||
|
||||
private System.Windows.Forms.Panel ControlsPanel;
|
||||
private System.Windows.Forms.TableLayoutPanel MainTableLayoutPanel;
|
||||
private System.Windows.Forms.Button ClearButton;
|
||||
private System.Windows.Forms.Button UnselectButton;
|
||||
private System.Windows.Forms.GroupBox AddSubscriptionBox;
|
||||
private System.Windows.Forms.Label RemarkLabel;
|
||||
private System.Windows.Forms.TextBox LinkTextBox;
|
||||
@@ -272,8 +267,9 @@
|
||||
private System.Windows.Forms.Label UserAgentLabel;
|
||||
private System.Windows.Forms.TextBox UserAgentTextBox;
|
||||
private System.Windows.Forms.ColumnHeader UserAgentHeader;
|
||||
private System.Windows.Forms.CheckBox UseSelectedServerCheckBox;
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.ToolStripMenuItem deleteServerToolStripMenuItem;
|
||||
}
|
||||
}
|
||||
@@ -8,85 +8,65 @@ namespace Netch.Forms
|
||||
{
|
||||
public partial class SubscribeForm : Form
|
||||
{
|
||||
private int _editingIndex = -1;
|
||||
|
||||
public SubscribeForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void InitSubscribeLink()
|
||||
{
|
||||
SubscribeLinkListView.Items.Clear();
|
||||
|
||||
foreach (var item in Global.Settings.SubscribeLink)
|
||||
{
|
||||
SubscribeLinkListView.Items.Add(new ListViewItem(new[]
|
||||
{
|
||||
item.Remark,
|
||||
item.Link,
|
||||
!string.IsNullOrEmpty(item.UserAgent) ? item.UserAgent : WebUtil.DefaultUserAgent
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
private void SubscribeForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
i18N.TranslateForm(this);
|
||||
i18N.TranslateForm(pContextMenuStrip);
|
||||
|
||||
ResetEditingGroup();
|
||||
|
||||
if (Global.Settings.Server.Count > 0)
|
||||
{
|
||||
UseSelectedServerCheckBox.Enabled = true;
|
||||
UseSelectedServerCheckBox.Checked = Global.Settings.UseProxyToUpdateSubscription;
|
||||
}
|
||||
else
|
||||
{
|
||||
UseSelectedServerCheckBox.Checked = false;
|
||||
UseSelectedServerCheckBox.Enabled = false;
|
||||
}
|
||||
|
||||
InitSubscribeLink();
|
||||
}
|
||||
|
||||
private int SelectedIndex
|
||||
{
|
||||
get
|
||||
{
|
||||
if (SubscribeLinkListView.MultiSelect)
|
||||
throw new Exception();
|
||||
|
||||
return SubscribeLinkListView.SelectedIndices.Count == 0 ? -1 : SubscribeLinkListView.SelectedIndices[0];
|
||||
}
|
||||
}
|
||||
|
||||
#region EventHandler
|
||||
|
||||
private void SubscribeLinkListView_MouseUp(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (e.Button == MouseButtons.Right)
|
||||
if (SelectedIndex != -1)
|
||||
pContextMenuStrip.Show(SubscribeLinkListView, e.Location);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 选中/取消选中
|
||||
/// </summary>
|
||||
private void SubscribeLinkListView_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
SetEditingGroup(SelectedIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 订阅启/禁用
|
||||
/// </summary>
|
||||
private void SubscribeLinkListView_ItemChecked(object sender, ItemCheckedEventArgs e)
|
||||
{
|
||||
var index = e.Item.Index;
|
||||
Global.Settings.SubscribeLink[index].Enable = SubscribeLinkListView.Items[index].Checked;
|
||||
}
|
||||
|
||||
private void SubscribeForm_FormClosing(object sender, FormClosingEventArgs e)
|
||||
{
|
||||
Configuration.Save();
|
||||
Global.Settings.UseProxyToUpdateSubscription = UseSelectedServerCheckBox.Checked;
|
||||
}
|
||||
|
||||
private void CopyLinkToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (SubscribeLinkListView.SelectedItems.Count > 0)
|
||||
{
|
||||
for (var i = SubscribeLinkListView.SelectedItems.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var item = SubscribeLinkListView.SelectedItems[i];
|
||||
var link = Global.Settings.SubscribeLink[item.Index];
|
||||
Clipboard.SetText(link.Link);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
private void DeleteToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (MessageBoxX.Show(i18N.Translate("Delete or not ? Will clean up the corresponding group of items in the server list"), confirm: true) == DialogResult.OK)
|
||||
{
|
||||
if (SubscribeLinkListView.SelectedItems.Count > 0)
|
||||
{
|
||||
for (var i = SubscribeLinkListView.SelectedItems.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var item = SubscribeLinkListView.SelectedItems[i];
|
||||
#region EditBox
|
||||
|
||||
DeleteServersInGroup(item.SubItems[0].Text);
|
||||
Global.Settings.SubscribeLink.RemoveAt(item.Index);
|
||||
SubscribeLinkListView.Items.Remove(item);
|
||||
ResetEditingGroup();
|
||||
}
|
||||
}
|
||||
}
|
||||
private void UnselectButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
ResetEditingGroup();
|
||||
}
|
||||
|
||||
private void AddButton_Click(object sender, EventArgs e)
|
||||
@@ -109,7 +89,7 @@ namespace Netch.Forms
|
||||
return;
|
||||
}
|
||||
|
||||
if (_editingIndex == -1)
|
||||
if (SelectedIndex == -1)
|
||||
{
|
||||
if (Global.Settings.SubscribeLink.Any(link => link.Remark.Equals(RemarkTextBox.Text)))
|
||||
{
|
||||
@@ -119,6 +99,7 @@ namespace Netch.Forms
|
||||
|
||||
Global.Settings.SubscribeLink.Add(new SubscribeLink
|
||||
{
|
||||
Enable = true,
|
||||
Remark = RemarkTextBox.Text,
|
||||
Link = LinkTextBox.Text,
|
||||
UserAgent = UserAgentTextBox.Text
|
||||
@@ -126,114 +107,107 @@ namespace Netch.Forms
|
||||
}
|
||||
else
|
||||
{
|
||||
var target = Global.Settings.SubscribeLink[_editingIndex];
|
||||
if (MessageBox.Show(i18N.Translate("Delete the corresponding group of items in the server list?"), i18N.Translate("Confirm"), MessageBoxButtons.YesNo) == DialogResult.Yes)
|
||||
{
|
||||
DeleteServersInGroup(target.Remark);
|
||||
}
|
||||
else
|
||||
{
|
||||
RenameServersGroup(target.Remark, RemarkTextBox.Text);
|
||||
}
|
||||
var subscribeLink = Global.Settings.SubscribeLink[SelectedIndex];
|
||||
|
||||
target.Link = LinkTextBox.Text;
|
||||
target.Remark = RemarkTextBox.Text;
|
||||
target.UserAgent = UserAgentTextBox.Text;
|
||||
RenameServers(subscribeLink.Remark, RemarkTextBox.Text);
|
||||
subscribeLink.Link = LinkTextBox.Text;
|
||||
subscribeLink.Remark = RemarkTextBox.Text;
|
||||
subscribeLink.UserAgent = UserAgentTextBox.Text;
|
||||
}
|
||||
|
||||
Configuration.Save();
|
||||
Global.Settings.UseProxyToUpdateSubscription = UseSelectedServerCheckBox.Checked;
|
||||
// MessageBoxX.Show(i18N.Translate("Saved"));
|
||||
|
||||
ResetEditingGroup();
|
||||
MessageBoxX.Show(i18N.Translate("Saved"));
|
||||
|
||||
InitSubscribeLink();
|
||||
}
|
||||
|
||||
private static void DeleteServersInGroup(string group)
|
||||
#endregion
|
||||
|
||||
#region ContextMenu
|
||||
|
||||
private void DeleteToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (MessageBoxX.Show(i18N.Translate("Delete or not ? Will clean up the corresponding group of items in the server list"), confirm: true) != DialogResult.OK)
|
||||
return;
|
||||
|
||||
var subscribeLink = Global.Settings.SubscribeLink[SelectedIndex];
|
||||
DeleteServers(subscribeLink.Remark);
|
||||
Global.Settings.SubscribeLink.Remove(subscribeLink);
|
||||
|
||||
InitSubscribeLink();
|
||||
}
|
||||
|
||||
private void deleteServerToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (MessageBoxX.Show(i18N.Translate("Confirm deletion?"), confirm: true) != DialogResult.OK)
|
||||
return;
|
||||
|
||||
DeleteServers(Global.Settings.SubscribeLink[SelectedIndex].Remark);
|
||||
}
|
||||
|
||||
private void CopyLinkToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Clipboard.SetText(Global.Settings.SubscribeLink[SelectedIndex].Link);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper
|
||||
|
||||
private static void DeleteServers(string group)
|
||||
{
|
||||
Global.Settings.Server.RemoveAll(server => server.Group == group);
|
||||
}
|
||||
|
||||
private static void RenameServersGroup(string oldGroup, string newGroup)
|
||||
private static void RenameServers(string oldGroup, string newGroup)
|
||||
{
|
||||
foreach (var server in Global.Settings.Server)
|
||||
{
|
||||
if (server.Group == oldGroup)
|
||||
{
|
||||
server.Group = newGroup;
|
||||
}
|
||||
}
|
||||
foreach (var server in Global.Settings.Server.Where(server => server.Group == oldGroup))
|
||||
server.Group = newGroup;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 订阅列表选中节点
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void SubscribeLinkListView_SelectedIndexChanged(object sender, EventArgs e)
|
||||
private void InitSubscribeLink()
|
||||
{
|
||||
var editingCanOverwrite = true;
|
||||
if (_editingIndex != -1)
|
||||
{
|
||||
var targetItem = SubscribeLinkListView.Items[_editingIndex].SubItems;
|
||||
editingCanOverwrite = RemarkTextBox.Text == targetItem[0].Text &&
|
||||
LinkTextBox.Text == targetItem[1].Text &&
|
||||
UserAgentTextBox.Text == targetItem[2].Text;
|
||||
}
|
||||
SubscribeLinkListView.Items.Clear();
|
||||
|
||||
if (SubscribeLinkListView.SelectedItems.Count == 1)
|
||||
{
|
||||
if (editingCanOverwrite)
|
||||
foreach (var item in Global.Settings.SubscribeLink)
|
||||
SubscribeLinkListView.Items.Add(new ListViewItem(new[]
|
||||
{
|
||||
SelectEditing(SubscribeLinkListView.SelectedItems[0].Index);
|
||||
}
|
||||
}
|
||||
else if (SubscribeLinkListView.SelectedItems.Count > 1)
|
||||
{
|
||||
}
|
||||
else if (editingCanOverwrite)
|
||||
{
|
||||
// 不选
|
||||
// 重置
|
||||
ResetEditingGroup();
|
||||
}
|
||||
}
|
||||
|
||||
private void SubscribeLinkListView_MouseUp(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (e.Button == MouseButtons.Right)
|
||||
{
|
||||
if (SubscribeLinkListView.SelectedItems.Count > 0)
|
||||
"",
|
||||
item.Remark,
|
||||
item.Link,
|
||||
!string.IsNullOrEmpty(item.UserAgent) ? item.UserAgent : WebUtil.DefaultUserAgent
|
||||
})
|
||||
{
|
||||
pContextMenuStrip.Show(SubscribeLinkListView, e.Location);
|
||||
}
|
||||
}
|
||||
}
|
||||
Checked = item.Enable
|
||||
});
|
||||
|
||||
private void SelectEditing(int index)
|
||||
{
|
||||
_editingIndex = index;
|
||||
ListViewItem target;
|
||||
target = SubscribeLinkListView.Items[index];
|
||||
AddSubscriptionBox.Text = target.SubItems[0].Text;
|
||||
RemarkTextBox.Text = target.SubItems[0].Text;
|
||||
LinkTextBox.Text = target.SubItems[1].Text;
|
||||
UserAgentTextBox.Text = target.SubItems[2].Text;
|
||||
ResetEditingGroup();
|
||||
}
|
||||
|
||||
private void ResetEditingGroup()
|
||||
{
|
||||
_editingIndex = -1;
|
||||
AddSubscriptionBox.Text = string.Empty;
|
||||
RemarkTextBox.Text = string.Empty;
|
||||
LinkTextBox.Text = string.Empty;
|
||||
UserAgentTextBox.Text = WebUtil.DefaultUserAgent;
|
||||
}
|
||||
|
||||
private void ClearButton_Click(object sender, EventArgs e)
|
||||
private void SetEditingGroup(int index)
|
||||
{
|
||||
ResetEditingGroup();
|
||||
if (index == -1)
|
||||
{
|
||||
ResetEditingGroup();
|
||||
AddButton.Text = i18N.Translate("Add");
|
||||
return;
|
||||
}
|
||||
|
||||
var item = Global.Settings.SubscribeLink[index];
|
||||
AddSubscriptionBox.Text = item.Remark;
|
||||
RemarkTextBox.Text = item.Remark;
|
||||
LinkTextBox.Text = item.Link;
|
||||
UserAgentTextBox.Text = item.UserAgent;
|
||||
|
||||
AddButton.Text = i18N.Translate("Modify");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
20
Netch/Models/Range.cs
Normal file
20
Netch/Models/Range.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
namespace Netch.Models
|
||||
{
|
||||
public readonly struct Range
|
||||
{
|
||||
public int Start { get; }
|
||||
|
||||
public int End { get; }
|
||||
|
||||
public Range(int start, int end)
|
||||
{
|
||||
Start = start;
|
||||
End = end;
|
||||
}
|
||||
|
||||
public bool InRange(int num)
|
||||
{
|
||||
return Start <= num && num <= End;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +1,23 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Netch.Utils;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Netch.Models
|
||||
{
|
||||
public class Server:ICloneable
|
||||
public class Server : ICloneable
|
||||
{
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// 延迟
|
||||
/// </summary>
|
||||
public string Remark;
|
||||
[JsonIgnore]
|
||||
public int Delay = -1;
|
||||
|
||||
/// <summary>
|
||||
/// 组
|
||||
/// </summary>
|
||||
public string Group = "None";
|
||||
|
||||
/// <summary>
|
||||
/// 代理类型
|
||||
/// </summary>
|
||||
public string Type;
|
||||
|
||||
/// <summary>
|
||||
/// 倍率
|
||||
/// </summary>
|
||||
public double Rate = 1.0;
|
||||
|
||||
/// <summary>
|
||||
/// 地址
|
||||
/// </summary>
|
||||
@@ -37,12 +29,26 @@ namespace Netch.Models
|
||||
public ushort Port;
|
||||
|
||||
/// <summary>
|
||||
/// 延迟
|
||||
/// 倍率
|
||||
/// </summary>
|
||||
public int Delay = -1;
|
||||
public double Rate = 1.0;
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string Remark;
|
||||
|
||||
/// <summary>
|
||||
/// 获取备注
|
||||
/// 代理类型
|
||||
/// </summary>
|
||||
public string Type;
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
return MemberwiseClone();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取备注
|
||||
/// </summary>
|
||||
/// <returns>备注</returns>
|
||||
public override string ToString()
|
||||
@@ -55,13 +61,8 @@ namespace Netch.Models
|
||||
return $"[{ServerHelper.GetUtilByTypeName(Type)?.ShortName ?? "WTF"}][{Group}] {remark}";
|
||||
}
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
return MemberwiseClone();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试延迟
|
||||
/// 测试延迟
|
||||
/// </summary>
|
||||
/// <returns>延迟</returns>
|
||||
public int Test()
|
||||
@@ -70,25 +71,21 @@ namespace Netch.Models
|
||||
{
|
||||
var destination = DNS.Lookup(Hostname);
|
||||
if (destination == null)
|
||||
{
|
||||
return Delay = -2;
|
||||
}
|
||||
|
||||
var list = new Task<int>[3];
|
||||
for (var i = 0; i < 3; i++)
|
||||
{
|
||||
list[i] = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
return await Utils.Utils.TCPingAsync(destination, Port);
|
||||
return Global.Settings.ServerTCPing ? await Utils.Utils.TCPingAsync(destination, Port) : Utils.Utils.ICMPing(destination, Port);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return -4;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Task.WaitAll(list[0], list[1], list[2]);
|
||||
|
||||
|
||||
@@ -1,83 +1,83 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Netch.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// TUN/TAP 适配器配置类
|
||||
/// TUN/TAP 适配器配置类
|
||||
/// </summary>
|
||||
public class TUNTAPConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 地址
|
||||
/// 地址
|
||||
/// </summary>
|
||||
public string Address = "10.0.236.10";
|
||||
|
||||
/// <summary>
|
||||
/// 掩码
|
||||
/// DNS
|
||||
/// </summary>
|
||||
public string Netmask = "255.255.255.0";
|
||||
public List<string> DNS = new();
|
||||
|
||||
/// <summary>
|
||||
/// 网关
|
||||
/// 网关
|
||||
/// </summary>
|
||||
public string Gateway = "10.0.236.1";
|
||||
|
||||
/// <summary>
|
||||
/// DNS
|
||||
/// 掩码
|
||||
/// </summary>
|
||||
public List<string> DNS = new List<string>();
|
||||
public string Netmask = "255.255.255.0";
|
||||
|
||||
/// <summary>
|
||||
/// 使用自定义 DNS 设置
|
||||
/// </summary>
|
||||
public bool UseCustomDNS = false;
|
||||
|
||||
/// <summary>
|
||||
/// 模式 2 下是否代理 DNS
|
||||
/// 模式 2 下是否代理 DNS
|
||||
/// </summary>
|
||||
public bool ProxyDNS = false;
|
||||
|
||||
/// <summary>
|
||||
/// 使用Fake DNS
|
||||
/// 使用自定义 DNS 设置
|
||||
/// </summary>
|
||||
public bool UseCustomDNS = false;
|
||||
|
||||
/// <summary>
|
||||
/// 使用Fake DNS
|
||||
/// </summary>
|
||||
public bool UseFakeDNS = false;
|
||||
}
|
||||
|
||||
public class KcpConfig
|
||||
{
|
||||
public bool congestion = false;
|
||||
|
||||
public int downlinkCapacity = 100;
|
||||
public int mtu = 1350;
|
||||
|
||||
public int readBufferSize = 2;
|
||||
|
||||
public int tti = 50;
|
||||
|
||||
public int uplinkCapacity = 12;
|
||||
|
||||
public int downlinkCapacity = 100;
|
||||
|
||||
public bool congestion = false;
|
||||
|
||||
public int readBufferSize = 2;
|
||||
|
||||
public int writeBufferSize = 2;
|
||||
}
|
||||
|
||||
public class V2rayConfig
|
||||
{
|
||||
public bool XrayCone = false;
|
||||
|
||||
public bool AllowInsecure = true;
|
||||
|
||||
public KcpConfig KcpConfig = new KcpConfig();
|
||||
public KcpConfig KcpConfig = new();
|
||||
|
||||
public bool UseMux = true;
|
||||
public bool UseMux = false;
|
||||
}
|
||||
|
||||
public class AioDNSConfig
|
||||
{
|
||||
public string RulePath = "bin\\china_site_list";
|
||||
|
||||
public string ChinaDNS = "223.5.5.5";
|
||||
|
||||
public string OtherDNS = "1.1.1.1";
|
||||
|
||||
public string Protocol = "tcp";
|
||||
public string RulePath = "bin\\china_site_list";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -86,29 +86,61 @@ namespace Netch.Models
|
||||
public class Setting
|
||||
{
|
||||
/// <summary>
|
||||
/// 服务器选择位置
|
||||
/// 服务器列表
|
||||
/// </summary>
|
||||
public int ServerComboBoxSelectedIndex = 0;
|
||||
public readonly List<Server> Server = new();
|
||||
|
||||
/// <summary>
|
||||
/// 模式选择位置
|
||||
/// ACL规则
|
||||
/// </summary>
|
||||
public int ModeComboBoxSelectedIndex = 0;
|
||||
public string ACL = "https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/banAD.acl";
|
||||
|
||||
public AioDNSConfig AioDNS = new();
|
||||
|
||||
/// <summary>
|
||||
/// 是否关闭窗口时退出
|
||||
/// 是否使用DLL启动Shadowsocks
|
||||
/// </summary>
|
||||
public bool BootShadowsocksFromDLL = true;
|
||||
|
||||
/// <summary>
|
||||
/// 全局绕过 IP 列表
|
||||
/// </summary>
|
||||
public List<string> BypassIPs = new();
|
||||
|
||||
/// <summary>
|
||||
/// 是否检查 Beta 更新
|
||||
/// </summary>
|
||||
public bool CheckBetaUpdate = false;
|
||||
|
||||
/// <summary>
|
||||
/// 是否打开软件时检查更新
|
||||
/// </summary>
|
||||
public bool CheckUpdateWhenOpened = true;
|
||||
|
||||
/// <summary>
|
||||
/// 测试所有服务器心跳/秒
|
||||
/// </summary>
|
||||
public int DetectionTick = 10;
|
||||
|
||||
/// <summary>
|
||||
/// 是否关闭窗口时退出
|
||||
/// </summary>
|
||||
public bool ExitWhenClosed = false;
|
||||
|
||||
/// <summary>
|
||||
/// 是否退出时停止
|
||||
/// HTTP 本地端口
|
||||
/// </summary>
|
||||
public bool StopWhenExited = false;
|
||||
public ushort HTTPLocalPort = 2802;
|
||||
|
||||
/// <summary>
|
||||
/// 是否打开软件时启动加速
|
||||
/// 语言设置
|
||||
/// </summary>
|
||||
public bool StartWhenOpened = false;
|
||||
public string Language = "System";
|
||||
|
||||
/// <summary>
|
||||
/// HTTP 和 Socks5 本地代理地址
|
||||
/// </summary>
|
||||
public string LocalAddress = "127.0.0.1";
|
||||
|
||||
/// <summary>
|
||||
/// 是否启动后自动最小化
|
||||
@@ -116,29 +148,9 @@ namespace Netch.Models
|
||||
public bool MinimizeWhenStarted = false;
|
||||
|
||||
/// <summary>
|
||||
/// 是否开机启动软件
|
||||
/// 模式选择位置
|
||||
/// </summary>
|
||||
public bool RunAtStartup = false;
|
||||
|
||||
/// <summary>
|
||||
/// 是否打开软件时检查更新
|
||||
/// </summary>
|
||||
public bool CheckUpdateWhenOpened = true;
|
||||
|
||||
/// <summary>
|
||||
/// 是否检查 Beta 更新
|
||||
/// </summary>
|
||||
public bool CheckBetaUpdate = false;
|
||||
|
||||
/// <summary>
|
||||
/// 是否打开软件时更新订阅
|
||||
/// </summary>
|
||||
public bool UpdateSubscribeatWhenOpened = false;
|
||||
|
||||
/// <summary>
|
||||
/// 修改系统 DNS
|
||||
/// </summary>
|
||||
public bool ModifySystemDNS = false;
|
||||
public int ModeComboBoxSelectedIndex = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 要修改为的系统 DNS
|
||||
@@ -146,9 +158,54 @@ namespace Netch.Models
|
||||
public string ModifiedDNS = "1.1.1.1,8.8.8.8";
|
||||
|
||||
/// <summary>
|
||||
/// 解析服务器主机名
|
||||
/// 修改系统 DNS
|
||||
/// </summary>
|
||||
public bool ResolveServerHostname = false;
|
||||
public bool ModifySystemDNS = false;
|
||||
|
||||
/// <summary>
|
||||
/// GFWList
|
||||
/// </summary>
|
||||
public string PAC = "https://raw.githubusercontent.com/HMBSbige/Text_Translation/master/ShadowsocksR/ss_white.pac";
|
||||
|
||||
/// <summary>
|
||||
/// PAC端口
|
||||
/// </summary>
|
||||
public int Pac_Port = 2803;
|
||||
|
||||
/// <summary>
|
||||
/// PAC URL
|
||||
/// </summary>
|
||||
public string Pac_Url = "";
|
||||
|
||||
/// <summary>
|
||||
/// 不代理TCP
|
||||
/// </summary>
|
||||
public bool ProcessNoProxyForTcp = false;
|
||||
|
||||
/// <summary>
|
||||
/// 不代理UDP
|
||||
/// </summary>
|
||||
public bool ProcessNoProxyForUdp = false;
|
||||
|
||||
/// <summary>
|
||||
/// 快捷配置数量
|
||||
/// </summary>
|
||||
public int ProfileCount = 4;
|
||||
|
||||
/// <summary>
|
||||
/// 已保存的快捷配置
|
||||
/// </summary>
|
||||
public List<Profile> Profiles = new();
|
||||
|
||||
/// <summary>
|
||||
/// 是否使用RDR内置SS
|
||||
/// </summary>
|
||||
public bool RedirectorSS = false;
|
||||
|
||||
/// <summary>
|
||||
/// Redirector TCP 占用端口
|
||||
/// </summary>
|
||||
public ushort RedirectorTCPPort = 3901;
|
||||
|
||||
/// <summary>
|
||||
/// 网页请求超时 毫秒
|
||||
@@ -156,64 +213,44 @@ namespace Netch.Models
|
||||
public int RequestTimeout = 10000;
|
||||
|
||||
/// <summary>
|
||||
/// HTTP 本地端口
|
||||
/// 解析服务器主机名
|
||||
/// </summary>
|
||||
public ushort HTTPLocalPort = 2802;
|
||||
public bool ResolveServerHostname = false;
|
||||
|
||||
/// <summary>
|
||||
/// Socks5 本地端口
|
||||
/// 是否开机启动软件
|
||||
/// </summary>
|
||||
public bool RunAtStartup = false;
|
||||
|
||||
/// <summary>
|
||||
/// 服务器选择位置
|
||||
/// </summary>
|
||||
public int ServerComboBoxSelectedIndex = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 服务器测试方式 false.ICMPing true.TCPing
|
||||
/// </summary>
|
||||
public bool ServerTCPing = true;
|
||||
|
||||
/// <summary>
|
||||
/// Socks5 本地端口
|
||||
/// </summary>
|
||||
public ushort Socks5LocalPort = 2801;
|
||||
|
||||
/// <summary>
|
||||
/// Redirector TCP 占用端口
|
||||
/// 启动后延迟测试间隔/秒
|
||||
/// </summary>
|
||||
public ushort RedirectorTCPPort = 3901;
|
||||
public int StartedPingInterval = -1;
|
||||
|
||||
/// <summary>
|
||||
/// UDP Socket 占用端口
|
||||
/// 是否打开软件时启动加速
|
||||
/// </summary>
|
||||
public ushort UDPSocketPort = 18291;
|
||||
public bool StartWhenOpened = false;
|
||||
|
||||
/// <summary>
|
||||
/// HTTP 和 Socks5 本地代理地址
|
||||
/// 是否退出时停止
|
||||
/// </summary>
|
||||
public string LocalAddress = "127.0.0.1";
|
||||
|
||||
/// <summary>
|
||||
/// TUNTAP 适配器配置
|
||||
/// </summary>
|
||||
public TUNTAPConfig TUNTAP = new TUNTAPConfig();
|
||||
|
||||
/// <summary>
|
||||
/// 使用代理更新订阅
|
||||
/// </summary>
|
||||
public bool UseProxyToUpdateSubscription = false;
|
||||
|
||||
/// <summary>
|
||||
/// 订阅链接列表
|
||||
/// </summary>
|
||||
public List<SubscribeLink> SubscribeLink = new List<SubscribeLink>();
|
||||
|
||||
/// <summary>
|
||||
/// 服务器列表
|
||||
/// </summary>
|
||||
public readonly List<Server> Server = new List<Server>();
|
||||
|
||||
/// <summary>
|
||||
/// 全局绕过 IP 列表
|
||||
/// </summary>
|
||||
public List<string> BypassIPs = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// 已保存的快捷配置
|
||||
/// </summary>
|
||||
public List<Profile> Profiles = new List<Profile>();
|
||||
|
||||
/// <summary>
|
||||
/// 快捷配置数量
|
||||
/// </summary>
|
||||
public int ProfileCount = 4;
|
||||
public bool StopWhenExited = false;
|
||||
|
||||
/// <summary>
|
||||
/// STUN测试服务器
|
||||
@@ -226,36 +263,34 @@ namespace Netch.Models
|
||||
public int STUN_Server_Port = 3478;
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用启动后延迟测试
|
||||
/// 订阅链接列表
|
||||
/// </summary>
|
||||
public bool StartedTcping = false;
|
||||
public List<SubscribeLink> SubscribeLink = new();
|
||||
|
||||
/// <summary>
|
||||
/// 启动后延迟测试间隔/秒
|
||||
/// TUNTAP 适配器配置
|
||||
/// </summary>
|
||||
public int StartedTcping_Interval = 3;
|
||||
public TUNTAPConfig TUNTAP = new();
|
||||
|
||||
/// <summary>
|
||||
/// ACL规则
|
||||
/// UDP Socket 占用端口
|
||||
/// </summary>
|
||||
public string ACL = "https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/banAD.acl";
|
||||
public ushort UDPSocketPort = 18291;
|
||||
|
||||
/// <summary>
|
||||
/// 是否使用DLL启动Shadowsocks
|
||||
/// 是否打开软件时更新订阅
|
||||
/// </summary>
|
||||
public bool BootShadowsocksFromDLL = true;
|
||||
public bool UpdateServersWhenOpened = false;
|
||||
|
||||
/// <summary>
|
||||
/// 语言设置
|
||||
/// 使用代理更新订阅
|
||||
/// </summary>
|
||||
public string Language = "System";
|
||||
public bool UseProxyToUpdateSubscription = false;
|
||||
|
||||
public V2rayConfig V2RayConfig = new V2rayConfig();
|
||||
|
||||
public AioDNSConfig AioDNS = new AioDNSConfig();
|
||||
|
||||
public bool RedirectorSS = false;
|
||||
|
||||
public bool ProcessNoProxyForUdp = false;
|
||||
public V2rayConfig V2RayConfig = new();
|
||||
public Setting Clone()
|
||||
{
|
||||
return (Setting) MemberwiseClone();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,11 @@
|
||||
{
|
||||
public class SubscribeLink
|
||||
{
|
||||
/// <summary>
|
||||
/// 启用状态
|
||||
/// </summary>
|
||||
public bool Enable = true;
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
@@ -17,4 +22,4 @@
|
||||
/// </summary>
|
||||
public string UserAgent;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ namespace Netch
|
||||
/// <param name="index">适配器索引</param>
|
||||
/// <param name="metric">跃点数</param>
|
||||
/// <returns>是否成功</returns>
|
||||
[DllImport("NetchCore", CallingConvention = CallingConvention.Cdecl, EntryPoint = "CreateRoute")]
|
||||
[DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl, EntryPoint = "CreateRoute")]
|
||||
public static extern bool CreateRoute(string address, int cidr, string gateway, int index, int metric = 0);
|
||||
|
||||
/// <summary>
|
||||
@@ -25,33 +25,9 @@ namespace Netch
|
||||
/// <param name="index">适配器索引</param>
|
||||
/// <param name="metric">跃点数</param>
|
||||
/// <returns>是否成功</returns>
|
||||
[DllImport("NetchCore", CallingConvention = CallingConvention.Cdecl, EntryPoint = "DeleteRoute")]
|
||||
[DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl, EntryPoint = "DeleteRoute")]
|
||||
public static extern bool DeleteRoute(string address, int cidr, string gateway, int index, int metric = 0);
|
||||
|
||||
/// <summary>
|
||||
/// 设置直连
|
||||
/// </summary>
|
||||
/// <returns>是否成功</returns>
|
||||
[DllImport("sysproxy", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern bool SetDIRECT();
|
||||
|
||||
/// <summary>
|
||||
/// 设置全局
|
||||
/// </summary>
|
||||
/// <param name="remote">地址</param>
|
||||
/// <param name="bypass">绕过</param>
|
||||
/// <returns>是否成功</returns>
|
||||
[DllImport("sysproxy", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern bool SetGlobal([MarshalAs(UnmanagedType.LPTStr)] string remote, [MarshalAs(UnmanagedType.LPTStr)] string bypass);
|
||||
|
||||
/// <summary>
|
||||
/// 设置自动代理
|
||||
/// </summary>
|
||||
/// <param name="remote">URL</param>
|
||||
/// <returns>是否成功</returns>
|
||||
[DllImport("sysproxy", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern bool SetURL([MarshalAs(UnmanagedType.LPTStr)] string remote);
|
||||
|
||||
[DllImport("dnsapi", EntryPoint = "DnsFlushResolverCache")]
|
||||
public static extern uint FlushDNSResolverCache();
|
||||
|
||||
|
||||
@@ -13,18 +13,14 @@ namespace Netch
|
||||
public static class Netch
|
||||
{
|
||||
/// <summary>
|
||||
/// 应用程序的主入口点
|
||||
/// 应用程序的主入口点
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
if (args.Contains("-console"))
|
||||
{
|
||||
if (!NativeMethods.AttachConsole(-1))
|
||||
{
|
||||
NativeMethods.AllocConsole();
|
||||
}
|
||||
}
|
||||
|
||||
// 创建互斥体防止多次运行
|
||||
using (var mutex = new Mutex(false, "Global\\Netch"))
|
||||
@@ -36,12 +32,8 @@ namespace Netch
|
||||
// 预创建目录
|
||||
var directories = new[] {"mode", "data", "i18n", "logging"};
|
||||
foreach (var item in directories)
|
||||
{
|
||||
if (!Directory.Exists(item))
|
||||
{
|
||||
Directory.CreateDirectory(item);
|
||||
}
|
||||
}
|
||||
|
||||
// 加载配置
|
||||
Configuration.Load();
|
||||
@@ -49,6 +41,12 @@ 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);
|
||||
}
|
||||
|
||||
// 检查是否已经运行
|
||||
if (!mutex.WaitOne(0, false))
|
||||
{
|
||||
@@ -65,21 +63,14 @@ namespace Netch
|
||||
var directory = new DirectoryInfo("logging");
|
||||
|
||||
foreach (var file in directory.GetFiles())
|
||||
{
|
||||
file.Delete();
|
||||
}
|
||||
|
||||
foreach (var dir in directory.GetDirectories())
|
||||
{
|
||||
dir.Delete(true);
|
||||
}
|
||||
}
|
||||
|
||||
Logging.Info($"版本: {UpdateChecker.Owner}/{UpdateChecker.Repo}@{UpdateChecker.Version}");
|
||||
Task.Run(() =>
|
||||
{
|
||||
Logging.Info($"主程序 SHA256: {Utils.Utils.SHA256CheckSum(Application.ExecutablePath)}");
|
||||
});
|
||||
Task.Run(() => { Logging.Info($"主程序 SHA256: {Utils.Utils.SHA256CheckSum(Application.ExecutablePath)}"); });
|
||||
Task.Run(() =>
|
||||
{
|
||||
Logging.Info("启动单实例");
|
||||
|
||||
@@ -37,23 +37,6 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<COMReference Include="TaskScheduler.dll">
|
||||
<Guid>e34cb9f1-c7f7-424c-be29-027dcc09363a</Guid>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<VersionMinor>0</VersionMinor>
|
||||
<WrapperTool>tlbimp</WrapperTool>
|
||||
<Lcid>0</Lcid>
|
||||
<Isolated>false</Isolated>
|
||||
<EmbedInteropTypes>false</EmbedInteropTypes>
|
||||
</COMReference>
|
||||
<COMReference Include="NetFwTypeLib.dll">
|
||||
<Guid>58fbcf7c-e7a9-467c-80b3-fc65e8fcca08</Guid>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<VersionMinor>0</VersionMinor>
|
||||
<Lcid>0</Lcid>
|
||||
<WrapperTool>tlbimp</WrapperTool>
|
||||
<Isolated>false</Isolated>
|
||||
</COMReference>
|
||||
<COMReference Include="NETCONLib.dll">
|
||||
<Guid>{43E734CA-043D-4A70-9A2C-A8F254063D91}</Guid>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
@@ -66,13 +49,17 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ILMerge" Version="3.0.41" />
|
||||
<PackageReference Include="MaxMind.GeoIP2" Version="3.3.0" />
|
||||
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="2.0.62" />
|
||||
<PackageReference Include="MaxMind.GeoIP2" Version="4.0.1" />
|
||||
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="2.0.65" />
|
||||
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0"/>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="System.Collections.Immutable" Version="5.0.0" />
|
||||
<PackageReference Include="System.Reflection.Metadata" Version="5.0.0" />
|
||||
<PackageReference Include="TaskScheduler" Version="2.9.1" />
|
||||
<PackageReference Include="WindowsAPICodePack-Shell" Version="1.1.1" />
|
||||
<PackageReference Include="WindowsJobAPI" Version="5.0.0" />
|
||||
<PackageReference Include="WindowsFirewallHelper" Version="2.0.4.70-beta2" />
|
||||
<PackageReference Include="WindowsJobAPI" Version="5.0.1" />
|
||||
<PackageReference Include="WindowsProxy" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
if %Configuration%==Release (
|
||||
:: Merge dlls
|
||||
%ILMergeConsolePath% /wildcards /out:%TargetDir%NetchMerged.exe ^
|
||||
%ILMergeConsolePath% /wildcards /out:%TargetDir%Netch.exe ^
|
||||
/lib:"C:\Windows\Microsoft.NET\Framework64\v4.0.30319" ^
|
||||
/targetplatform:v4,"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8" ^
|
||||
%TargetDir%Netch.exe ^
|
||||
%TargetDir%*.dll
|
||||
|
||||
DEL /f %TargetDir%*.dll >NUL 2>&1
|
||||
MOVE /Y %TargetDir%NetchMerged.exe %TargetDir%Netch.exe >NUL
|
||||
|
||||
DEL /f %TargetDir%*.config >NUL 2>&1
|
||||
DEL /f %TargetDir%*.pdb >NUL 2>&1
|
||||
)
|
||||
|
||||
RD /S /Q %TargetDir%bin >NUL 2>&1
|
||||
@@ -18,6 +20,7 @@ XCOPY /s /Y %SolutionDir%binaries %TargetDir%bin\ >NUL
|
||||
XCOPY /s /Y %SolutionDir%translations\i18n %TargetDir%i18n\ >NUL
|
||||
XCOPY /s /Y %SolutionDir%modes\mode %TargetDir%mode\ >NUL
|
||||
|
||||
DEL /f %TargetDir%*.config >NUL 2>&1
|
||||
DEL /f %TargetDir%*.pdb >NUL 2>&1
|
||||
RD /s /Q %TargetDir%x86 >NUL 2>&1
|
||||
RD /s /Q %TargetDir%de %TargetDir%es %TargetDir%fr %TargetDir%it %TargetDir%pl %TargetDir%ru %TargetDir%zh-CN >NUL 2>&1
|
||||
|
||||
exit 0
|
||||
10
Netch/Properties/Resources.Designer.cs
generated
10
Netch/Properties/Resources.Designer.cs
generated
@@ -60,6 +60,16 @@ namespace Netch.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
internal static byte[] abp_js {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("abp_js", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,145 +1,172 @@
|
||||
<?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>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<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>
|
||||
<assembly alias="System.Windows.Forms"
|
||||
name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
|
||||
<data name="defaultTUNTAP" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\defaultTUNTAP;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
</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 name="zh_CN" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\zh-CN;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</data>
|
||||
<data name="speed" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\speed.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b03f5f7f11d50a3a
|
||||
</value>
|
||||
</data>
|
||||
<data name="delete" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\delete.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b03f5f7f11d50a3a
|
||||
</value>
|
||||
</data>
|
||||
<data name="edit" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\edit.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b03f5f7f11d50a3a
|
||||
</value>
|
||||
</data>
|
||||
<data name="Netch" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\Netch.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b03f5f7f11d50a3a
|
||||
</value>
|
||||
</data>
|
||||
<data name="Sponsor" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\Sponsor.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b03f5f7f11d50a3a
|
||||
</value>
|
||||
</data>
|
||||
<data name="CopyLink" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\CopyLink.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b03f5f7f11d50a3a
|
||||
</value>
|
||||
</data>
|
||||
<data name="abp_js" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\abp.js.gz;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b03f5f7f11d50a3a
|
||||
</value>
|
||||
</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.
|
||||
-->
|
||||
<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>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="defaultTUNTAP" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\defaultTUNTAP;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="zh_CN" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\zh-CN;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="speed" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\speed.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="delete" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\delete.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="edit" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\edit.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="Netch" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\Netch.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="Sponsor" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\Sponsor.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="CopyLink" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\CopyLink.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
</root>
|
||||
BIN
Netch/Resources/abp.js.gz
Normal file
BIN
Netch/Resources/abp.js.gz
Normal file
Binary file not shown.
@@ -6,6 +6,7 @@
|
||||
"If this is your first time using this software,\n please check https://netch.org to install supports first,\n or the program may report errors.": "如果你是第一次使用本软件,\n请务必前往 https://netch.org 安装程序所需依赖,\n否则程序将无法正常运行!",
|
||||
"Netch is already running": "Netch 已经在运行中",
|
||||
"Missing File or runtime components": "缺少文件或运行库",
|
||||
"Please extract all files then run the program!": "请先解压所有文件再执行程序!",
|
||||
|
||||
"Start": "启动",
|
||||
"Stop": "停止",
|
||||
@@ -28,7 +29,7 @@
|
||||
"Import Servers From Clipboard": "从剪贴板导入服务器",
|
||||
"Import servers error!": "未找到可导入的链接!",
|
||||
"Add [{0}] Server": "添加 [{0}] 服务器",
|
||||
"Netch is now minimized to the notification bar, double click this icon to restore.": "Netch 已最小化至通知栏,双击此图标恢复窗口。",
|
||||
"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": "寻找新版本失败",
|
||||
@@ -66,10 +67,18 @@
|
||||
"Subscribe": "订阅",
|
||||
"Manage Subscribe Links": "管理订阅链接",
|
||||
"Update Servers From Subscribe Links": "从订阅链接更新服务器",
|
||||
"Update Servers From Subscribe Links With Proxy": "使用代理从订阅链接更新服务器",
|
||||
"No subscription link": "没有任何一条订阅链接",
|
||||
"Updating in the background": "正在后台更新中",
|
||||
"Updating {0}": "正在更新 {0}",
|
||||
"Update {1} server(s) from {0}": "从 {0} 更新 {1} 个服务器",
|
||||
"Update servers error from {0}": "从 {0} 更新服务器失败",
|
||||
"Delete the corresponding group of items in the server list?": "是否删除订阅对应服务器?",
|
||||
"Confirm deletion?": "确认删除?",
|
||||
"DeleteServer": "删除订阅节点",
|
||||
"Status": "状态",
|
||||
"Remark": "备注",
|
||||
"Link": "链接",
|
||||
"Unselect": "取消选择",
|
||||
|
||||
"Options": "选项",
|
||||
"NF Service": "NF 服务",
|
||||
@@ -81,10 +90,17 @@
|
||||
"Modes have been reload": "模式已重载",
|
||||
"Clean DNS Cache": "清理 DNS 缓存",
|
||||
"DNS cache cleanup succeeded": "DNS 缓存清理成功",
|
||||
"Remove Netch Firewall Rules": "移除 Netch 防火墙规则",
|
||||
|
||||
"Update PAC": "更新 PAC",
|
||||
"PAC updated successfully": "PAC 更新成功",
|
||||
"PAC update failed": "PAC 更新失败",
|
||||
|
||||
"Update ACL": "更新 ACL 规则",
|
||||
"Update ACL with proxy": "使用代理更新 ACL 规则",
|
||||
"ACL updated successfully": "ACL 更新成功",
|
||||
"ACL update failed": "ACL 更新失败",
|
||||
|
||||
"Open Directory": "打开目录",
|
||||
|
||||
"About": "关于",
|
||||
@@ -113,9 +129,10 @@
|
||||
"Add": "添加",
|
||||
"Scan": "扫描",
|
||||
"Save": "保存",
|
||||
"Add / Modify": "保存/修改",
|
||||
"Modify": "修改",
|
||||
"Select a folder": "选择一个目录",
|
||||
"Please enter an process name (xxx.exe)": "请输入一个进程名(xxx.exe)",
|
||||
"Rule does not conform to C++ regular expression syntax": "规则不符合 C++ 正则表达式语法",
|
||||
"Scan completed": "扫描完成",
|
||||
"Mode added successfully": "模式添加成功",
|
||||
"Mode updated successfully": "模式修改成功",
|
||||
@@ -149,21 +166,23 @@
|
||||
"Exit when closed": "关闭时退出",
|
||||
"Stop when exited": "退出时停止",
|
||||
"Global Bypass IPs": "全局直连 IP",
|
||||
"Port value illegal. Try again.": "端口值非法。请重试。",
|
||||
"Port value illegal. Try again.": "端口值非法。请重试",
|
||||
"Check update when opened": "打开软件时检查更新",
|
||||
"Check Beta update": "检查 Beta 更新",
|
||||
"Update subscribeat when opened": "自动更新订阅",
|
||||
"Update Servers when opened": "打开软件时更新服务器",
|
||||
"SS DLL": "SS DLL",
|
||||
"Modify System DNS": "修改系统 DNS",
|
||||
"No Proxy for Udp": "不代理Udp流量",
|
||||
"No Proxy for Udp": "不代理 UDP 流量",
|
||||
"No Proxy for Tcp": "不代理 TCP 流量",
|
||||
"ProfileCount": "快捷配置数量",
|
||||
"ProfileCount value illegal. Try again.": "快捷配置数值非法。请重试。",
|
||||
"STUN_ServerPort value illegal. Try again.": "STUN 端口数值非法。请重试。",
|
||||
"Detection interval value illegal. Try again.": "检测间隔值非法。请重试。",
|
||||
"ProfileCount value illegal. Try again.": "快捷配置数值非法。请重试",
|
||||
"STUN_ServerPort value illegal. Try again.": "STUN 端口数值非法。请重试",
|
||||
"Detection interval value illegal. Try again.": "检测间隔值非法。请重试",
|
||||
"TUN/TAP driver is not detected. Is it installed now?": "未检测到 TUN/TAP 驱动,是否现在安装?",
|
||||
"Failed to set the system proxy, it may be caused by the lack of dependent programs. Do you want to jump to Netch's official website to download dependent programs?": "设置系统代理失败,可能是缺少依赖导致,是否跳转 Netch 官网下载依赖程序?",
|
||||
"Delay test after start": "启动后延迟测试",
|
||||
"Enable": "启用",
|
||||
"ServerPingType": "测速方式",
|
||||
"Detection interval(sec)": "检测间隔(秒)",
|
||||
"STUN Server": "STUN 服务器",
|
||||
"STUN Server Port": "STUN 服务器端口",
|
||||
@@ -171,6 +190,7 @@
|
||||
"Language": "语言",
|
||||
"Tap Network Sharing": "Tap 网络共享",
|
||||
"Resolve Server Hostname": "解析服务器主机名",
|
||||
"FullCone Support (Required Server Xray-core v1.3.0+)": "FullCone 支持(需服务端 Xray-core v1.3.0+)",
|
||||
|
||||
"Profile": "配置名",
|
||||
"Profiles": "配置",
|
||||
@@ -181,6 +201,7 @@
|
||||
"Unable to start? Click me to download": "无法启动?点我下载依赖",
|
||||
|
||||
"The {0} port is in use.": "{0} 端口已被占用",
|
||||
"The {0} port is reserved by system.": "{0} 端口是系统保留端口",
|
||||
|
||||
"[Web Proxy] Bypass LAN": "[网页代理] 绕过局域网",
|
||||
"[Non Web Proxy] Bypass LAN": "[不设置代理] 绕过局域网",
|
||||
@@ -188,4 +209,4 @@
|
||||
"[Web Proxy] Bypass LAN and China": "[网页代理] 绕过局域网和中国大陆",
|
||||
"[Non Web Proxy] Bypass LAN and China": "[不设置代理] 绕过局域网和中国大陆",
|
||||
"[TUN/TAP] Bypass LAN and China": "[TUN/TAP] 绕过局域网和中国大陆"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Netch.Servers.Shadowsocks
|
||||
{
|
||||
public class SSController : Guard, IServerController
|
||||
{
|
||||
public override string Name { get; protected set; } = "Shadowsocks";
|
||||
public override string Name { get; } = "Shadowsocks";
|
||||
public override string MainFile { get; protected set; } = "Shadowsocks.exe";
|
||||
|
||||
public ushort? Socks5LocalPort { get; set; }
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System.Text;
|
||||
using Netch.Controllers;
|
||||
using Netch.Models;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Servers.ShadowsocksR
|
||||
{
|
||||
@@ -9,7 +8,7 @@ namespace Netch.Servers.ShadowsocksR
|
||||
{
|
||||
public override string MainFile { get; protected set; } = "ShadowsocksR.exe";
|
||||
|
||||
public override string Name { get; protected set; } = "ShadowsocksR";
|
||||
public override string Name { get; } = "ShadowsocksR";
|
||||
|
||||
public ushort? Socks5LocalPort { get; set; }
|
||||
public string LocalAddress { get; set; }
|
||||
|
||||
@@ -1,40 +1,21 @@
|
||||
using System.IO;
|
||||
using Netch.Controllers;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.VMess.Utils;
|
||||
using Netch.Servers.V2ray;
|
||||
|
||||
namespace Netch.Servers.Socks5
|
||||
{
|
||||
public class S5Controller : Guard, IServerController
|
||||
public class S5Controller : V2RayController
|
||||
{
|
||||
public override string Name { get; protected set; } = "Socks5";
|
||||
public override string MainFile { get; protected set; } = "v2ray.exe";
|
||||
public override string Name { get; } = "Socks5";
|
||||
|
||||
public bool Start(in Server s, in Mode mode)
|
||||
public override bool Start(in Server s, in Mode mode)
|
||||
{
|
||||
var server = (Socks5) s;
|
||||
if (server.Auth())
|
||||
{
|
||||
File.WriteAllText("data\\last.json", V2rayConfigUtils.GenerateClientConfig(s, mode));
|
||||
if (StartInstanceAuto("-config ..\\data\\last.json"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return base.Start(s, mode);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
if (Instance != null)
|
||||
StopInstance();
|
||||
}
|
||||
|
||||
public ushort? Socks5LocalPort { get; set; }
|
||||
|
||||
public string LocalAddress { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ using System.IO;
|
||||
using Netch.Controllers;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.Trojan.Models;
|
||||
using Netch.Utils;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Netch.Servers.Trojan
|
||||
@@ -17,15 +16,14 @@ namespace Netch.Servers.Trojan
|
||||
}
|
||||
|
||||
public override string MainFile { get; protected set; } = "Trojan.exe";
|
||||
public override string Name { get; protected set; } = "Trojan";
|
||||
public override string Name { get; } = "Trojan";
|
||||
public ushort? Socks5LocalPort { get; set; }
|
||||
public string LocalAddress { get; set; }
|
||||
|
||||
|
||||
public bool Start(in Server s, in Mode mode)
|
||||
{
|
||||
var server = (Trojan) s;
|
||||
File.WriteAllText("data\\last.json", JsonConvert.SerializeObject(new TrojanConfig
|
||||
var trojanConfig = new TrojanConfig
|
||||
{
|
||||
local_addr = this.LocalAddress(),
|
||||
local_port = this.Socks5LocalPort(),
|
||||
@@ -35,8 +33,15 @@ namespace Netch.Servers.Trojan
|
||||
{
|
||||
server.Password
|
||||
}
|
||||
}));
|
||||
};
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(server.Host))
|
||||
trojanConfig.ssl.sni = server.Host;
|
||||
|
||||
File.WriteAllText("data\\last.json", JsonConvert.SerializeObject(trojanConfig, Formatting.Indented, new JsonSerializerSettings
|
||||
{
|
||||
NullValueHandling = NullValueHandling.Ignore
|
||||
}));
|
||||
return StartInstanceAuto("-c ..\\data\\last.json");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Netch.Servers.VMess.Models
|
||||
namespace Netch.Servers.V2ray.Models
|
||||
{
|
||||
public class V2rayConfig
|
||||
{
|
||||
@@ -40,7 +40,6 @@ namespace Netch.Servers.VMess.Models
|
||||
|
||||
public List<UsersItem> clients { get; set; }
|
||||
|
||||
|
||||
public string decryption { get; set; }
|
||||
}
|
||||
|
||||
@@ -125,7 +124,6 @@ namespace Netch.Servers.VMess.Models
|
||||
public int level { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class Mux
|
||||
{
|
||||
public bool enabled { get; set; }
|
||||
@@ -218,7 +216,6 @@ namespace Netch.Servers.VMess.Models
|
||||
public TCPRequestHeaders headers;
|
||||
}
|
||||
|
||||
|
||||
public class TCPRequestHeaders
|
||||
{
|
||||
public string Host;
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Netch.Servers.VMess.Models
|
||||
namespace Netch.Servers.V2ray.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// 使用 v2rayN 定义的 VMess 链接格式
|
||||
@@ -1,11 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.VMess.Models;
|
||||
using Netch.Servers.V2ray.Models;
|
||||
using Newtonsoft.Json;
|
||||
using V2rayConfig = Netch.Servers.VMess.Models.V2rayConfig;
|
||||
using V2rayConfig = Netch.Servers.V2ray.Models.V2rayConfig;
|
||||
|
||||
namespace Netch.Servers.VMess.Utils
|
||||
namespace Netch.Servers.V2ray.Utils
|
||||
{
|
||||
public static class V2rayConfigUtils
|
||||
{
|
||||
@@ -214,7 +214,7 @@ namespace Netch.Servers.VMess.Utils
|
||||
outbound.settings.servers = null;
|
||||
break;
|
||||
}
|
||||
case VMess vmess:
|
||||
case VMess.VMess vmess:
|
||||
{
|
||||
var vnextItem = new VnextItem
|
||||
{
|
||||
@@ -261,7 +261,7 @@ namespace Netch.Servers.VMess.Utils
|
||||
}
|
||||
}
|
||||
|
||||
private static void boundStreamSettings(VMess server, ref StreamSettings streamSettings)
|
||||
private static void boundStreamSettings(VMess.VMess server, ref StreamSettings streamSettings)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -1,25 +1,23 @@
|
||||
using System.IO;
|
||||
using System.IO;
|
||||
using Netch.Controllers;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.VMess.Utils;
|
||||
using Netch.Servers.V2ray.Utils;
|
||||
|
||||
namespace Netch.Servers.VMess
|
||||
namespace Netch.Servers.V2ray
|
||||
{
|
||||
public class VMessController : Guard, IServerController
|
||||
public class V2RayController : Guard, IServerController
|
||||
{
|
||||
public VMessController()
|
||||
public V2RayController()
|
||||
{
|
||||
StartedKeywords.Add("started");
|
||||
StoppedKeywords.AddRange(new[] {"config file not readable", "failed to"});
|
||||
}
|
||||
public override string MainFile { get; protected set; } = "xray.exe";
|
||||
|
||||
public override string Name { get; protected set; } = "VMess";
|
||||
public override string MainFile { get; protected set; } = "v2ray.exe";
|
||||
public override string Name { get; } = "Xray";
|
||||
public ushort? Socks5LocalPort { get; set; }
|
||||
public string LocalAddress { get; set; }
|
||||
|
||||
|
||||
public bool Start(in Server s,in Mode mode)
|
||||
public virtual bool Start(in Server s, in Mode mode)
|
||||
{
|
||||
File.WriteAllText("data\\last.json", V2rayConfigUtils.GenerateClientConfig(s, mode));
|
||||
return StartInstanceAuto("-config ..\\data\\last.json");
|
||||
@@ -29,5 +27,12 @@ namespace Netch.Servers.VMess
|
||||
{
|
||||
StopInstance();
|
||||
}
|
||||
|
||||
protected override void InitInstance(string argument)
|
||||
{
|
||||
base.InitInstance(argument);
|
||||
if (!Global.Settings.V2RayConfig.XrayCone)
|
||||
Instance.StartInfo.Environment["XRAY_CONE_DISABLED"] = "true";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.VMess;
|
||||
|
||||
namespace Netch.Servers.VLESS
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
using System.IO;
|
||||
using Netch.Controllers;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.VMess.Utils;
|
||||
|
||||
namespace Netch.Servers.VLESS
|
||||
{
|
||||
public class VLESSController : Guard, IServerController
|
||||
{
|
||||
public override string Name { get; protected set; } = "VLESS";
|
||||
public override string MainFile { get; protected set; } = "v2ray.exe";
|
||||
|
||||
public ushort? Socks5LocalPort { get; set; }
|
||||
|
||||
public string LocalAddress { get; set; }
|
||||
|
||||
public bool Start(in Server s,in Mode mode)
|
||||
{
|
||||
File.WriteAllText("data\\last.json", V2rayConfigUtils.GenerateClientConfig(s, mode));
|
||||
return StartInstanceAuto("-config ..\\data\\last.json");
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
StopInstance();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using Netch.Controllers;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.V2ray;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Netch.Servers.VLESS
|
||||
@@ -36,7 +37,7 @@ namespace Netch.Servers.VLESS
|
||||
|
||||
public IServerController GetController()
|
||||
{
|
||||
return new VLESSController();
|
||||
return new V2RayController();
|
||||
}
|
||||
|
||||
public IEnumerable<Server> ParseUri(string text)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Netch.Models;
|
||||
|
||||
@@ -70,7 +69,7 @@ namespace Netch.Servers.VMess
|
||||
/// <summary>
|
||||
/// Mux 多路复用
|
||||
/// </summary>
|
||||
public bool? UseMux { get; set; } = true;
|
||||
public bool? UseMux { get; set; } = false;
|
||||
}
|
||||
|
||||
public class VMessGlobal
|
||||
|
||||
@@ -2,8 +2,9 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using Netch.Controllers;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.V2ray;
|
||||
using Netch.Servers.V2ray.Models;
|
||||
using Netch.Servers.VMess.Form;
|
||||
using Netch.Servers.VMess.Models;
|
||||
using Netch.Utils;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
@@ -56,7 +57,7 @@ namespace Netch.Servers.VMess
|
||||
|
||||
public IServerController GetController()
|
||||
{
|
||||
return new VMessController();
|
||||
return new V2RayController();
|
||||
}
|
||||
|
||||
public IEnumerable<Server> ParseUri(string text)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
@@ -8,7 +7,6 @@ using Microsoft.Diagnostics.Tracing.Session;
|
||||
using Netch.Controllers;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.Shadowsocks;
|
||||
using Netch.Servers.Socks5;
|
||||
|
||||
namespace Netch.Utils
|
||||
{
|
||||
@@ -54,7 +52,7 @@ namespace Netch.Utils
|
||||
/// <summary>
|
||||
/// 根据程序名统计流量
|
||||
/// </summary>
|
||||
public static void NetTraffic(in Server server, in Mode mode)
|
||||
public static void NetTraffic()
|
||||
{
|
||||
if (!Global.Flags.IsWindows10Upper)
|
||||
return;
|
||||
@@ -100,6 +98,13 @@ namespace Netch.Utils
|
||||
Logging.Info("流量统计进程:" + string.Join(",",
|
||||
instances.Select(instance => $"({instance.Id})" + instance.ProcessName).ToArray()));
|
||||
|
||||
received = 0;
|
||||
|
||||
if (!instances.Any())
|
||||
return;
|
||||
|
||||
Global.MainForm.BandwidthState(true);
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
tSession = new TraceEventSession("KernelAndClrEventsSession");
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using NetFwTypeLib;
|
||||
using WindowsFirewallHelper;
|
||||
|
||||
namespace Netch.Utils
|
||||
{
|
||||
public static class Firewall
|
||||
{
|
||||
private const string Netch = "Netch";
|
||||
private static readonly string[] ProgramPath =
|
||||
{
|
||||
"bin/NTT.exe",
|
||||
@@ -15,53 +16,30 @@ namespace Netch.Utils
|
||||
"bin/ShadowsocksR.exe",
|
||||
"bin/Trojan.exe",
|
||||
"bin/tun2socks.exe",
|
||||
"bin/v2ray.exe",
|
||||
"bin/xray.exe",
|
||||
"Netch.exe"
|
||||
};
|
||||
|
||||
private const string Netch = "Netch";
|
||||
private const string NetchAutoRule = "NetchAutoRule";
|
||||
|
||||
/// <summary>
|
||||
/// 添加防火墙规则 (非 Netch 自带程序)
|
||||
/// </summary>
|
||||
/// <param name="exeFullPath"></param>
|
||||
public static void AddFwRule(string exeFullPath)
|
||||
{
|
||||
AddFwRule(NetchAutoRule, exeFullPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除防火墙规则 (非 Netch 自带程序)
|
||||
/// </summary>
|
||||
public static void RemoveFwRules()
|
||||
{
|
||||
try
|
||||
{
|
||||
RemoveFwRules(NetchAutoRule);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Warning("添加防火墙规则错误\n" + e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Netch 自带程序添加防火墙
|
||||
/// Netch 自带程序添加防火墙
|
||||
/// </summary>
|
||||
public static void AddNetchFwRules()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (GetFwRulePath(Netch).StartsWith(Global.NetchDir) && GetFwRulesNumber(Netch) >= ProgramPath.Length) return;
|
||||
RemoveNetchFwRules();
|
||||
var rule = FirewallManager.Instance.Rules.FirstOrDefault(r => r.Name == Netch);
|
||||
if (rule != null)
|
||||
{
|
||||
if (rule.Name.StartsWith(Global.NetchDir))
|
||||
return;
|
||||
RemoveNetchFwRules();
|
||||
}
|
||||
|
||||
foreach (var p in ProgramPath)
|
||||
{
|
||||
var path = Path.GetFullPath(p);
|
||||
if (File.Exists(path))
|
||||
{
|
||||
AddFwRule("Netch", path);
|
||||
}
|
||||
AddFwRule(Netch, path);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -71,72 +49,29 @@ namespace Netch.Utils
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除防火墙规则 (Netch 自带程序)
|
||||
/// 清除防火墙规则 (Netch 自带程序)
|
||||
/// </summary>
|
||||
private static void RemoveNetchFwRules()
|
||||
public static void RemoveNetchFwRules()
|
||||
{
|
||||
try
|
||||
{
|
||||
RemoveFwRules(Netch);
|
||||
foreach (var rule in FirewallManager.Instance.Rules.Where(r => r.Name == Netch))
|
||||
FirewallManager.Instance.Rules.Remove(rule);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Warning("清除防火墙规则错误\n" + e);
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
#region 封装
|
||||
|
||||
private static readonly INetFwPolicy2 FwPolicy = (INetFwPolicy2) Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwPolicy2"));
|
||||
|
||||
private static void AddFwRule(string ruleName, string exeFullPath)
|
||||
{
|
||||
var rule = NewFwRule();
|
||||
var rule = FirewallManager.Instance.CreateApplicationRule(ruleName, FirewallAction.Allow, exeFullPath);
|
||||
rule.Direction = FirewallDirection.Inbound;
|
||||
|
||||
rule.Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW;
|
||||
// ApplicationName 大小不敏感
|
||||
rule.ApplicationName = exeFullPath;
|
||||
// rule.Description = "";
|
||||
rule.Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN;
|
||||
rule.Enabled = true;
|
||||
rule.InterfaceTypes = "All";
|
||||
rule.Name = ruleName;
|
||||
|
||||
FwPolicy.Rules.Add(rule);
|
||||
}
|
||||
|
||||
private static void RemoveFwRules(string ruleName)
|
||||
{
|
||||
var c = GetFwRulesNumber(ruleName);
|
||||
foreach (var _ in new bool[c])
|
||||
{
|
||||
FwPolicy.Rules.Remove(ruleName);
|
||||
}
|
||||
}
|
||||
|
||||
private static INetFwRule NewFwRule()
|
||||
{
|
||||
return (INetFwRule) Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FWRule"));
|
||||
}
|
||||
|
||||
|
||||
private static string GetFwRulePath(string ruleName)
|
||||
{
|
||||
try
|
||||
{
|
||||
var rule = (INetFwRule2) FwPolicy.Rules.Item(ruleName);
|
||||
return rule.ApplicationName;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private static int GetFwRulesNumber(string ruleName)
|
||||
{
|
||||
return FwPolicy.Rules.Cast<INetFwRule2>().Count(rule => rule.Name == ruleName);
|
||||
FirewallManager.Instance.Rules.Add(rule);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
99
Netch/Utils/HttpProxyHandler/HttpWebServer.cs
Normal file
99
Netch/Utils/HttpProxyHandler/HttpWebServer.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
namespace Netch.Utils.HttpProxyHandler
|
||||
{
|
||||
public class HttpWebServer
|
||||
{
|
||||
private HttpListener _listener;
|
||||
private Func<HttpListenerRequest, string> _responderMethod;
|
||||
|
||||
public HttpWebServer(string[] prefixes, Func<HttpListenerRequest, string> method)
|
||||
{
|
||||
try
|
||||
{
|
||||
_listener = new HttpListener();
|
||||
|
||||
if (!HttpListener.IsSupported)
|
||||
throw new NotSupportedException(
|
||||
"Needs Windows XP SP2, Server 2003 or later.");
|
||||
|
||||
// URI prefixes are required, for example
|
||||
// "http://localhost:8080/index/".
|
||||
if (prefixes == null || prefixes.Length == 0)
|
||||
throw new ArgumentException("prefixes");
|
||||
|
||||
// A responder method is required
|
||||
if (method == null)
|
||||
throw new ArgumentException("method");
|
||||
|
||||
foreach (string s in prefixes)
|
||||
_listener.Prefixes.Add(s);
|
||||
|
||||
_responderMethod = method;
|
||||
_listener.Start();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Error("HttpWebServer():" + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public HttpWebServer(Func<HttpListenerRequest, string> method, params string[] prefixes)
|
||||
: this(prefixes, method)
|
||||
{
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem((o) =>
|
||||
{
|
||||
Logging.Info("Webserver running...");
|
||||
try
|
||||
{
|
||||
while (_listener.IsListening)
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem((c) =>
|
||||
{
|
||||
var ctx = c as HttpListenerContext;
|
||||
try
|
||||
{
|
||||
string rstr = _responderMethod(ctx.Request);
|
||||
byte[] buf = Encoding.UTF8.GetBytes(rstr);
|
||||
ctx.Response.StatusCode = 200;
|
||||
ctx.Response.ContentType = "application/x-ns-proxy-autoconfig";
|
||||
ctx.Response.ContentLength64 = buf.Length;
|
||||
ctx.Response.OutputStream.Write(buf, 0, buf.Length);
|
||||
}
|
||||
catch
|
||||
{
|
||||
} // suppress any exceptions
|
||||
finally
|
||||
{
|
||||
// always close the stream
|
||||
ctx.Response.OutputStream.Close();
|
||||
}
|
||||
}, _listener.GetContext());
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//Logging.Error(ex.Message, ex);
|
||||
Logging.Error(ex.Message);
|
||||
} // suppress any exceptions
|
||||
});
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
if (_listener != null)
|
||||
{
|
||||
_listener.Stop();
|
||||
_listener.Close();
|
||||
_listener = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
124
Netch/Utils/HttpProxyHandler/PACServerHandle.cs
Normal file
124
Netch/Utils/HttpProxyHandler/PACServerHandle.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using WindowsProxy;
|
||||
|
||||
namespace Netch.Utils.HttpProxyHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// 提供PAC功能支持
|
||||
/// </summary>
|
||||
class PACServerHandle
|
||||
{
|
||||
private static Hashtable httpWebServer = new Hashtable();
|
||||
private static Hashtable pacList = new Hashtable();
|
||||
|
||||
public static void InitPACServer(string address)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!pacList.ContainsKey(address))
|
||||
{
|
||||
pacList.Add(address, GetPacList(address));
|
||||
}
|
||||
|
||||
string prefixes = string.Format("http://{0}:{1}/pac/", address, Global.Settings.Pac_Port);
|
||||
|
||||
HttpWebServer ws = new HttpWebServer(SendResponse, prefixes);
|
||||
ws.Run();
|
||||
|
||||
if (!httpWebServer.ContainsKey(address) && ws != null)
|
||||
{
|
||||
httpWebServer.Add(address, ws);
|
||||
}
|
||||
Global.Settings.Pac_Url = GetPacUrl();
|
||||
|
||||
using var service = new ProxyService
|
||||
{
|
||||
AutoConfigUrl = Global.Settings.Pac_Url
|
||||
};
|
||||
service.Pac();
|
||||
|
||||
Logging.Info(service.Set(service.Query()) + "");
|
||||
Logging.Info($"Webserver InitServer OK: {Global.Settings.Pac_Url}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Error("Webserver InitServer " + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public static string SendResponse(HttpListenerRequest request)
|
||||
{
|
||||
try
|
||||
{
|
||||
string[] arrAddress = request.UserHostAddress.Split(':');
|
||||
string address = "127.0.0.1";
|
||||
if (arrAddress.Length > 0)
|
||||
{
|
||||
address = arrAddress[0];
|
||||
}
|
||||
return pacList[address].ToString();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Error("Webserver SendResponse " + ex.Message);
|
||||
return ex.Message;
|
||||
}
|
||||
}
|
||||
|
||||
public static void Stop()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (httpWebServer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (var key in httpWebServer.Keys)
|
||||
{
|
||||
Logging.Info("Webserver Stop " + key.ToString());
|
||||
((HttpWebServer)httpWebServer[key]).Stop();
|
||||
}
|
||||
httpWebServer.Clear();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Error("Webserver Stop " + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetPacList(string address)
|
||||
{
|
||||
try
|
||||
{
|
||||
List<string> lstProxy = new List<string>();
|
||||
lstProxy.Add(string.Format("PROXY {0}:{1};", address, Global.Settings.HTTPLocalPort));
|
||||
|
||||
var proxy = string.Join("", lstProxy.ToArray());
|
||||
string strPacfile = Path.Combine(Global.NetchDir, $"bin\\pac.txt");
|
||||
|
||||
var pac = File.ReadAllText(strPacfile, Encoding.UTF8).Replace("__PROXY__", proxy);
|
||||
return pac;
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
return "No pac content";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取PAC地址
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static string GetPacUrl()
|
||||
{
|
||||
string pacUrl = string.Format("http://127.0.0.1:{0}/pac/?t={1}", Global.Settings.Pac_Port,
|
||||
DateTime.Now.ToString("yyyyMMddHHmmssfff"));
|
||||
|
||||
return pacUrl;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Management;
|
||||
using Netch.Controllers;
|
||||
using Netch.Models.WinFW;
|
||||
|
||||
@@ -16,12 +16,21 @@ namespace Netch.Utils
|
||||
|
||||
public static readonly string ModeDirectory = Path.Combine(Global.NetchDir, $"{MODE_DIR}\\");
|
||||
|
||||
public static string GetRelativePath(string fullName) => fullName.Substring(ModeDirectory.Length);
|
||||
public static string GetFullPath(string relativeName) => Path.Combine(ModeDirectory, relativeName);
|
||||
public static string GetFullPath(Mode mode) => Path.Combine(ModeDirectory, mode.RelativePath);
|
||||
public static string GetRelativePath(string fullName)
|
||||
{
|
||||
return fullName.Substring(ModeDirectory.Length);
|
||||
}
|
||||
public static string GetFullPath(string relativeName)
|
||||
{
|
||||
return Path.Combine(ModeDirectory, relativeName);
|
||||
}
|
||||
public static string GetFullPath(Mode mode)
|
||||
{
|
||||
return Path.Combine(ModeDirectory, mode.RelativePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从模式文件夹读取模式并为 <see cref="Forms.MainForm.ModeComboBox"/> 绑定数据
|
||||
/// 从模式文件夹读取模式并为 <see cref="Forms.MainForm.ModeComboBox" /> 绑定数据
|
||||
/// </summary>
|
||||
public static void Load()
|
||||
{
|
||||
@@ -99,16 +108,12 @@ namespace Netch.Utils
|
||||
public static void WriteFile(Mode mode)
|
||||
{
|
||||
if (!Directory.Exists(ModeDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(ModeDirectory);
|
||||
}
|
||||
|
||||
var fullName = GetFullPath(mode.RelativePath ?? mode.FileName + ".txt");
|
||||
|
||||
if (mode.RelativePath == null && File.Exists(fullName))
|
||||
{
|
||||
throw new Exception("新建模式的文件名已存在,请贡献者检查代码");
|
||||
}
|
||||
|
||||
// 写入到模式文件里
|
||||
File.WriteAllText(fullName, mode.ToFileString());
|
||||
@@ -131,9 +136,7 @@ namespace Netch.Utils
|
||||
{
|
||||
var fullName = GetFullPath(mode);
|
||||
if (File.Exists(fullName))
|
||||
{
|
||||
File.Delete(fullName);
|
||||
}
|
||||
|
||||
Global.Modes.Remove(mode);
|
||||
Global.MainForm.InitMode();
|
||||
@@ -166,6 +169,7 @@ namespace Netch.Utils
|
||||
modeController = new NFController();
|
||||
port = Global.Settings.RedirectorTCPPort;
|
||||
portName = "Redirector TCP";
|
||||
portType = PortType.TCP;
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
@@ -176,6 +180,7 @@ namespace Netch.Utils
|
||||
modeController = new HTTPController();
|
||||
port = Global.Settings.HTTPLocalPort;
|
||||
portName = "HTTP";
|
||||
portType = PortType.TCP;
|
||||
MainForm.StatusPortInfoText.HttpPort = (ushort) port;
|
||||
break;
|
||||
case 4:
|
||||
|
||||
@@ -24,11 +24,21 @@ namespace Netch.Utils
|
||||
{
|
||||
try
|
||||
{
|
||||
if (PortHelper.PortInUse(Global.Settings.UDPSocketPort))
|
||||
{
|
||||
Global.Settings.UDPSocketPort = PortHelper.GetAvailablePort();
|
||||
Configuration.Save();
|
||||
}
|
||||
const int tryLimit = 3;
|
||||
var i = tryLimit;
|
||||
while (i > 0)
|
||||
try
|
||||
{
|
||||
PortHelper.CheckPort(Global.Settings.UDPSocketPort, PortType.UDP);
|
||||
if (i != tryLimit)
|
||||
Configuration.Save();
|
||||
break;
|
||||
}
|
||||
catch
|
||||
{
|
||||
Global.Settings.UDPSocketPort = PortHelper.GetAvailablePort(PortType.UDP);
|
||||
i--;
|
||||
}
|
||||
|
||||
var data = new byte[1024];
|
||||
var newsock = new UdpClient(new IPEndPoint(IPAddress.Loopback, Global.Settings.UDPSocketPort));
|
||||
@@ -38,9 +48,7 @@ namespace Netch.Utils
|
||||
var result = await newsock.ReceiveAsync();
|
||||
data = result.Buffer;
|
||||
if (Enum.TryParse<Commands>(Encoding.ASCII.GetString(data, 0, data.Length), out var command))
|
||||
{
|
||||
OnCalled(command);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -53,14 +61,12 @@ namespace Netch.Utils
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var udpClient = new UdpClient(Global.Settings.UDPSocketPort))
|
||||
{
|
||||
udpClient.Connect(IPAddress.Loopback, Global.Settings.UDPSocketPort);
|
||||
var sendBytes = Encoding.ASCII.GetBytes(command.ToString());
|
||||
await udpClient.SendAsync(sendBytes, sendBytes.Length);
|
||||
using var udpClient = new UdpClient(Global.Settings.UDPSocketPort);
|
||||
udpClient.Connect(IPAddress.Loopback, Global.Settings.UDPSocketPort);
|
||||
var sendBytes = Encoding.ASCII.GetBytes(command.ToString());
|
||||
await udpClient.SendAsync(sendBytes, sendBytes.Length);
|
||||
|
||||
udpClient.Close();
|
||||
}
|
||||
udpClient.Close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
@@ -3,20 +3,22 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Net.NetworkInformation;
|
||||
using Netch.Models;
|
||||
|
||||
namespace Netch.Utils
|
||||
{
|
||||
public static class PortHelper
|
||||
{
|
||||
private static readonly List<ushort[]> TCPExcludedRanges = new List<ushort[]>();
|
||||
private static readonly List<ushort[]> UDPExcludedRanges = new List<ushort[]>();
|
||||
private static readonly List<Range> TCPReservedRanges = new();
|
||||
private static readonly List<Range> UDPReservedRanges = new();
|
||||
private static readonly IPGlobalProperties NetInfo = IPGlobalProperties.GetIPGlobalProperties();
|
||||
|
||||
static PortHelper()
|
||||
{
|
||||
try
|
||||
{
|
||||
GetExcludedPortRange(PortType.TCP, ref TCPExcludedRanges);
|
||||
GetExcludedPortRange(PortType.UDP, ref UDPExcludedRanges);
|
||||
GetReservedPortRange(PortType.TCP, ref TCPReservedRanges);
|
||||
GetReservedPortRange(PortType.UDP, ref UDPReservedRanges);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -24,7 +26,7 @@ namespace Netch.Utils
|
||||
}
|
||||
}
|
||||
|
||||
private static void GetExcludedPortRange(PortType portType, ref List<ushort[]> targetList)
|
||||
private static void GetReservedPortRange(PortType portType, ref List<Range> targetList)
|
||||
{
|
||||
var lines = new List<string>();
|
||||
var process = new Process
|
||||
@@ -48,47 +50,20 @@ namespace Netch.Utils
|
||||
|
||||
var splitLine = false;
|
||||
foreach (var line in lines)
|
||||
{
|
||||
if (!splitLine)
|
||||
{
|
||||
if (line.StartsWith("-"))
|
||||
{
|
||||
splitLine = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (line == string.Empty)
|
||||
break;
|
||||
|
||||
var value = line.Trim().Split(' ').Where(s => s != string.Empty);
|
||||
var value = line.Trim().Split(' ').Where(s => s != string.Empty).ToArray();
|
||||
|
||||
ushort port = 0;
|
||||
var _ = (from s1 in value
|
||||
where ushort.TryParse(s1, out port)
|
||||
select port).ToArray();
|
||||
|
||||
targetList.Add(_);
|
||||
targetList.Add(new Range(ushort.Parse(value[0]), ushort.Parse(value[1])));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查端口是否是保留端口
|
||||
/// </summary>
|
||||
/// <param name="port">端口</param>
|
||||
/// <param name="type">端口类型</param>
|
||||
/// <returns>是否是保留端口</returns>
|
||||
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
||||
private static bool IsPortExcluded(ushort port, PortType type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
PortType.TCP => TCPExcludedRanges.Any(range => range[0] <= port && port <= range[1]),
|
||||
PortType.UDP => UDPExcludedRanges.Any(range => range[0] <= port && port <= range[1]),
|
||||
PortType.Both => IsPortExcluded(port, PortType.TCP) || IsPortExcluded(port, PortType.UDP),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -97,39 +72,83 @@ namespace Netch.Utils
|
||||
/// <param name="port">端口</param>
|
||||
/// <param name="type">检查端口类型</param>
|
||||
/// <returns>是否被占用</returns>
|
||||
public static bool PortInUse(ushort port, PortType type = PortType.Both)
|
||||
public static void CheckPort(ushort port, PortType type = PortType.Both)
|
||||
{
|
||||
var netInfo = IPGlobalProperties.GetIPGlobalProperties();
|
||||
var isTcpUsed = type != PortType.UDP &&
|
||||
(IsPortExcluded(port, PortType.TCP) ||
|
||||
netInfo.GetActiveTcpListeners().Any(ipEndPoint => ipEndPoint.Port == port));
|
||||
var isUdpUsed = type != PortType.TCP &&
|
||||
(IsPortExcluded(port, PortType.UDP) ||
|
||||
netInfo.GetActiveUdpListeners().Any(ipEndPoint => ipEndPoint.Port == port));
|
||||
var isPortExcluded = !UsingPorts.Contains(port);
|
||||
|
||||
return isPortExcluded && (isTcpUsed || isUdpUsed);
|
||||
switch (type)
|
||||
{
|
||||
case PortType.Both:
|
||||
CheckPort(port, PortType.TCP);
|
||||
CheckPort(port, PortType.UDP);
|
||||
break;
|
||||
default:
|
||||
CheckPortInUse(port, type);
|
||||
CheckPortReserved(port, type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
private static void CheckPortInUse(ushort port, PortType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case PortType.Both:
|
||||
CheckPortInUse(port, PortType.TCP);
|
||||
CheckPortInUse(port, PortType.UDP);
|
||||
break;
|
||||
case PortType.TCP:
|
||||
if (NetInfo.GetActiveTcpListeners().Any(ipEndPoint => ipEndPoint.Port == port))
|
||||
throw new PortInUseException();
|
||||
break;
|
||||
case PortType.UDP:
|
||||
if (NetInfo.GetActiveUdpListeners().Any(ipEndPoint => ipEndPoint.Port == port))
|
||||
throw new PortInUseException();
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(type), type, null);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 检查端口是否是保留端口
|
||||
/// </summary>
|
||||
private static void CheckPortReserved(ushort port, PortType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case PortType.Both:
|
||||
CheckPortReserved(port, PortType.TCP);
|
||||
CheckPortReserved(port, PortType.UDP);
|
||||
return;
|
||||
case PortType.TCP:
|
||||
if (TCPReservedRanges.Any(range => range.InRange(port)))
|
||||
throw new PortReservedException();
|
||||
break;
|
||||
case PortType.UDP:
|
||||
if (UDPReservedRanges.Any(range => range.InRange(port)))
|
||||
throw new PortReservedException();
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(type), type, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static ushort GetAvailablePort()
|
||||
public static ushort GetAvailablePort(PortType portType = PortType.Both)
|
||||
{
|
||||
var random = new Random();
|
||||
for (ushort i = 0; i < 55535; i++)
|
||||
{
|
||||
var p = (ushort) random.Next(10000, 65535);
|
||||
if (!PortInUse(p))
|
||||
try
|
||||
{
|
||||
CheckPort(p, portType);
|
||||
return p;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception("Cant Generate Available Port");
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 记录Netch使用的端口
|
||||
/// </summary>
|
||||
public static readonly List<ushort> UsingPorts = new List<ushort>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -145,4 +164,7 @@ namespace Netch.Utils
|
||||
public class PortInUseException : Exception
|
||||
{
|
||||
}
|
||||
public class PortReservedException : Exception
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using System.Timers;
|
||||
using Netch.Models;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
@@ -9,14 +11,87 @@ namespace Netch.Utils
|
||||
{
|
||||
public static class ServerHelper
|
||||
{
|
||||
public static readonly IEnumerable<IServerUtil> ServerUtils;
|
||||
|
||||
static ServerHelper()
|
||||
{
|
||||
var serversUtilsTypes = Assembly.GetExecutingAssembly().GetExportedTypes().Where(type => type.GetInterfaces().Any(t => t == typeof(IServerUtil)));
|
||||
var serversUtilsTypes = Assembly.GetExecutingAssembly().GetExportedTypes().Where(type => type.GetInterfaces().Contains(typeof(IServerUtil)));
|
||||
ServerUtils = serversUtilsTypes.Select(t => (IServerUtil) Activator.CreateInstance(t)).OrderBy(util => util.Priority);
|
||||
}
|
||||
|
||||
#region Delay
|
||||
|
||||
public static class DelayTestHelper
|
||||
{
|
||||
private static readonly Timer Timer;
|
||||
private static bool _mux;
|
||||
|
||||
public static readonly Range Range = new(0, int.MaxValue / 1000);
|
||||
static DelayTestHelper()
|
||||
{
|
||||
Timer = new Timer
|
||||
{
|
||||
Interval = 10000,
|
||||
AutoReset = true
|
||||
};
|
||||
|
||||
Timer.Elapsed += (_, _) => TestAllDelay();
|
||||
}
|
||||
|
||||
public static bool Enabled
|
||||
{
|
||||
get => Timer.Enabled;
|
||||
set
|
||||
{
|
||||
if (!ValueIsEnabled(Global.Settings.DetectionTick))
|
||||
return;
|
||||
Timer.Enabled = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static int Interval => (int) (Timer.Interval / 1000);
|
||||
|
||||
private static bool ValueIsEnabled(int value)
|
||||
{
|
||||
return value != 0 && Range.InRange(value);
|
||||
}
|
||||
public static event EventHandler TestDelayFinished;
|
||||
|
||||
public static void TestAllDelay()
|
||||
{
|
||||
if (_mux)
|
||||
return;
|
||||
try
|
||||
{
|
||||
_mux = true;
|
||||
Parallel.ForEach(Global.Settings.Server, new ParallelOptions {MaxDegreeOfParallelism = 16},
|
||||
server => { server.Test(); });
|
||||
_mux = false;
|
||||
TestDelayFinished?.Invoke(null, new EventArgs());
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
public static void UpdateInterval()
|
||||
{
|
||||
Timer.Stop();
|
||||
|
||||
if (!ValueIsEnabled(Global.Settings.DetectionTick))
|
||||
return;
|
||||
|
||||
Timer.Interval = Global.Settings.DetectionTick * 1000;
|
||||
Task.Run(TestAllDelay);
|
||||
Timer.Start();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Handler
|
||||
|
||||
public static readonly IEnumerable<IServerUtil> ServerUtils;
|
||||
|
||||
public static Server ParseJObject(JObject o)
|
||||
{
|
||||
var handle = GetUtilByTypeName((string) o["Type"]);
|
||||
@@ -47,5 +122,7 @@ namespace Netch.Utils
|
||||
{
|
||||
return ServerUtils.FirstOrDefault(i => i.UriScheme.Any(s => s.Equals(typeName)));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using Netch.Servers.Shadowsocks;
|
||||
using Netch.Servers.Shadowsocks.Models;
|
||||
using Netch.Servers.VMess;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Server = Netch.Models.Server;
|
||||
|
||||
46
Netch/Utils/StringEx.cs
Normal file
46
Netch/Utils/StringEx.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Netch.Utils
|
||||
{
|
||||
static class StringEx
|
||||
{
|
||||
public static bool IsNullOrEmpty(this string value)
|
||||
{
|
||||
return string.IsNullOrEmpty(value);
|
||||
}
|
||||
|
||||
public static bool IsNullOrWhiteSpace(this string value)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(value);
|
||||
}
|
||||
|
||||
public static bool BeginWithAny(this string s, IEnumerable<char> chars)
|
||||
{
|
||||
if (s.IsNullOrEmpty()) return false;
|
||||
return chars.Contains(s[0]);
|
||||
}
|
||||
|
||||
public static bool IsWhiteSpace(this string value)
|
||||
{
|
||||
foreach (var c in value)
|
||||
{
|
||||
if (char.IsWhiteSpace(c)) continue;
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static IEnumerable<string> NonWhiteSpaceLines(this TextReader reader)
|
||||
{
|
||||
string line;
|
||||
while ((line = reader.ReadLine()) != null)
|
||||
{
|
||||
if (line.IsWhiteSpace()) continue;
|
||||
yield return line;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,10 @@ namespace Netch.Utils
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!item.Enable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var request = WebUtil.CreateRequest(item.Link);
|
||||
|
||||
if (!string.IsNullOrEmpty(item.UserAgent)) request.UserAgent = item.UserAgent;
|
||||
|
||||
@@ -12,7 +12,8 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using MaxMind.GeoIP2;
|
||||
using TaskScheduler;
|
||||
using Microsoft.Win32.TaskScheduler;
|
||||
using Task = System.Threading.Tasks.Task;
|
||||
|
||||
namespace Netch.Utils
|
||||
{
|
||||
@@ -56,12 +57,20 @@ namespace Netch.Utils
|
||||
return timeout;
|
||||
}
|
||||
|
||||
public static int ICMPing(IPAddress ip, int timeout = 1000)
|
||||
{
|
||||
var reply = new Ping().Send(ip, timeout);
|
||||
|
||||
if (reply?.Status == IPStatus.Success)
|
||||
return Convert.ToInt32(reply.RoundtripTime);
|
||||
|
||||
return timeout;
|
||||
}
|
||||
|
||||
public static string GetCityCode(string Hostname)
|
||||
{
|
||||
if (Hostname.Contains(":"))
|
||||
{
|
||||
Hostname = Hostname.Split(':')[0];
|
||||
}
|
||||
|
||||
string Country;
|
||||
try
|
||||
@@ -77,13 +86,9 @@ namespace Netch.Utils
|
||||
var DnsResult = DNS.Lookup(Hostname);
|
||||
|
||||
if (DnsResult != null)
|
||||
{
|
||||
Country = databaseReader.Country(DnsResult).Country.IsoCode;
|
||||
}
|
||||
else
|
||||
{
|
||||
Country = "Unknown";
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
@@ -126,7 +131,10 @@ namespace Netch.Utils
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetFileVersion(string file) => File.Exists(file) ? FileVersionInfo.GetVersionInfo(file).FileVersion : string.Empty;
|
||||
public static string GetFileVersion(string file)
|
||||
{
|
||||
return File.Exists(file) ? FileVersionInfo.GetVersionInfo(file).FileVersion : string.Empty;
|
||||
}
|
||||
|
||||
public static bool SearchOutboundAdapter(bool logging = true)
|
||||
{
|
||||
@@ -183,19 +191,12 @@ namespace Netch.Utils
|
||||
{
|
||||
e.DrawBackground();
|
||||
|
||||
if (e.Index >= 0)
|
||||
{
|
||||
var brush = new SolidBrush(cbx.ForeColor);
|
||||
if (e.Index < 0)
|
||||
return;
|
||||
|
||||
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
|
||||
brush = SystemBrushes.HighlightText as SolidBrush;
|
||||
|
||||
e.Graphics.DrawString(cbx.Items[e.Index].ToString(), cbx.Font, brush, e.Bounds, new StringFormat
|
||||
{
|
||||
LineAlignment = StringAlignment.Center,
|
||||
Alignment = StringAlignment.Center
|
||||
});
|
||||
}
|
||||
TextRenderer.DrawText(e.Graphics, cbx.Items[e.Index].ToString(), cbx.Font, e.Bounds,
|
||||
(e.State & DrawItemState.Selected) == DrawItemState.Selected ? SystemColors.HighlightText : cbx.ForeColor,
|
||||
TextFormatFlags.HorizontalCenter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,34 +205,32 @@ namespace Netch.Utils
|
||||
func.Invoke(component);
|
||||
switch (component)
|
||||
{
|
||||
case ListView listView:
|
||||
// ListView sub item
|
||||
foreach (var item in listView.Columns.Cast<ColumnHeader>())
|
||||
ComponentIterator(item, func);
|
||||
|
||||
break;
|
||||
case ToolStripMenuItem toolStripMenuItem:
|
||||
// Iterator Menu strip sub item
|
||||
foreach (var item in toolStripMenuItem.DropDownItems.Cast<ToolStripItem>())
|
||||
{
|
||||
ComponentIterator(item, func);
|
||||
}
|
||||
|
||||
break;
|
||||
case MenuStrip menuStrip:
|
||||
// Menu Strip
|
||||
foreach (var item in menuStrip.Items.Cast<ToolStripItem>())
|
||||
{
|
||||
ComponentIterator(item, func);
|
||||
}
|
||||
|
||||
break;
|
||||
case ContextMenuStrip contextMenuStrip:
|
||||
foreach (var item in contextMenuStrip.Items.Cast<ToolStripItem>())
|
||||
{
|
||||
ComponentIterator(item, func);
|
||||
}
|
||||
|
||||
break;
|
||||
case Control control:
|
||||
foreach (var c in control.Controls.Cast<Control>())
|
||||
{
|
||||
ComponentIterator(c, func);
|
||||
}
|
||||
|
||||
if (control.ContextMenuStrip != null)
|
||||
ComponentIterator(control.ContextMenuStrip, func);
|
||||
@@ -242,47 +241,35 @@ namespace Netch.Utils
|
||||
|
||||
public static void RegisterNetchStartupItem()
|
||||
{
|
||||
var scheduler = new TaskSchedulerClass();
|
||||
scheduler.Connect();
|
||||
var folder = scheduler.GetFolder("\\");
|
||||
|
||||
var taskIsExists = false;
|
||||
try
|
||||
{
|
||||
folder.GetTask("Netch Startup");
|
||||
taskIsExists = true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
const string TaskName = "Netch Startup";
|
||||
var folder = TaskService.Instance.GetFolder("\\");
|
||||
var taskIsExists = folder.Tasks.Any(task => task.Name == TaskName);
|
||||
|
||||
if (Global.Settings.RunAtStartup)
|
||||
{
|
||||
if (taskIsExists)
|
||||
folder.DeleteTask("Netch Startup", 0);
|
||||
folder.DeleteTask(TaskName, false);
|
||||
|
||||
var task = scheduler.NewTask(0);
|
||||
task.RegistrationInfo.Author = "Netch";
|
||||
task.RegistrationInfo.Description = "Netch run at startup.";
|
||||
task.Principal.RunLevel = _TASK_RUNLEVEL.TASK_RUNLEVEL_HIGHEST;
|
||||
var td = TaskService.Instance.NewTask();
|
||||
|
||||
task.Triggers.Create(_TASK_TRIGGER_TYPE2.TASK_TRIGGER_LOGON);
|
||||
var action = (IExecAction) task.Actions.Create(_TASK_ACTION_TYPE.TASK_ACTION_EXEC);
|
||||
action.Path = Application.ExecutablePath;
|
||||
td.RegistrationInfo.Author = "Netch";
|
||||
td.RegistrationInfo.Description = "Netch run at startup.";
|
||||
td.Principal.RunLevel = TaskRunLevel.Highest;
|
||||
|
||||
td.Triggers.Add(new LogonTrigger());
|
||||
td.Actions.Add(new ExecAction(Application.ExecutablePath));
|
||||
|
||||
task.Settings.ExecutionTimeLimit = "PT0S";
|
||||
task.Settings.DisallowStartIfOnBatteries = false;
|
||||
task.Settings.RunOnlyIfIdle = false;
|
||||
td.Settings.ExecutionTimeLimit = TimeSpan.Zero;
|
||||
td.Settings.DisallowStartIfOnBatteries = false;
|
||||
td.Settings.RunOnlyIfIdle = false;
|
||||
td.Settings.Compatibility = TaskCompatibility.V2_1;
|
||||
|
||||
folder.RegisterTaskDefinition("Netch Startup", task, (int) _TASK_CREATION.TASK_CREATE, null, null,
|
||||
_TASK_LOGON_TYPE.TASK_LOGON_INTERACTIVE_TOKEN, "");
|
||||
TaskService.Instance.RootFolder.RegisterTaskDefinition("Netch Startup", td);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (taskIsExists)
|
||||
folder.DeleteTask("Netch Startup", 0);
|
||||
folder.DeleteTask(TaskName, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -121,6 +121,9 @@ namespace Netch.Utils
|
||||
case ToolStripItem c:
|
||||
c.Text = Translate(c.Text);
|
||||
break;
|
||||
case ColumnHeader c:
|
||||
c.Text = Translate(c.Text);
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
[](https://github.com/NetchX/Netch/releases)
|
||||
[](https://github.com/NetchX/Netch/releases)
|
||||
[](https://github.com/NetchX/Netch/actions)
|
||||
[](https://netch.org/)
|
||||
[](LICENSE)
|
||||
|
||||
[中文说明](/docs/README.zh-CN.md)
|
||||
@@ -60,9 +59,10 @@ As well, Netch avoid the restricted NAT problem caused by SSTap. You can use an
|
||||
- [go-tun2socks](https://github.com/eycorsican/go-tun2socks)
|
||||
- [shadowsocks-libev](https://github.com/shadowsocks/shadowsocks-libev)
|
||||
- [shadowsocksr-libev](https://github.com/shadowsocksrr/shadowsocksr-libev)
|
||||
- [v2ray-core](https://github.com/v2ray/v2ray-core)
|
||||
- [v2ray-core](https://github.com/v2fly/v2ray-core)
|
||||
- [trojan](https://github.com/trojan-gfw/trojan)
|
||||
- [ACL4SSR](https://github.com/ACL4SSR/ACL4SSR)
|
||||
- [PAC](https://github.com/HMBSbige/Text_Translation/blob/master/ShadowsocksR/ss_white.pac)
|
||||
- [dnsmasq-china-list](https://github.com/felixonmars/dnsmasq-china-list)
|
||||
- [tap-windows6](https://github.com/OpenVPN/tap-windows6)
|
||||
- [Privoxy](https://www.privoxy.org/)
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||
<PackageReference Include="NUnit" Version="3.13.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
2
binaries
2
binaries
Submodule binaries updated: 4525fe9c71...f453be24b2
@@ -34,19 +34,21 @@
|
||||
### 模式 1 进程代理模式
|
||||
|
||||
- 根据进程名进行代理
|
||||
- 底层依赖于 [NetFilter SDK](https://netfiltersdk.com) 和 Redirector.exe(未开源)等
|
||||
- 底层依赖于 [NetFilter SDK](https://netfiltersdk.com)
|
||||
- 对于第一次使用 Netch 的用户而言,不需要做多余的事情
|
||||
- 若 [NetFilter SDK](https://netfiltersdk.com) 的驱动不存在,会自动安装
|
||||
- 若驱动版本过低,会自动更新
|
||||
|
||||
范例文件
|
||||
|
||||
在这个模式里,第一行只有备注是有用的
|
||||
在这个模式里,第一行只有备注是有用的,规则内容支持C++正则表达式
|
||||
|
||||
```
|
||||
# 备注
|
||||
进程名 1(会被代理)
|
||||
进程名 2
|
||||
!进程名 2(不会被代理)
|
||||
csgo.exe
|
||||
\\steam\\(代理运行路径包含steam的所有程序)
|
||||
...
|
||||
```
|
||||
|
||||
@@ -131,7 +133,7 @@
|
||||
|
||||
## Socks 5 代理中转
|
||||
|
||||
说明一下,Netch 并非是以网页代理为目的开发的程序,如果需要网络代理为目的的程序,需要 PAC,规则分流,订阅管理等功能的,请参考使用以下软件而非 Netch(均为 Windows 平台)
|
||||
说明一下,Netch 并非是以网页代理为目的开发的程序,如果需要网络代理为目的的程序,需要 PAC,规则分流,订阅管理等功能的,请尽量参考使用以下软件而非 Netch(均为 Windows 平台)
|
||||
|
||||
ShadowsocksR
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
[](https://github.com/NetchX/Netch/releases)
|
||||
[](https://github.com/NetchX/Netch/releases)
|
||||
[](https://github.com/NetchX/Netch/actions)
|
||||
[](https://netch.org/)
|
||||
[](LICENSE)
|
||||
|
||||
游戏加速工具
|
||||
@@ -69,9 +68,10 @@ Netch 支持多种语言,在启动时会根据系统语言选择自身语言
|
||||
- [go-tun2socks](https://github.com/eycorsican/go-tun2socks)
|
||||
- [shadowsocks-libev](https://github.com/shadowsocks/shadowsocks-libev)
|
||||
- [shadowsocksr-libev](https://github.com/shadowsocksrr/shadowsocksr-libev)
|
||||
- [v2ray-core](https://github.com/v2ray/v2ray-core)
|
||||
- [v2ray-core](https://github.com/v2fly/v2ray-core)
|
||||
- [trojan](https://github.com/trojan-gfw/trojan)
|
||||
- [ACL4SSR](https://github.com/ACL4SSR/ACL4SSR)
|
||||
- [PAC](https://github.com/HMBSbige/Text_Translation/blob/master/ShadowsocksR/ss_white.pac)
|
||||
- [dnsmasq-china-list](https://github.com/felixonmars/dnsmasq-china-list)
|
||||
- [tap-windows6](https://github.com/OpenVPN/tap-windows6)
|
||||
- [Privoxy](https://www.privoxy.org/)
|
||||
|
||||
2
modes
2
modes
Submodule modes updated: 90ffd0c66a...25ec8156f9
Submodule translations updated: e7390dc01f...8ce7bdb364
Reference in New Issue
Block a user