mirror of
https://github.com/netchx/netch.git
synced 2026-05-11 23:45:06 +08:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d15206b803 | ||
|
|
754753300d | ||
|
|
aa021aaf79 | ||
|
|
c50ca563b2 | ||
|
|
a1fdf7ead2 | ||
|
|
c9da7197ba | ||
|
|
5ff26e97b4 | ||
|
|
06049cb06f | ||
|
|
8cf765de92 | ||
|
|
2b53a7ca9e | ||
|
|
c7c0a2a698 | ||
|
|
1d072214ee | ||
|
|
135ff642bd | ||
|
|
4c274a1888 | ||
|
|
59cfc071cc | ||
|
|
8cf32e5d37 | ||
|
|
7a1e5b58b9 | ||
|
|
651fbb6ff9 | ||
|
|
45bf31e9f3 | ||
|
|
f7c9ab4028 | ||
|
|
717dc55055 | ||
|
|
a0c4dd3192 |
@@ -1,7 +1,7 @@
|
|||||||
|
root = true
|
||||||
# http://editorconfig.org/
|
# http://editorconfig.org/
|
||||||
|
|
||||||
# top-most EditorConfig file
|
# top-most EditorConfig file
|
||||||
root = true
|
|
||||||
|
|
||||||
# all files
|
# 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_invocable = 0
|
||||||
resharper_csharp_blank_lines_around_type = 0
|
resharper_csharp_blank_lines_around_type = 0
|
||||||
resharper_csharp_int_align_comments = true
|
resharper_csharp_int_align_comments = true
|
||||||
|
resharper_csharp_keep_blank_lines_in_declarations = 1
|
||||||
resharper_csharp_max_line_length = 368
|
resharper_csharp_max_line_length = 368
|
||||||
resharper_csharp_wrap_lines = false
|
resharper_csharp_wrap_lines = false
|
||||||
resharper_place_expr_accessor_on_single_line = true
|
resharper_place_expr_accessor_on_single_line = true
|
||||||
|
|||||||
@@ -2,12 +2,13 @@ using System;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using Microsoft.Win32;
|
|
||||||
using Netch.Models;
|
|
||||||
using Netch.Utils;
|
|
||||||
using WindowsProxy;
|
using WindowsProxy;
|
||||||
|
using Microsoft.Win32;
|
||||||
|
using Netch.Forms;
|
||||||
|
using Netch.Models;
|
||||||
using Netch.Servers.Socks5;
|
using Netch.Servers.Socks5;
|
||||||
using Netch.Servers.Trojan;
|
using Netch.Servers.Trojan;
|
||||||
|
using Netch.Utils;
|
||||||
using Netch.Utils.HttpProxyHandler;
|
using Netch.Utils.HttpProxyHandler;
|
||||||
|
|
||||||
namespace Netch.Controllers
|
namespace Netch.Controllers
|
||||||
@@ -16,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 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 string prevBypass, prevHTTP, prevPAC;
|
||||||
private bool prevEnabled;
|
private bool prevEnabled;
|
||||||
@@ -35,13 +36,11 @@ namespace Netch.Controllers
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (pPrivoxyController.Start(MainController.Server, mode))
|
if (pPrivoxyController.Start(MainController.Server, mode))
|
||||||
{
|
|
||||||
Global.Job.AddProcess(pPrivoxyController.Instance);
|
Global.Job.AddProcess(pPrivoxyController.Instance);
|
||||||
}
|
|
||||||
|
|
||||||
if (mode.Type == 3)
|
if (mode.Type == 3)
|
||||||
{
|
{
|
||||||
if ((MainController.Server is Socks5 or Trojan) && mode.BypassChina)
|
if (MainController.Server is Socks5 or Trojan && mode.BypassChina)
|
||||||
{
|
{
|
||||||
//启动PAC服务器
|
//启动PAC服务器
|
||||||
PACServerHandle.InitPACServer("127.0.0.1");
|
PACServerHandle.InitPACServer("127.0.0.1");
|
||||||
@@ -68,35 +67,6 @@ namespace Netch.Controllers
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RecordPrevious()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var registry = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings");
|
|
||||||
if (registry == null)
|
|
||||||
throw new Exception();
|
|
||||||
|
|
||||||
prevPAC = registry.GetValue("AutoConfigURL")?.ToString() ?? "";
|
|
||||||
prevHTTP = registry.GetValue("ProxyServer")?.ToString() ?? "";
|
|
||||||
prevBypass = registry.GetValue("ProxyOverride")?.ToString() ?? "";
|
|
||||||
prevEnabled = registry.GetValue("ProxyEnable")?.Equals(1) ?? false; // HTTP Proxy Enabled
|
|
||||||
|
|
||||||
if (prevHTTP == $"127.0.0.1:{Global.Settings.HTTPLocalPort}")
|
|
||||||
{
|
|
||||||
prevEnabled = false;
|
|
||||||
prevHTTP = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prevPAC != "")
|
|
||||||
prevEnabled = true;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
prevEnabled = false;
|
|
||||||
prevPAC = prevHTTP = prevBypass = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 停止
|
/// 停止
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -138,5 +108,34 @@ namespace Netch.Controllers
|
|||||||
};
|
};
|
||||||
Task.WaitAll(tasks);
|
Task.WaitAll(tasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void RecordPrevious()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var registry = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings");
|
||||||
|
if (registry == null)
|
||||||
|
throw new Exception();
|
||||||
|
|
||||||
|
prevPAC = registry.GetValue("AutoConfigURL")?.ToString() ?? "";
|
||||||
|
prevHTTP = registry.GetValue("ProxyServer")?.ToString() ?? "";
|
||||||
|
prevBypass = registry.GetValue("ProxyOverride")?.ToString() ?? "";
|
||||||
|
prevEnabled = registry.GetValue("ProxyEnable")?.Equals(1) ?? false; // HTTP Proxy Enabled
|
||||||
|
|
||||||
|
if (prevHTTP == $"127.0.0.1:{Global.Settings.HTTPLocalPort}")
|
||||||
|
{
|
||||||
|
prevEnabled = false;
|
||||||
|
prevHTTP = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevPAC != "")
|
||||||
|
prevEnabled = true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
prevEnabled = false;
|
||||||
|
prevPAC = prevHTTP = prevBypass = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,7 @@ using System.IO;
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Netch.Forms;
|
||||||
using Netch.Models;
|
using Netch.Models;
|
||||||
using Netch.Servers.Socks5;
|
using Netch.Servers.Socks5;
|
||||||
using Netch.Utils;
|
using Netch.Utils;
|
||||||
@@ -13,6 +14,19 @@ namespace Netch.Controllers
|
|||||||
{
|
{
|
||||||
public static class MainController
|
public static class MainController
|
||||||
{
|
{
|
||||||
|
public static Mode Mode;
|
||||||
|
|
||||||
|
/// TCP or Both Server
|
||||||
|
public static Server Server;
|
||||||
|
|
||||||
|
private static Server _udpServer;
|
||||||
|
|
||||||
|
public static bool NttTested;
|
||||||
|
|
||||||
|
private static readonly NTTController NTTController = new();
|
||||||
|
private static IServerController _serverController;
|
||||||
|
private static IServerController _udpServerController;
|
||||||
|
|
||||||
public static IServerController ServerController
|
public static IServerController ServerController
|
||||||
{
|
{
|
||||||
get => _serverController;
|
get => _serverController;
|
||||||
@@ -24,10 +38,6 @@ namespace Netch.Controllers
|
|||||||
get => _udpServerController ?? _serverController;
|
get => _udpServerController ?? _serverController;
|
||||||
set => _udpServerController = value;
|
set => _udpServerController = value;
|
||||||
}
|
}
|
||||||
public static Mode Mode;
|
|
||||||
|
|
||||||
/// TCP or Both Server
|
|
||||||
public static Server Server;
|
|
||||||
|
|
||||||
public static Server UdpServer
|
public static Server UdpServer
|
||||||
{
|
{
|
||||||
@@ -35,15 +45,8 @@ namespace Netch.Controllers
|
|||||||
set => _udpServer = value;
|
set => _udpServer = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Server _udpServer;
|
|
||||||
public static IModeController ModeController { get; private set; }
|
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>
|
||||||
/// 启动
|
/// 启动
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -57,9 +60,7 @@ namespace Netch.Controllers
|
|||||||
Mode = mode;
|
Mode = mode;
|
||||||
|
|
||||||
if (server is Socks5 && mode.Type == 4)
|
if (server is Socks5 && mode.Type == 4)
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
// 刷新DNS缓存
|
// 刷新DNS缓存
|
||||||
NativeMethods.FlushDNSResolverCache();
|
NativeMethods.FlushDNSResolverCache();
|
||||||
@@ -88,20 +89,16 @@ namespace Netch.Controllers
|
|||||||
if (!ModeHelper.SkipServerController(server, mode))
|
if (!ModeHelper.SkipServerController(server, mode))
|
||||||
{
|
{
|
||||||
if (!await Task.Run(() => StartServer(server, mode, ref _serverController)))
|
if (!await Task.Run(() => StartServer(server, mode, ref _serverController)))
|
||||||
{
|
|
||||||
throw new StartFailedException();
|
throw new StartFailedException();
|
||||||
}
|
|
||||||
|
|
||||||
StatusPortInfoText.UpdateShareLan();
|
StatusPortInfoText.UpdateShareLan();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!await StartMode(mode))
|
if (!await StartMode(mode))
|
||||||
{
|
|
||||||
throw new StartFailedException();
|
throw new StartFailedException();
|
||||||
}
|
|
||||||
|
|
||||||
if (mode.TestNatRequired())
|
_ = Task.Run(Bandwidth.NetTraffic);
|
||||||
NatTest();
|
_ = Task.Run(NatTest);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -114,7 +111,6 @@ namespace Netch.Controllers
|
|||||||
MessageBoxX.Show(e.Message + "\n\n" + i18N.Translate("Missing File or runtime components"), owner: Global.MainForm);
|
MessageBoxX.Show(e.Message + "\n\n" + i18N.Translate("Missing File or runtime components"), owner: Global.MainForm);
|
||||||
break;
|
break;
|
||||||
case StartFailedException _:
|
case StartFailedException _:
|
||||||
case PortInUseException _:
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Logging.Error($"主控制器未处理异常: {e}");
|
Logging.Error($"主控制器未处理异常: {e}");
|
||||||
@@ -139,35 +135,30 @@ namespace Netch.Controllers
|
|||||||
controller = ServerHelper.GetUtilByTypeName(server.Type).GetController();
|
controller = ServerHelper.GetUtilByTypeName(server.Type).GetController();
|
||||||
|
|
||||||
if (controller is Guard instanceController)
|
if (controller is Guard instanceController)
|
||||||
{
|
|
||||||
Utils.Utils.KillProcessByName(instanceController.MainFile);
|
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));
|
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", controller.Name));
|
||||||
if (controller.Start(in server, mode))
|
if (controller.Start(in server, mode))
|
||||||
{
|
{
|
||||||
if (controller is Guard guard)
|
if (controller is Guard guard)
|
||||||
{
|
|
||||||
if (guard.Instance != null)
|
if (guard.Instance != null)
|
||||||
{
|
|
||||||
Task.Run(() =>
|
Task.Run(() =>
|
||||||
{
|
{
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
Global.Job.AddProcess(guard.Instance);
|
Global.Job.AddProcess(guard.Instance);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (server is Socks5 socks5)
|
if (server is Socks5 socks5)
|
||||||
{
|
{
|
||||||
if (socks5.Auth())
|
if (socks5.Auth())
|
||||||
UsingPorts.Add(StatusPortInfoText.Socks5Port = controller.Socks5LocalPort());
|
StatusPortInfoText.Socks5Port = controller.Socks5LocalPort();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UsingPorts.Add(StatusPortInfoText.Socks5Port = controller.Socks5LocalPort());
|
StatusPortInfoText.Socks5Port = controller.Socks5LocalPort();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -181,26 +172,18 @@ namespace Netch.Controllers
|
|||||||
ModeController = ModeHelper.GetModeControllerByType(mode.Type, out var port, out var portName, out var portType);
|
ModeController = ModeHelper.GetModeControllerByType(mode.Type, out var port, out var portName, out var portType);
|
||||||
|
|
||||||
if (ModeController == null)
|
if (ModeController == null)
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
if (port != null)
|
if (port != null)
|
||||||
{
|
if (!PortCheckAndShowMessageBox((ushort) port, portName, portType))
|
||||||
PortCheckAndShowMessageBox((ushort) port, portName, portType);
|
return false;
|
||||||
UsingPorts.Add((ushort) port);
|
|
||||||
}
|
|
||||||
|
|
||||||
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ModeController.Name));
|
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ModeController.Name));
|
||||||
if (await Task.Run(() => ModeController.Start(mode)))
|
if (await Task.Run(() => ModeController.Start(mode)))
|
||||||
{
|
{
|
||||||
if (ModeController is Guard guard)
|
if (ModeController is Guard guard)
|
||||||
{
|
|
||||||
if (guard.Instance != null)
|
if (guard.Instance != null)
|
||||||
{
|
|
||||||
Global.Job.AddProcess(guard.Instance);
|
Global.Job.AddProcess(guard.Instance);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -213,7 +196,6 @@ namespace Netch.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static async Task Stop()
|
public static async Task Stop()
|
||||||
{
|
{
|
||||||
UsingPorts.Clear();
|
|
||||||
StatusPortInfoText.Reset();
|
StatusPortInfoText.Reset();
|
||||||
|
|
||||||
_ = Task.Run(() => NTTController.Stop());
|
_ = Task.Run(() => NTTController.Stop());
|
||||||
@@ -221,28 +203,33 @@ namespace Netch.Controllers
|
|||||||
var tasks = new[]
|
var tasks = new[]
|
||||||
{
|
{
|
||||||
Task.Run(() => ServerController?.Stop()),
|
Task.Run(() => ServerController?.Stop()),
|
||||||
Task.Run(() => ModeController?.Stop()),
|
Task.Run(() => ModeController?.Stop())
|
||||||
};
|
};
|
||||||
await Task.WhenAll(tasks);
|
await Task.WhenAll(tasks);
|
||||||
ModeController = null;
|
ModeController = null;
|
||||||
ServerController = null;
|
ServerController = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 检查端口是否被占用,
|
/// 检查端口是否被占用,
|
||||||
/// 被占用则弹窗提示, 确认后抛出异常
|
/// 被占用则弹窗提示, 确认后抛出异常
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="port">检查的端口</param>
|
public static bool PortCheckAndShowMessageBox(ushort port, string portName, PortType portType = PortType.Both)
|
||||||
/// <param name="portName">端口用途名称</param>
|
|
||||||
/// <param name="portType"></param>
|
|
||||||
/// <exception cref="PortInUseException"></exception>
|
|
||||||
public static void 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})"));
|
MessageBoxX.Show(i18N.TranslateFormat("The {0} port is in use.", $"{portName} ({port})"));
|
||||||
throw new PortInUseException();
|
return false;
|
||||||
|
}
|
||||||
|
catch (PortReservedException)
|
||||||
|
{
|
||||||
|
MessageBoxX.Show(i18N.TranslateFormat("The {0} port is reserved by system.", $"{portName} ({port})"));
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,6 +238,8 @@ namespace Netch.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static void NatTest()
|
public static void NatTest()
|
||||||
{
|
{
|
||||||
|
if (!Mode.TestNatRequired())
|
||||||
|
return;
|
||||||
NttTested = false;
|
NttTested = false;
|
||||||
Task.Run(() =>
|
Task.Run(() =>
|
||||||
{
|
{
|
||||||
@@ -264,7 +253,9 @@ namespace Netch.Controllers
|
|||||||
Global.MainForm.NatTypeStatusText(result, country);
|
Global.MainForm.NatTypeStatusText(result, country);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
Global.MainForm.NatTypeStatusText(result ?? "Error");
|
Global.MainForm.NatTypeStatusText(result ?? "Error");
|
||||||
|
}
|
||||||
|
|
||||||
NttTested = true;
|
NttTested = true;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using System.Linq;
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.ServiceProcess;
|
using System.ServiceProcess;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Netch.Forms;
|
||||||
using Netch.Models;
|
using Netch.Models;
|
||||||
using Netch.Servers.Shadowsocks;
|
using Netch.Servers.Shadowsocks;
|
||||||
using Netch.Servers.Socks5;
|
using Netch.Servers.Socks5;
|
||||||
@@ -15,14 +16,12 @@ namespace Netch.Controllers
|
|||||||
{
|
{
|
||||||
public class NFController : IModeController
|
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 BinDriver = string.Empty;
|
||||||
private static readonly string SystemDriver = $"{Environment.SystemDirectory}\\drivers\\netfilter2.sys";
|
private static readonly string SystemDriver = $"{Environment.SystemDirectory}\\drivers\\netfilter2.sys";
|
||||||
private static string _sysDns;
|
private static string _sysDns;
|
||||||
|
|
||||||
public string Name { get; } = "Redirector";
|
|
||||||
|
|
||||||
static NFController()
|
static NFController()
|
||||||
{
|
{
|
||||||
string fileName;
|
string fileName;
|
||||||
@@ -47,6 +46,8 @@ namespace Netch.Controllers
|
|||||||
BinDriver = "bin\\" + fileName;
|
BinDriver = "bin\\" + fileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string Name { get; } = "Redirector";
|
||||||
|
|
||||||
public bool Start(in Mode mode)
|
public bool Start(in Mode mode)
|
||||||
{
|
{
|
||||||
if (!CheckDriver())
|
if (!CheckDriver())
|
||||||
@@ -105,8 +106,19 @@ namespace Netch.Controllers
|
|||||||
return aio_init();
|
return aio_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
if (Global.Settings.ModifySystemDNS)
|
||||||
|
//恢复系统DNS
|
||||||
|
DNS.OutboundDNS = _sysDns;
|
||||||
|
});
|
||||||
|
|
||||||
|
aio_free();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="rules"></param>
|
/// <param name="rules"></param>
|
||||||
/// <param name="incompatibleRule"></param>
|
/// <param name="incompatibleRule"></param>
|
||||||
@@ -119,7 +131,6 @@ namespace Netch.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="r"></param>
|
/// <param name="r"></param>
|
||||||
/// <param name="clear"></param>
|
/// <param name="clear"></param>
|
||||||
@@ -161,9 +172,7 @@ namespace Netch.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!File.Exists(SystemDriver))
|
if (!File.Exists(SystemDriver))
|
||||||
{
|
|
||||||
return InstallDriver();
|
return InstallDriver();
|
||||||
}
|
|
||||||
|
|
||||||
var updateFlag = false;
|
var updateFlag = false;
|
||||||
|
|
||||||
@@ -178,18 +187,14 @@ namespace Netch.Controllers
|
|||||||
{
|
{
|
||||||
// Installed greater than Bin
|
// Installed greater than Bin
|
||||||
if (systemResult.Major != binResult.Major)
|
if (systemResult.Major != binResult.Major)
|
||||||
{
|
|
||||||
// API breaking changes
|
// API breaking changes
|
||||||
updateFlag = true;
|
updateFlag = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!systemFileVersion.Equals(binFileVersion))
|
if (!systemFileVersion.Equals(binFileVersion))
|
||||||
{
|
|
||||||
updateFlag = true;
|
updateFlag = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!updateFlag) return true;
|
if (!updateFlag) return true;
|
||||||
@@ -267,18 +272,6 @@ namespace Netch.Controllers
|
|||||||
aio_dial((int) NameList.TYPE_ADDNAME, @"NTT\.exe");
|
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
|
#region NativeMethods
|
||||||
|
|
||||||
private const int UdpNameListOffset = (int) NameList.TYPE_UDPTYPE - (int) NameList.TYPE_TCPTYPE;
|
private const int UdpNameListOffset = (int) NameList.TYPE_UDPTYPE - (int) NameList.TYPE_TCPTYPE;
|
||||||
@@ -299,7 +292,7 @@ namespace Netch.Controllers
|
|||||||
private static extern ulong aio_getDL();
|
private static extern ulong aio_getDL();
|
||||||
|
|
||||||
|
|
||||||
public enum NameList : int
|
public enum NameList
|
||||||
{
|
{
|
||||||
TYPE_FILTERLOOPBACK,
|
TYPE_FILTERLOOPBACK,
|
||||||
TYPE_FILTERTCP,
|
TYPE_FILTERTCP,
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ namespace Netch.Controllers
|
|||||||
{
|
{
|
||||||
public class TUNTAPController : Guard, IModeController
|
public class TUNTAPController : Guard, IModeController
|
||||||
{
|
{
|
||||||
|
private readonly List<string> _directIPs = new();
|
||||||
|
|
||||||
|
private readonly List<string> _proxyIPs = new();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 服务器 IP 地址
|
/// 服务器 IP 地址
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -24,16 +26,16 @@ namespace Netch.Controllers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 本地 DNS 服务控制器
|
/// 本地 DNS 服务控制器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DNSController DNSController = new DNSController();
|
public DNSController DNSController = new();
|
||||||
|
|
||||||
public TUNTAPController()
|
public TUNTAPController()
|
||||||
{
|
{
|
||||||
StartedKeywords.Add("Running");
|
StartedKeywords.Add("Running");
|
||||||
StoppedKeywords.AddRange(new[] {"failed", "invalid vconfig file"});
|
StoppedKeywords.AddRange(new[] {"failed", "invalid vconfig file"});
|
||||||
}
|
}
|
||||||
|
public override string MainFile { get; protected set; } = "tun2socks.exe";
|
||||||
|
|
||||||
public override string Name { get; protected set; } = "tun2socks";
|
public override string Name { get; protected set; } = "tun2socks";
|
||||||
public override string MainFile { get; protected set; } = "tun2socks.exe";
|
|
||||||
|
|
||||||
public bool Start(in Mode mode)
|
public bool Start(in Mode mode)
|
||||||
{
|
{
|
||||||
@@ -43,9 +45,7 @@ namespace Netch.Controllers
|
|||||||
|
|
||||||
// 查找出口适配器
|
// 查找出口适配器
|
||||||
if (!Utils.Utils.SearchOutboundAdapter())
|
if (!Utils.Utils.SearchOutboundAdapter())
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
// 查找并安装 TAP 适配器
|
// 查找并安装 TAP 适配器
|
||||||
if (!SearchTapAdapter())
|
if (!SearchTapAdapter())
|
||||||
@@ -79,14 +79,8 @@ namespace Netch.Controllers
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
try
|
if (!MainController.PortCheckAndShowMessageBox(53, "DNS"))
|
||||||
{
|
|
||||||
MainController.PortCheckAndShowMessageBox(53, "DNS");
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
if (!DNSController.Start())
|
if (!DNSController.Start())
|
||||||
{
|
{
|
||||||
@@ -126,10 +120,6 @@ namespace Netch.Controllers
|
|||||||
Task.WaitAll(tasks);
|
Task.WaitAll(tasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly List<string> _directIPs = new List<string>();
|
|
||||||
|
|
||||||
private readonly List<string> _proxyIPs = new List<string>();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设置绕行规则
|
/// 设置绕行规则
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -150,7 +140,6 @@ namespace Netch.Controllers
|
|||||||
|
|
||||||
//处理 NAT 类型检测,由于协议的原因,无法仅通过域名确定需要代理的 IP,自己记录解析了返回的 IP,仅支持默认检测服务器
|
//处理 NAT 类型检测,由于协议的原因,无法仅通过域名确定需要代理的 IP,自己记录解析了返回的 IP,仅支持默认检测服务器
|
||||||
if (Global.Settings.STUN_Server == "stun.stunprotocol.org")
|
if (Global.Settings.STUN_Server == "stun.stunprotocol.org")
|
||||||
{
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Logging.Info("代理 → STUN 服务器 IP");
|
Logging.Info("代理 → STUN 服务器 IP");
|
||||||
@@ -166,23 +155,18 @@ namespace Netch.Controllers
|
|||||||
{
|
{
|
||||||
Logging.Info("NAT 类型测试域名解析失败,将不会被添加到代理列表");
|
Logging.Info("NAT 类型测试域名解析失败,将不会被添加到代理列表");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (Global.Settings.TUNTAP.ProxyDNS)
|
if (Global.Settings.TUNTAP.ProxyDNS)
|
||||||
{
|
{
|
||||||
Logging.Info("代理 → 自定义 DNS");
|
Logging.Info("代理 → 自定义 DNS");
|
||||||
if (Global.Settings.TUNTAP.UseCustomDNS)
|
if (Global.Settings.TUNTAP.UseCustomDNS)
|
||||||
{
|
|
||||||
RouteAction(Action.Create,
|
RouteAction(Action.Create,
|
||||||
Global.Settings.TUNTAP.DNS.Select(ip => $"{ip}/32"),
|
Global.Settings.TUNTAP.DNS.Select(ip => $"{ip}/32"),
|
||||||
RouteType.TUNTAP);
|
RouteType.TUNTAP);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
RouteAction(Action.Create,
|
RouteAction(Action.Create,
|
||||||
new[] {"1.1.1.1", "8.8.8.8", "9.9.9.9", "185.222.222.222"}.Select(ip => $"{ip}/32"),
|
new[] {"1.1.1.1", "8.8.8.8", "9.9.9.9", "185.222.222.222"}.Select(ip => $"{ip}/32"),
|
||||||
RouteType.TUNTAP);
|
RouteType.TUNTAP);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -303,26 +287,11 @@ namespace Netch.Controllers
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private enum RouteType
|
|
||||||
{
|
|
||||||
Outbound,
|
|
||||||
TUNTAP
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum Action
|
|
||||||
{
|
|
||||||
Create,
|
|
||||||
Delete
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RouteAction(Action action, in IEnumerable<string> ipNetworks, RouteType routeType,
|
private void RouteAction(Action action, in IEnumerable<string> ipNetworks, RouteType routeType,
|
||||||
int metric = 0)
|
int metric = 0)
|
||||||
{
|
{
|
||||||
foreach (var address in ipNetworks)
|
foreach (var address in ipNetworks)
|
||||||
{
|
|
||||||
RouteAction(action, address, routeType, metric);
|
RouteAction(action, address, routeType, metric);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool RouteAction(Action action, in string ipNetwork, RouteType routeType, int metric = 0)
|
private bool RouteAction(Action action, in string ipNetwork, RouteType routeType, int metric = 0)
|
||||||
@@ -383,11 +352,22 @@ namespace Netch.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
|
||||||
Logging.Warning($"Failed to {action} Route on {routeType} Adapter: {ipNetwork} metric {metric}");
|
Logging.Warning($"Failed to {action} Route on {routeType} Adapter: {ipNetwork} metric {metric}");
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private enum RouteType
|
||||||
|
{
|
||||||
|
Outbound,
|
||||||
|
TUNTAP
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum Action
|
||||||
|
{
|
||||||
|
Create,
|
||||||
|
Delete
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,17 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Netch.Models.GitHubRelease;
|
using Netch.Models.GitHubRelease;
|
||||||
using Netch.Utils;
|
using Netch.Utils;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Netch.Controllers
|
namespace Netch.Controllers
|
||||||
{
|
{
|
||||||
public class UpdateChecker
|
public static class UpdateChecker
|
||||||
{
|
{
|
||||||
public const string Owner = @"NetchX";
|
public const string Owner = @"NetchX";
|
||||||
public const string Repo = @"Netch";
|
public const string Repo = @"Netch";
|
||||||
@@ -15,20 +19,20 @@ namespace Netch.Controllers
|
|||||||
public const string Name = @"Netch";
|
public const string Name = @"Netch";
|
||||||
public const string Copyright = @"Copyright © 2019 - 2020";
|
public const string Copyright = @"Copyright © 2019 - 2020";
|
||||||
|
|
||||||
public const string AssemblyVersion = @"1.7.1";
|
public const string AssemblyVersion = @"1.7.2";
|
||||||
private const string Suffix = @"";
|
private const string Suffix = @"";
|
||||||
|
|
||||||
public static readonly string Version = $"{AssemblyVersion}{(string.IsNullOrEmpty(Suffix) ? "" : $"-{Suffix}")}";
|
public static readonly string Version = $"{AssemblyVersion}{(string.IsNullOrEmpty(Suffix) ? "" : $"-{Suffix}")}";
|
||||||
|
|
||||||
public string LatestVersionNumber;
|
public static string LatestVersionNumber;
|
||||||
public string LatestVersionUrl;
|
public static string LatestVersionUrl;
|
||||||
public Release LatestRelease;
|
public static Release LatestRelease;
|
||||||
|
|
||||||
public event EventHandler NewVersionFound;
|
public static event EventHandler NewVersionFound;
|
||||||
public event EventHandler NewVersionFoundFailed;
|
public static event EventHandler NewVersionFoundFailed;
|
||||||
public event EventHandler NewVersionNotFound;
|
public static event EventHandler NewVersionNotFound;
|
||||||
|
|
||||||
public async void Check(bool isPreRelease)
|
public static async void Check(bool isPreRelease)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -45,12 +49,12 @@ namespace Netch.Controllers
|
|||||||
if (VersionUtil.CompareVersion(LatestRelease.tag_name, Version) > 0)
|
if (VersionUtil.CompareVersion(LatestRelease.tag_name, Version) > 0)
|
||||||
{
|
{
|
||||||
Logging.Info("发现新版本");
|
Logging.Info("发现新版本");
|
||||||
NewVersionFound?.Invoke(this, new EventArgs());
|
NewVersionFound?.Invoke(null, new EventArgs());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Logging.Info("目前是最新版本");
|
Logging.Info("目前是最新版本");
|
||||||
NewVersionNotFound?.Invoke(this, new EventArgs());
|
NewVersionNotFound?.Invoke(null, new EventArgs());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -58,12 +62,67 @@ namespace Netch.Controllers
|
|||||||
if (e is WebException)
|
if (e is WebException)
|
||||||
Logging.Warning($"获取新版本失败: {e.Message}");
|
Logging.Warning($"获取新版本失败: {e.Message}");
|
||||||
else
|
else
|
||||||
{
|
|
||||||
Logging.Warning(e.ToString());
|
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(); });
|
|
||||||
// 如果勾选启动后最小化
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
12
Netch/Forms/MainForm.Designer.cs
generated
12
Netch/Forms/MainForm.Designer.cs
generated
@@ -39,6 +39,7 @@
|
|||||||
this.SubscribeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
this.SubscribeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.ManageSubscribeLinksToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
this.ManageSubscribeLinksToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.UpdateServersFromSubscribeLinksToolStripMenuItem = 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.OptionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.OpenDirectoryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
this.OpenDirectoryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.CleanDNSCacheToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
this.CleanDNSCacheToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
@@ -170,7 +171,8 @@
|
|||||||
//
|
//
|
||||||
this.SubscribeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
this.SubscribeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||||
this.ManageSubscribeLinksToolStripMenuItem,
|
this.ManageSubscribeLinksToolStripMenuItem,
|
||||||
this.UpdateServersFromSubscribeLinksToolStripMenuItem});
|
this.UpdateServersFromSubscribeLinksToolStripMenuItem,
|
||||||
|
this.UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem});
|
||||||
this.SubscribeToolStripMenuItem.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1);
|
this.SubscribeToolStripMenuItem.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1);
|
||||||
this.SubscribeToolStripMenuItem.Name = "SubscribeToolStripMenuItem";
|
this.SubscribeToolStripMenuItem.Name = "SubscribeToolStripMenuItem";
|
||||||
this.SubscribeToolStripMenuItem.Size = new System.Drawing.Size(77, 21);
|
this.SubscribeToolStripMenuItem.Size = new System.Drawing.Size(77, 21);
|
||||||
@@ -190,6 +192,13 @@
|
|||||||
this.UpdateServersFromSubscribeLinksToolStripMenuItem.Text = "Update Servers From Subscribe Links";
|
this.UpdateServersFromSubscribeLinksToolStripMenuItem.Text = "Update Servers From Subscribe Links";
|
||||||
this.UpdateServersFromSubscribeLinksToolStripMenuItem.Click += new System.EventHandler(this.UpdateServersFromSubscribeLinksToolStripMenuItem_Click);
|
this.UpdateServersFromSubscribeLinksToolStripMenuItem.Click += new System.EventHandler(this.UpdateServersFromSubscribeLinksToolStripMenuItem_Click);
|
||||||
//
|
//
|
||||||
|
// UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem
|
||||||
|
//
|
||||||
|
this.UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem.Name = "UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem";
|
||||||
|
this.UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem.Size = new System.Drawing.Size(294, 22);
|
||||||
|
this.UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem.Text = "Update Servers From Subscribe Links With Proxy";
|
||||||
|
this.UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem.Click += new System.EventHandler(this.UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem_Click);
|
||||||
|
//
|
||||||
// OptionsToolStripMenuItem
|
// OptionsToolStripMenuItem
|
||||||
//
|
//
|
||||||
this.OptionsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
this.OptionsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||||
@@ -800,6 +809,7 @@
|
|||||||
private System.Windows.Forms.ToolStripMenuItem UpdateACLToolStripMenuItem;
|
private System.Windows.Forms.ToolStripMenuItem UpdateACLToolStripMenuItem;
|
||||||
private System.Windows.Forms.ToolStripMenuItem updateACLWithProxyToolStripMenuItem;
|
private System.Windows.Forms.ToolStripMenuItem updateACLWithProxyToolStripMenuItem;
|
||||||
private System.Windows.Forms.ToolStripMenuItem UpdateServersFromSubscribeLinksToolStripMenuItem;
|
private System.Windows.Forms.ToolStripMenuItem UpdateServersFromSubscribeLinksToolStripMenuItem;
|
||||||
|
private System.Windows.Forms.ToolStripMenuItem UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem;
|
||||||
private System.Windows.Forms.ToolStripStatusLabel UploadSpeedLabel;
|
private System.Windows.Forms.ToolStripStatusLabel UploadSpeedLabel;
|
||||||
private System.Windows.Forms.ToolStripStatusLabel UsedBandwidthLabel;
|
private System.Windows.Forms.ToolStripStatusLabel UsedBandwidthLabel;
|
||||||
private System.Windows.Forms.ToolStripLabel NewVersionLabel;
|
private System.Windows.Forms.ToolStripLabel NewVersionLabel;
|
||||||
|
|||||||
@@ -1,377 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Net;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
using Netch.Controllers;
|
|
||||||
using Netch.Forms.Mode;
|
|
||||||
using Netch.Models;
|
|
||||||
using Netch.Utils;
|
|
||||||
|
|
||||||
namespace Netch.Forms
|
|
||||||
{
|
|
||||||
partial class Dummy
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
partial class MainForm
|
|
||||||
{
|
|
||||||
#region MenuStrip
|
|
||||||
|
|
||||||
#region 服务器
|
|
||||||
|
|
||||||
private void ImportServersFromClipboardToolStripMenuItem_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
var texts = Clipboard.GetText();
|
|
||||||
if (!string.IsNullOrWhiteSpace(texts))
|
|
||||||
{
|
|
||||||
var servers = ShareLink.ParseText(texts);
|
|
||||||
Global.Settings.Server.AddRange(servers);
|
|
||||||
NotifyTip(i18N.TranslateFormat("Import {0} server(s) form Clipboard", servers.Count));
|
|
||||||
|
|
||||||
InitServer();
|
|
||||||
Configuration.Save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddServerToolStripMenuItem_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
var s = ((ToolStripMenuItem) sender).Text;
|
|
||||||
|
|
||||||
var start = s.IndexOf("[", StringComparison.Ordinal) + 1;
|
|
||||||
var end = s.IndexOf("]", start, StringComparison.Ordinal);
|
|
||||||
var result = s.Substring(start, end - start);
|
|
||||||
|
|
||||||
Hide();
|
|
||||||
ServerHelper.GetUtilByFullName(result).Create();
|
|
||||||
|
|
||||||
InitServer();
|
|
||||||
Configuration.Save();
|
|
||||||
Show();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 模式
|
|
||||||
|
|
||||||
private void CreateProcessModeToolStripButton_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
Hide();
|
|
||||||
new Process().ShowDialog();
|
|
||||||
Show();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ReloadModesToolStripMenuItem_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
Enabled = false;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ModeHelper.Load();
|
|
||||||
InitMode();
|
|
||||||
NotifyTip(i18N.Translate("Modes have been reload"));
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Enabled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 订阅
|
|
||||||
|
|
||||||
private void ManageSubscribeLinksToolStripMenuItem_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
Hide();
|
|
||||||
new SubscribeForm().ShowDialog();
|
|
||||||
InitServer();
|
|
||||||
Show();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void UpdateServersFromSubscribeLinksToolStripMenuItem_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
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();
|
|
||||||
});
|
|
||||||
|
|
||||||
NotifyTip(i18N.Translate("DNS cache cleanup succeeded"));
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
StatusText();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateACLWithProxyToolStripMenuItem_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
UpdateACL(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateACLToolStripMenuItem_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
UpdateACL(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void UpdateACL(bool useProxy)
|
|
||||||
{
|
|
||||||
if (useProxy && ServerComboBox.SelectedIndex == -1)
|
|
||||||
{
|
|
||||||
MessageBoxX.Show(i18N.Translate("Please select a server first"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Enabled = false;
|
|
||||||
StatusText(i18N.TranslateFormat("Updating {0}", "ACL"));
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (useProxy)
|
|
||||||
{
|
|
||||||
var mode = new Models.Mode
|
|
||||||
{
|
|
||||||
Remark = "ProxyUpdate",
|
|
||||||
Type = 5
|
|
||||||
};
|
|
||||||
State = State.Starting;
|
|
||||||
await MainController.Start(ServerComboBox.SelectedItem as Server, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
var req = WebUtil.CreateRequest(Global.Settings.ACL);
|
|
||||||
if (useProxy)
|
|
||||||
req.Proxy = new WebProxy($"http://127.0.0.1:{Global.Settings.HTTPLocalPort}");
|
|
||||||
|
|
||||||
await WebUtil.DownloadFileAsync(req, Path.Combine(Global.NetchDir, "bin\\default.acl"));
|
|
||||||
NotifyTip(i18N.Translate("ACL updated successfully"));
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
NotifyTip(i18N.Translate("ACL update failed") + "\n" + e.Message, info: false);
|
|
||||||
Logging.Error("更新 ACL 失败!" + e);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (useProxy)
|
|
||||||
{
|
|
||||||
await MainController.Stop();
|
|
||||||
State = State.Stopped;
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusText();
|
|
||||||
Enabled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void updatePACToolStripMenuItem_Click(object sender, EventArgs eventArgs)
|
|
||||||
{
|
|
||||||
Enabled = false;
|
|
||||||
|
|
||||||
StatusText(i18N.TranslateFormat("Updating {0}", "PAC"));
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var req = WebUtil.CreateRequest(Global.Settings.PAC);
|
|
||||||
|
|
||||||
string pac = Path.Combine(Global.NetchDir, "bin\\pac.txt");
|
|
||||||
|
|
||||||
await WebUtil.DownloadFileAsync(req, pac);
|
|
||||||
|
|
||||||
NotifyTip(i18N.Translate("PAC updated successfully"));
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
NotifyTip(i18N.Translate("PAC update failed") + "\n" + e.Message, info: false);
|
|
||||||
Logging.Error("更新 PAC 失败!" + e);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
StatusText();
|
|
||||||
Enabled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void UninstallServiceToolStripMenuItem_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
Enabled = false;
|
|
||||||
StatusText(i18N.TranslateFormat("Uninstalling {0}", "NF Service"));
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await Task.Run(() =>
|
|
||||||
{
|
|
||||||
if (NFController.UninstallDriver())
|
|
||||||
{
|
|
||||||
NotifyTip(i18N.TranslateFormat("{0} has been uninstalled", "NF Service"));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
StatusText();
|
|
||||||
Enabled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void UninstallTapDriverToolStripMenuItem_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
Enabled = false;
|
|
||||||
StatusText(i18N.TranslateFormat("Uninstalling {0}", "TUN/TAP driver"));
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await Task.Run(TUNTAP.deltapall);
|
|
||||||
NotifyTip(i18N.TranslateFormat("{0} has been uninstalled", "TUN/TAP driver"));
|
|
||||||
}
|
|
||||||
catch (Exception exception)
|
|
||||||
{
|
|
||||||
Logging.Error($"卸载 TUN/TAP 适配器失败: {exception}");
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
StatusText();
|
|
||||||
Enabled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 菜单栏强制退出
|
|
||||||
/// </summary>
|
|
||||||
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,239 +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 =
|
|
||||||
updatePACToolStripMenuItem.Enabled =
|
|
||||||
UpdateServersFromSubscribeLinksToolStripMenuItem.Enabled =
|
|
||||||
UninstallTapDriverToolStripMenuItem.Enabled =
|
|
||||||
ReloadModesToolStripMenuItem.Enabled = enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
_state = value;
|
|
||||||
|
|
||||||
StatusText();
|
|
||||||
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;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case State.Stopping:
|
|
||||||
ControlButton.Enabled = false;
|
|
||||||
ControlButton.Text = "...";
|
|
||||||
|
|
||||||
ProfileGroupBox.Enabled = false;
|
|
||||||
BandwidthState(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 BandwidthState(bool state)
|
|
||||||
{
|
|
||||||
UsedBandwidthLabel.Visible /*= UploadSpeedLabel.Visible*/ = DownloadSpeedLabel.Visible = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 = null)
|
|
||||||
{
|
|
||||||
if (InvokeRequired)
|
|
||||||
{
|
|
||||||
BeginInvoke(new Action<string>(StatusText), text);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
text ??= i18N.Translate(StateExtension.GetStatusString(State));
|
|
||||||
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;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using Netch.Models;
|
using Netch.Models;
|
||||||
|
using Netch.Utils;
|
||||||
|
|
||||||
namespace Netch.Utils
|
namespace Netch.Forms
|
||||||
{
|
{
|
||||||
static class MessageBoxX
|
public static class MessageBoxX
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -34,11 +35,11 @@ namespace Netch.Utils
|
|||||||
};
|
};
|
||||||
|
|
||||||
return MessageBox.Show(
|
return MessageBox.Show(
|
||||||
owner: owner,
|
owner,
|
||||||
text: text,
|
text,
|
||||||
caption: i18N.Translate(title),
|
i18N.Translate(title),
|
||||||
buttons: confirm ? MessageBoxButtons.OKCancel : MessageBoxButtons.OK,
|
confirm ? MessageBoxButtons.OKCancel : MessageBoxButtons.OK,
|
||||||
icon: msgIcon);
|
msgIcon);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
113
Netch/Forms/SettingForm.Designer.cs
generated
113
Netch/Forms/SettingForm.Designer.cs
generated
@@ -49,9 +49,10 @@ namespace Netch.Forms
|
|||||||
this.ResolveServerHostnameCheckBox = new System.Windows.Forms.CheckBox();
|
this.ResolveServerHostnameCheckBox = new System.Windows.Forms.CheckBox();
|
||||||
this.ProfileCountLabel = new System.Windows.Forms.Label();
|
this.ProfileCountLabel = new System.Windows.Forms.Label();
|
||||||
this.ProfileCountTextBox = new System.Windows.Forms.TextBox();
|
this.ProfileCountTextBox = new System.Windows.Forms.TextBox();
|
||||||
this.TcpingAtStartedCheckBox = new System.Windows.Forms.CheckBox();
|
this.StartedPingLabel = new System.Windows.Forms.Label();
|
||||||
this.DetectionIntervalLabel = new System.Windows.Forms.Label();
|
this.DetectionTickLabel = new System.Windows.Forms.Label();
|
||||||
this.DetectionIntervalTextBox = new System.Windows.Forms.TextBox();
|
this.StartedPingIntervalTextBox = new System.Windows.Forms.TextBox();
|
||||||
|
this.DetectionTickTextBox = new System.Windows.Forms.TextBox();
|
||||||
this.STUNServerLabel = new System.Windows.Forms.Label();
|
this.STUNServerLabel = new System.Windows.Forms.Label();
|
||||||
this.STUN_ServerComboBox = new System.Windows.Forms.ComboBox();
|
this.STUN_ServerComboBox = new System.Windows.Forms.ComboBox();
|
||||||
this.AclLabel = new System.Windows.Forms.Label();
|
this.AclLabel = new System.Windows.Forms.Label();
|
||||||
@@ -105,7 +106,7 @@ namespace Netch.Forms
|
|||||||
this.RunAtStartupCheckBox = new System.Windows.Forms.CheckBox();
|
this.RunAtStartupCheckBox = new System.Windows.Forms.CheckBox();
|
||||||
this.CheckUpdateWhenOpenedCheckBox = new System.Windows.Forms.CheckBox();
|
this.CheckUpdateWhenOpenedCheckBox = new System.Windows.Forms.CheckBox();
|
||||||
this.CheckBetaUpdateCheckBox = new System.Windows.Forms.CheckBox();
|
this.CheckBetaUpdateCheckBox = new System.Windows.Forms.CheckBox();
|
||||||
this.UpdateSubscribeatWhenOpenedCheckBox = new System.Windows.Forms.CheckBox();
|
this.UpdateServersWhenOpenedCheckBox = new System.Windows.Forms.CheckBox();
|
||||||
this.AioDNSTabPage = new System.Windows.Forms.TabPage();
|
this.AioDNSTabPage = new System.Windows.Forms.TabPage();
|
||||||
this.AioDNSRuleRuleLabel = new System.Windows.Forms.Label();
|
this.AioDNSRuleRuleLabel = new System.Windows.Forms.Label();
|
||||||
this.AioDNSRulePathTextBox = new System.Windows.Forms.TextBox();
|
this.AioDNSRulePathTextBox = new System.Windows.Forms.TextBox();
|
||||||
@@ -154,9 +155,10 @@ namespace Netch.Forms
|
|||||||
this.GeneralTabPage.Controls.Add(this.ResolveServerHostnameCheckBox);
|
this.GeneralTabPage.Controls.Add(this.ResolveServerHostnameCheckBox);
|
||||||
this.GeneralTabPage.Controls.Add(this.ProfileCountLabel);
|
this.GeneralTabPage.Controls.Add(this.ProfileCountLabel);
|
||||||
this.GeneralTabPage.Controls.Add(this.ProfileCountTextBox);
|
this.GeneralTabPage.Controls.Add(this.ProfileCountTextBox);
|
||||||
this.GeneralTabPage.Controls.Add(this.TcpingAtStartedCheckBox);
|
this.GeneralTabPage.Controls.Add(this.StartedPingLabel);
|
||||||
this.GeneralTabPage.Controls.Add(this.DetectionIntervalLabel);
|
this.GeneralTabPage.Controls.Add(this.DetectionTickLabel);
|
||||||
this.GeneralTabPage.Controls.Add(this.DetectionIntervalTextBox);
|
this.GeneralTabPage.Controls.Add(this.StartedPingIntervalTextBox);
|
||||||
|
this.GeneralTabPage.Controls.Add(this.DetectionTickTextBox);
|
||||||
this.GeneralTabPage.Controls.Add(this.STUNServerLabel);
|
this.GeneralTabPage.Controls.Add(this.STUNServerLabel);
|
||||||
this.GeneralTabPage.Controls.Add(this.STUN_ServerComboBox);
|
this.GeneralTabPage.Controls.Add(this.STUN_ServerComboBox);
|
||||||
this.GeneralTabPage.Controls.Add(this.AclLabel);
|
this.GeneralTabPage.Controls.Add(this.AclLabel);
|
||||||
@@ -173,7 +175,7 @@ namespace Netch.Forms
|
|||||||
// ServerPingTypeLabel
|
// ServerPingTypeLabel
|
||||||
//
|
//
|
||||||
this.ServerPingTypeLabel.AutoSize = true;
|
this.ServerPingTypeLabel.AutoSize = true;
|
||||||
this.ServerPingTypeLabel.Location = new System.Drawing.Point(217, 160);
|
this.ServerPingTypeLabel.Location = new System.Drawing.Point(267, 66);
|
||||||
this.ServerPingTypeLabel.Name = "ServerPingTypeLabel";
|
this.ServerPingTypeLabel.Name = "ServerPingTypeLabel";
|
||||||
this.ServerPingTypeLabel.Size = new System.Drawing.Size(89, 12);
|
this.ServerPingTypeLabel.Size = new System.Drawing.Size(89, 12);
|
||||||
this.ServerPingTypeLabel.TabIndex = 16;
|
this.ServerPingTypeLabel.TabIndex = 16;
|
||||||
@@ -182,26 +184,24 @@ namespace Netch.Forms
|
|||||||
// TCPingRadioBtn
|
// TCPingRadioBtn
|
||||||
//
|
//
|
||||||
this.TCPingRadioBtn.AutoSize = true;
|
this.TCPingRadioBtn.AutoSize = true;
|
||||||
this.TCPingRadioBtn.Location = new System.Drawing.Point(376, 158);
|
this.TCPingRadioBtn.Location = new System.Drawing.Point(332, 85);
|
||||||
this.TCPingRadioBtn.Name = "TCPingRadioBtn";
|
this.TCPingRadioBtn.Name = "TCPingRadioBtn";
|
||||||
this.TCPingRadioBtn.Size = new System.Drawing.Size(59, 16);
|
this.TCPingRadioBtn.Size = new System.Drawing.Size(59, 16);
|
||||||
this.TCPingRadioBtn.TabIndex = 15;
|
this.TCPingRadioBtn.TabIndex = 15;
|
||||||
this.TCPingRadioBtn.TabStop = true;
|
this.TCPingRadioBtn.TabStop = true;
|
||||||
this.TCPingRadioBtn.Text = "TCPing";
|
this.TCPingRadioBtn.Text = "TCPing";
|
||||||
this.TCPingRadioBtn.UseVisualStyleBackColor = true;
|
this.TCPingRadioBtn.UseVisualStyleBackColor = true;
|
||||||
this.TCPingRadioBtn.CheckedChanged += new System.EventHandler(this.TCPingRadioBtn_CheckedChanged);
|
|
||||||
//
|
//
|
||||||
// ICMPingRadioBtn
|
// ICMPingRadioBtn
|
||||||
//
|
//
|
||||||
this.ICMPingRadioBtn.AutoSize = true;
|
this.ICMPingRadioBtn.AutoSize = true;
|
||||||
this.ICMPingRadioBtn.Location = new System.Drawing.Point(312, 158);
|
this.ICMPingRadioBtn.Location = new System.Drawing.Point(268, 85);
|
||||||
this.ICMPingRadioBtn.Name = "ICMPingRadioBtn";
|
this.ICMPingRadioBtn.Name = "ICMPingRadioBtn";
|
||||||
this.ICMPingRadioBtn.Size = new System.Drawing.Size(65, 16);
|
this.ICMPingRadioBtn.Size = new System.Drawing.Size(65, 16);
|
||||||
this.ICMPingRadioBtn.TabIndex = 14;
|
this.ICMPingRadioBtn.TabIndex = 14;
|
||||||
this.ICMPingRadioBtn.TabStop = true;
|
this.ICMPingRadioBtn.TabStop = true;
|
||||||
this.ICMPingRadioBtn.Text = "ICMPing";
|
this.ICMPingRadioBtn.Text = "ICMPing";
|
||||||
this.ICMPingRadioBtn.UseVisualStyleBackColor = true;
|
this.ICMPingRadioBtn.UseVisualStyleBackColor = true;
|
||||||
this.ICMPingRadioBtn.CheckedChanged += new System.EventHandler(this.ICMPingRadioBtn_CheckedChanged);
|
|
||||||
//
|
//
|
||||||
// PortGroupBox
|
// PortGroupBox
|
||||||
//
|
//
|
||||||
@@ -318,32 +318,39 @@ namespace Netch.Forms
|
|||||||
this.ProfileCountTextBox.TabIndex = 4;
|
this.ProfileCountTextBox.TabIndex = 4;
|
||||||
this.ProfileCountTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
this.ProfileCountTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||||
//
|
//
|
||||||
// TcpingAtStartedCheckBox
|
// StartedPingLabel
|
||||||
//
|
//
|
||||||
this.TcpingAtStartedCheckBox.AutoSize = true;
|
this.StartedPingLabel.AutoSize = true;
|
||||||
this.TcpingAtStartedCheckBox.Location = new System.Drawing.Point(15, 186);
|
this.StartedPingLabel.Location = new System.Drawing.Point(12, 187);
|
||||||
this.TcpingAtStartedCheckBox.Name = "TcpingAtStartedCheckBox";
|
this.StartedPingLabel.Name = "StartedPingLabel";
|
||||||
this.TcpingAtStartedCheckBox.Size = new System.Drawing.Size(156, 16);
|
this.StartedPingLabel.Size = new System.Drawing.Size(137, 12);
|
||||||
this.TcpingAtStartedCheckBox.TabIndex = 5;
|
this.StartedPingLabel.TabIndex = 5;
|
||||||
this.TcpingAtStartedCheckBox.Text = "Delay test after start";
|
this.StartedPingLabel.Text = "Delay test after start";
|
||||||
this.TcpingAtStartedCheckBox.UseVisualStyleBackColor = true;
|
|
||||||
//
|
//
|
||||||
// DetectionIntervalLabel
|
// DetectionTickLabel
|
||||||
//
|
//
|
||||||
this.DetectionIntervalLabel.AutoSize = true;
|
this.DetectionTickLabel.AutoSize = true;
|
||||||
this.DetectionIntervalLabel.Location = new System.Drawing.Point(217, 187);
|
this.DetectionTickLabel.Location = new System.Drawing.Point(225, 160);
|
||||||
this.DetectionIntervalLabel.Name = "DetectionIntervalLabel";
|
this.DetectionTickLabel.Name = "DetectionTickLabel";
|
||||||
this.DetectionIntervalLabel.Size = new System.Drawing.Size(143, 12);
|
this.DetectionTickLabel.Size = new System.Drawing.Size(119, 12);
|
||||||
this.DetectionIntervalLabel.TabIndex = 6;
|
this.DetectionTickLabel.TabIndex = 6;
|
||||||
this.DetectionIntervalLabel.Text = "Detection interval(sec)";
|
this.DetectionTickLabel.Text = "Detection Tick(sec)";
|
||||||
//
|
//
|
||||||
// DetectionIntervalTextBox
|
// StartedPingIntervalTextBox
|
||||||
//
|
//
|
||||||
this.DetectionIntervalTextBox.Location = new System.Drawing.Point(366, 184);
|
this.StartedPingIntervalTextBox.Location = new System.Drawing.Point(177, 184);
|
||||||
this.DetectionIntervalTextBox.Name = "DetectionIntervalTextBox";
|
this.StartedPingIntervalTextBox.Name = "StartedPingIntervalTextBox";
|
||||||
this.DetectionIntervalTextBox.Size = new System.Drawing.Size(68, 21);
|
this.StartedPingIntervalTextBox.Size = new System.Drawing.Size(68, 21);
|
||||||
this.DetectionIntervalTextBox.TabIndex = 7;
|
this.StartedPingIntervalTextBox.TabIndex = 7;
|
||||||
this.DetectionIntervalTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
this.StartedPingIntervalTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||||
|
//
|
||||||
|
// DetectionTickTextBox
|
||||||
|
//
|
||||||
|
this.DetectionTickTextBox.Location = new System.Drawing.Point(366, 157);
|
||||||
|
this.DetectionTickTextBox.Name = "DetectionTickTextBox";
|
||||||
|
this.DetectionTickTextBox.Size = new System.Drawing.Size(68, 21);
|
||||||
|
this.DetectionTickTextBox.TabIndex = 7;
|
||||||
|
this.DetectionTickTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||||
//
|
//
|
||||||
// STUNServerLabel
|
// STUNServerLabel
|
||||||
//
|
//
|
||||||
@@ -375,7 +382,7 @@ namespace Netch.Forms
|
|||||||
//
|
//
|
||||||
this.AclAddrTextBox.Location = new System.Drawing.Point(120, 245);
|
this.AclAddrTextBox.Location = new System.Drawing.Point(120, 245);
|
||||||
this.AclAddrTextBox.Name = "AclAddrTextBox";
|
this.AclAddrTextBox.Name = "AclAddrTextBox";
|
||||||
this.AclAddrTextBox.Size = new System.Drawing.Size(315, 21);
|
this.AclAddrTextBox.Size = new System.Drawing.Size(314, 21);
|
||||||
this.AclAddrTextBox.TabIndex = 11;
|
this.AclAddrTextBox.TabIndex = 11;
|
||||||
this.AclAddrTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
this.AclAddrTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||||
//
|
//
|
||||||
@@ -444,7 +451,6 @@ namespace Netch.Forms
|
|||||||
this.ModifySystemDNSCheckBox.TabIndex = 0;
|
this.ModifySystemDNSCheckBox.TabIndex = 0;
|
||||||
this.ModifySystemDNSCheckBox.Text = "Modify System DNS";
|
this.ModifySystemDNSCheckBox.Text = "Modify System DNS";
|
||||||
this.ModifySystemDNSCheckBox.UseVisualStyleBackColor = true;
|
this.ModifySystemDNSCheckBox.UseVisualStyleBackColor = true;
|
||||||
this.ModifySystemDNSCheckBox.CheckedChanged += new System.EventHandler(this.ModifySystemDNSCheckBox_CheckedChanged);
|
|
||||||
//
|
//
|
||||||
// ModifiedDNSLabel
|
// ModifiedDNSLabel
|
||||||
//
|
//
|
||||||
@@ -457,6 +463,7 @@ namespace Netch.Forms
|
|||||||
//
|
//
|
||||||
// ModifiedDNSTextBox
|
// ModifiedDNSTextBox
|
||||||
//
|
//
|
||||||
|
this.ModifiedDNSTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", this.ModifySystemDNSCheckBox, "Checked", true));
|
||||||
this.ModifiedDNSTextBox.Location = new System.Drawing.Point(264, 14);
|
this.ModifiedDNSTextBox.Location = new System.Drawing.Point(264, 14);
|
||||||
this.ModifiedDNSTextBox.Name = "ModifiedDNSTextBox";
|
this.ModifiedDNSTextBox.Name = "ModifiedDNSTextBox";
|
||||||
this.ModifiedDNSTextBox.Size = new System.Drawing.Size(194, 21);
|
this.ModifiedDNSTextBox.Size = new System.Drawing.Size(194, 21);
|
||||||
@@ -472,7 +479,6 @@ namespace Netch.Forms
|
|||||||
this.RedirectorSSCheckBox.TabIndex = 0;
|
this.RedirectorSSCheckBox.TabIndex = 0;
|
||||||
this.RedirectorSSCheckBox.Text = "Redirector SS";
|
this.RedirectorSSCheckBox.Text = "Redirector SS";
|
||||||
this.RedirectorSSCheckBox.UseVisualStyleBackColor = true;
|
this.RedirectorSSCheckBox.UseVisualStyleBackColor = true;
|
||||||
this.RedirectorSSCheckBox.CheckedChanged += new System.EventHandler(this.ModifySystemDNSCheckBox_CheckedChanged);
|
|
||||||
//
|
//
|
||||||
// TAPTabPage
|
// TAPTabPage
|
||||||
//
|
//
|
||||||
@@ -569,6 +575,7 @@ namespace Netch.Forms
|
|||||||
//
|
//
|
||||||
// TUNTAPDNSTextBox
|
// TUNTAPDNSTextBox
|
||||||
//
|
//
|
||||||
|
this.TUNTAPDNSTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", this.UseCustomDNSCheckBox, "Checked", true));
|
||||||
this.TUNTAPDNSTextBox.Location = new System.Drawing.Point(120, 110);
|
this.TUNTAPDNSTextBox.Location = new System.Drawing.Point(120, 110);
|
||||||
this.TUNTAPDNSTextBox.Name = "TUNTAPDNSTextBox";
|
this.TUNTAPDNSTextBox.Name = "TUNTAPDNSTextBox";
|
||||||
this.TUNTAPDNSTextBox.Size = new System.Drawing.Size(294, 21);
|
this.TUNTAPDNSTextBox.Size = new System.Drawing.Size(294, 21);
|
||||||
@@ -807,7 +814,7 @@ namespace Netch.Forms
|
|||||||
this.OtherTabPage.Controls.Add(this.RunAtStartupCheckBox);
|
this.OtherTabPage.Controls.Add(this.RunAtStartupCheckBox);
|
||||||
this.OtherTabPage.Controls.Add(this.CheckUpdateWhenOpenedCheckBox);
|
this.OtherTabPage.Controls.Add(this.CheckUpdateWhenOpenedCheckBox);
|
||||||
this.OtherTabPage.Controls.Add(this.CheckBetaUpdateCheckBox);
|
this.OtherTabPage.Controls.Add(this.CheckBetaUpdateCheckBox);
|
||||||
this.OtherTabPage.Controls.Add(this.UpdateSubscribeatWhenOpenedCheckBox);
|
this.OtherTabPage.Controls.Add(this.UpdateServersWhenOpenedCheckBox);
|
||||||
this.OtherTabPage.Location = new System.Drawing.Point(4, 25);
|
this.OtherTabPage.Location = new System.Drawing.Point(4, 25);
|
||||||
this.OtherTabPage.Name = "OtherTabPage";
|
this.OtherTabPage.Name = "OtherTabPage";
|
||||||
this.OtherTabPage.Padding = new System.Windows.Forms.Padding(3);
|
this.OtherTabPage.Padding = new System.Windows.Forms.Padding(3);
|
||||||
@@ -890,16 +897,16 @@ namespace Netch.Forms
|
|||||||
this.CheckBetaUpdateCheckBox.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
this.CheckBetaUpdateCheckBox.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||||
this.CheckBetaUpdateCheckBox.UseVisualStyleBackColor = true;
|
this.CheckBetaUpdateCheckBox.UseVisualStyleBackColor = true;
|
||||||
//
|
//
|
||||||
// UpdateSubscribeatWhenOpenedCheckBox
|
// UpdateServersWhenOpenedCheckBox
|
||||||
//
|
//
|
||||||
this.UpdateSubscribeatWhenOpenedCheckBox.AutoSize = true;
|
this.UpdateServersWhenOpenedCheckBox.AutoSize = true;
|
||||||
this.UpdateSubscribeatWhenOpenedCheckBox.Location = new System.Drawing.Point(200, 94);
|
this.UpdateServersWhenOpenedCheckBox.Location = new System.Drawing.Point(200, 94);
|
||||||
this.UpdateSubscribeatWhenOpenedCheckBox.Name = "UpdateSubscribeatWhenOpenedCheckBox";
|
this.UpdateServersWhenOpenedCheckBox.Name = "UpdateServersWhenOpenedCheckBox";
|
||||||
this.UpdateSubscribeatWhenOpenedCheckBox.Size = new System.Drawing.Size(204, 16);
|
this.UpdateServersWhenOpenedCheckBox.Size = new System.Drawing.Size(180, 16);
|
||||||
this.UpdateSubscribeatWhenOpenedCheckBox.TabIndex = 7;
|
this.UpdateServersWhenOpenedCheckBox.TabIndex = 7;
|
||||||
this.UpdateSubscribeatWhenOpenedCheckBox.Text = "Update subscribeat when opened";
|
this.UpdateServersWhenOpenedCheckBox.Text = "Update Servers when opened";
|
||||||
this.UpdateSubscribeatWhenOpenedCheckBox.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
this.UpdateServersWhenOpenedCheckBox.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||||
this.UpdateSubscribeatWhenOpenedCheckBox.UseVisualStyleBackColor = true;
|
this.UpdateServersWhenOpenedCheckBox.UseVisualStyleBackColor = true;
|
||||||
//
|
//
|
||||||
// AioDNSTabPage
|
// AioDNSTabPage
|
||||||
//
|
//
|
||||||
@@ -970,7 +977,7 @@ namespace Netch.Forms
|
|||||||
//
|
//
|
||||||
// ControlButton
|
// ControlButton
|
||||||
//
|
//
|
||||||
this.ControlButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
this.ControlButton.Anchor = ((System.Windows.Forms.AnchorStyles) ((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.ControlButton.Location = new System.Drawing.Point(397, 363);
|
this.ControlButton.Location = new System.Drawing.Point(397, 363);
|
||||||
this.ControlButton.Name = "ControlButton";
|
this.ControlButton.Name = "ControlButton";
|
||||||
this.ControlButton.Size = new System.Drawing.Size(75, 23);
|
this.ControlButton.Size = new System.Drawing.Size(75, 23);
|
||||||
@@ -1001,7 +1008,7 @@ namespace Netch.Forms
|
|||||||
this.ClientSize = new System.Drawing.Size(480, 400);
|
this.ClientSize = new System.Drawing.Size(480, 400);
|
||||||
this.Controls.Add(this.flowLayoutPanel1);
|
this.Controls.Add(this.flowLayoutPanel1);
|
||||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
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.MaximizeBox = false;
|
this.MaximizeBox = false;
|
||||||
this.Name = "SettingForm";
|
this.Name = "SettingForm";
|
||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||||
@@ -1028,8 +1035,8 @@ namespace Netch.Forms
|
|||||||
this.flowLayoutPanel1.ResumeLayout(false);
|
this.flowLayoutPanel1.ResumeLayout(false);
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
this.PerformLayout();
|
this.PerformLayout();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
private System.Windows.Forms.TextBox StartedPingIntervalTextBox;
|
||||||
private System.Windows.Forms.CheckBox NoProxyForTcpCheckBox;
|
private System.Windows.Forms.CheckBox NoProxyForTcpCheckBox;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -1067,7 +1074,7 @@ namespace Netch.Forms
|
|||||||
private System.Windows.Forms.Button ControlButton;
|
private System.Windows.Forms.Button ControlButton;
|
||||||
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
|
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
|
||||||
private System.Windows.Forms.TabPage OtherTabPage;
|
private System.Windows.Forms.TabPage OtherTabPage;
|
||||||
private System.Windows.Forms.CheckBox UpdateSubscribeatWhenOpenedCheckBox;
|
private System.Windows.Forms.CheckBox UpdateServersWhenOpenedCheckBox;
|
||||||
private System.Windows.Forms.CheckBox RunAtStartupCheckBox;
|
private System.Windows.Forms.CheckBox RunAtStartupCheckBox;
|
||||||
private System.Windows.Forms.CheckBox MinimizeWhenStartedCheckBox;
|
private System.Windows.Forms.CheckBox MinimizeWhenStartedCheckBox;
|
||||||
private System.Windows.Forms.CheckBox CheckBetaUpdateCheckBox;
|
private System.Windows.Forms.CheckBox CheckBetaUpdateCheckBox;
|
||||||
@@ -1079,9 +1086,9 @@ namespace Netch.Forms
|
|||||||
private System.Windows.Forms.ComboBox LanguageComboBox;
|
private System.Windows.Forms.ComboBox LanguageComboBox;
|
||||||
private System.Windows.Forms.TextBox AclAddrTextBox;
|
private System.Windows.Forms.TextBox AclAddrTextBox;
|
||||||
private System.Windows.Forms.Label AclLabel;
|
private System.Windows.Forms.Label AclLabel;
|
||||||
private System.Windows.Forms.Label DetectionIntervalLabel;
|
private System.Windows.Forms.Label DetectionTickLabel;
|
||||||
private System.Windows.Forms.TextBox DetectionIntervalTextBox;
|
private System.Windows.Forms.TextBox DetectionTickTextBox;
|
||||||
private System.Windows.Forms.CheckBox TcpingAtStartedCheckBox;
|
private System.Windows.Forms.Label StartedPingLabel;
|
||||||
private System.Windows.Forms.Label STUNServerLabel;
|
private System.Windows.Forms.Label STUNServerLabel;
|
||||||
private System.Windows.Forms.ComboBox STUN_ServerComboBox;
|
private System.Windows.Forms.ComboBox STUN_ServerComboBox;
|
||||||
private System.Windows.Forms.Label ProfileCountLabel;
|
private System.Windows.Forms.Label ProfileCountLabel;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using Netch.Utils;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
@@ -7,11 +6,15 @@ using System.Linq;
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
using Netch.Utils;
|
||||||
|
|
||||||
namespace Netch.Forms
|
namespace Netch.Forms
|
||||||
{
|
{
|
||||||
public partial class SettingForm : Form
|
public partial class SettingForm : Form
|
||||||
{
|
{
|
||||||
|
private readonly Dictionary<Control, Func<string, bool>> _checkActions = new();
|
||||||
|
|
||||||
|
private readonly Dictionary<Control, Action<Control>> _saveActions = new();
|
||||||
public SettingForm()
|
public SettingForm()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
@@ -19,7 +22,6 @@ namespace Netch.Forms
|
|||||||
InitValue();
|
InitValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void SettingForm_Load(object sender, EventArgs e)
|
private void SettingForm_Load(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
TUNTAPUseCustomDNSCheckBox_CheckedChanged(null, null);
|
TUNTAPUseCustomDNSCheckBox_CheckedChanged(null, null);
|
||||||
@@ -59,7 +61,7 @@ namespace Netch.Forms
|
|||||||
Global.Settings.ResolveServerHostname);
|
Global.Settings.ResolveServerHostname);
|
||||||
|
|
||||||
BindRadioBox(ICMPingRadioBtn,
|
BindRadioBox(ICMPingRadioBtn,
|
||||||
c => Global.Settings.ServerTCPing = c,
|
_ => { },
|
||||||
!Global.Settings.ServerTCPing);
|
!Global.Settings.ServerTCPing);
|
||||||
|
|
||||||
BindRadioBox(TCPingRadioBtn,
|
BindRadioBox(TCPingRadioBtn,
|
||||||
@@ -70,13 +72,14 @@ namespace Netch.Forms
|
|||||||
i => i > -1,
|
i => i > -1,
|
||||||
i => Global.Settings.ProfileCount = i,
|
i => Global.Settings.ProfileCount = i,
|
||||||
Global.Settings.ProfileCount);
|
Global.Settings.ProfileCount);
|
||||||
BindCheckBox(TcpingAtStartedCheckBox,
|
BindTextBox<int>(DetectionTickTextBox,
|
||||||
b => Global.Settings.StartedTcping = b,
|
|
||||||
Global.Settings.StartedTcping);
|
|
||||||
BindTextBox<int>(DetectionIntervalTextBox,
|
|
||||||
i => i >= 0,
|
i => i >= 0,
|
||||||
i => Global.Settings.StartedTcping_Interval = i,
|
i => Global.Settings.DetectionTick = i,
|
||||||
Global.Settings.StartedTcping_Interval);
|
Global.Settings.DetectionTick);
|
||||||
|
BindTextBox<int>(StartedPingIntervalTextBox,
|
||||||
|
_ => true,
|
||||||
|
i => Global.Settings.StartedPingInterval = i,
|
||||||
|
Global.Settings.StartedPingInterval);
|
||||||
|
|
||||||
InitSTUN();
|
InitSTUN();
|
||||||
|
|
||||||
@@ -97,8 +100,6 @@ namespace Netch.Forms
|
|||||||
b => Global.Settings.ModifySystemDNS = b,
|
b => Global.Settings.ModifySystemDNS = b,
|
||||||
Global.Settings.ModifySystemDNS);
|
Global.Settings.ModifySystemDNS);
|
||||||
|
|
||||||
ModifySystemDNSCheckBox_CheckedChanged(null, null);
|
|
||||||
|
|
||||||
BindTextBox(ModifiedDNSTextBox,
|
BindTextBox(ModifiedDNSTextBox,
|
||||||
s => DNS.TrySplit(s, out _, 2),
|
s => DNS.TrySplit(s, out _, 2),
|
||||||
s => Global.Settings.ModifiedDNS = s,
|
s => Global.Settings.ModifiedDNS = s,
|
||||||
@@ -135,7 +136,6 @@ namespace Netch.Forms
|
|||||||
BindCheckBox(UseCustomDNSCheckBox,
|
BindCheckBox(UseCustomDNSCheckBox,
|
||||||
b => { Global.Settings.TUNTAP.UseCustomDNS = b; },
|
b => { Global.Settings.TUNTAP.UseCustomDNS = b; },
|
||||||
Global.Settings.TUNTAP.UseCustomDNS);
|
Global.Settings.TUNTAP.UseCustomDNS);
|
||||||
TUNTAPUseCustomDNSCheckBox_CheckedChanged(null, null);
|
|
||||||
|
|
||||||
BindTextBox(TUNTAPDNSTextBox,
|
BindTextBox(TUNTAPDNSTextBox,
|
||||||
s => !UseCustomDNSCheckBox.Checked || DNS.TrySplit(s, out _, 2),
|
s => !UseCustomDNSCheckBox.Checked || DNS.TrySplit(s, out _, 2),
|
||||||
@@ -238,9 +238,9 @@ namespace Netch.Forms
|
|||||||
b => Global.Settings.CheckBetaUpdate = b,
|
b => Global.Settings.CheckBetaUpdate = b,
|
||||||
Global.Settings.CheckBetaUpdate);
|
Global.Settings.CheckBetaUpdate);
|
||||||
|
|
||||||
BindCheckBox(UpdateSubscribeatWhenOpenedCheckBox,
|
BindCheckBox(UpdateServersWhenOpenedCheckBox,
|
||||||
b => Global.Settings.UpdateSubscribeatWhenOpened = b,
|
b => Global.Settings.UpdateServersWhenOpened = b,
|
||||||
Global.Settings.UpdateSubscribeatWhenOpened);
|
Global.Settings.UpdateServersWhenOpened);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -266,21 +266,14 @@ namespace Netch.Forms
|
|||||||
|
|
||||||
private void TUNTAPUseCustomDNSCheckBox_CheckedChanged(object sender, EventArgs e)
|
private void TUNTAPUseCustomDNSCheckBox_CheckedChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
TUNTAPDNSTextBox.Enabled = UseCustomDNSCheckBox.Checked;
|
|
||||||
|
|
||||||
if (UseCustomDNSCheckBox.Checked)
|
if (UseCustomDNSCheckBox.Checked)
|
||||||
{
|
|
||||||
TUNTAPDNSTextBox.Text = Global.Settings.TUNTAP.DNS.Any()
|
TUNTAPDNSTextBox.Text = Global.Settings.TUNTAP.DNS.Any()
|
||||||
? DNS.Join(Global.Settings.TUNTAP.DNS)
|
? DNS.Join(Global.Settings.TUNTAP.DNS)
|
||||||
: "1.1.1.1";
|
: "1.1.1.1";
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
TUNTAPDNSTextBox.Text = "AioDNS";
|
TUNTAPDNSTextBox.Text = "AioDNS";
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void InitSTUN()
|
private void InitSTUN()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -317,9 +310,7 @@ namespace Netch.Forms
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!flag)
|
if (!flag)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -336,9 +327,7 @@ namespace Netch.Forms
|
|||||||
stunServer = stun[0];
|
stunServer = stun[0];
|
||||||
if (stun.Length > 1)
|
if (stun.Length > 1)
|
||||||
if (!ushort.TryParse(stun[1], out stunServerPort))
|
if (!ushort.TryParse(stun[1], out stunServerPort))
|
||||||
{
|
|
||||||
errFlag = true;
|
errFlag = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -356,9 +345,7 @@ namespace Netch.Forms
|
|||||||
#region Save
|
#region Save
|
||||||
|
|
||||||
foreach (var pair in _saveActions)
|
foreach (var pair in _saveActions)
|
||||||
{
|
|
||||||
pair.Value.Invoke(pair.Key);
|
pair.Value.Invoke(pair.Key);
|
||||||
}
|
|
||||||
|
|
||||||
Global.Settings.STUN_Server = stunServer;
|
Global.Settings.STUN_Server = stunServer;
|
||||||
Global.Settings.STUN_Server_Port = stunServerPort;
|
Global.Settings.STUN_Server_Port = stunServerPort;
|
||||||
@@ -427,23 +414,12 @@ namespace Netch.Forms
|
|||||||
private void BindCheckBox(CheckBox control, Action<bool> save, bool value)
|
private void BindCheckBox(CheckBox control, Action<bool> save, bool value)
|
||||||
{
|
{
|
||||||
control.Checked = value;
|
control.Checked = value;
|
||||||
_checkActions.Add(control, s => true);
|
_saveActions.Add(control, c => save.Invoke(((CheckBox) c).Checked));
|
||||||
_saveActions.Add(control, c => save.Invoke(((CheckBox)c).Checked));
|
|
||||||
}
|
}
|
||||||
private void BindRadioBox(RadioButton control, Action<bool> save, bool value)
|
private void BindRadioBox(RadioButton control, Action<bool> save, bool value)
|
||||||
{
|
{
|
||||||
control.Checked = value;
|
control.Checked = value;
|
||||||
_checkActions.Add(control, s => true);
|
_saveActions.Add(control, c => save.Invoke(((RadioButton) c).Checked));
|
||||||
_saveActions.Add(control, c => save.Invoke(((RadioButton)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)
|
|
||||||
{
|
|
||||||
ModifiedDNSTextBox.Enabled = ModifySystemDNSCheckBox.Checked;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void NoProxyForUdpCheckBox_CheckedChanged(object sender, EventArgs e)
|
private void NoProxyForUdpCheckBox_CheckedChanged(object sender, EventArgs e)
|
||||||
@@ -455,15 +431,5 @@ namespace Netch.Forms
|
|||||||
{
|
{
|
||||||
if (NoProxyForTcpCheckBox.Checked) NoProxyForUdpCheckBox.Checked = false;
|
if (NoProxyForTcpCheckBox.Checked) NoProxyForUdpCheckBox.Checked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ICMPingRadioBtn_CheckedChanged(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
if (ICMPingRadioBtn.Checked) TCPingRadioBtn.Checked = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void TCPingRadioBtn_CheckedChanged(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
if (TCPingRadioBtn.Checked) ICMPingRadioBtn.Checked = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
65
Netch/Forms/SubscribeForm.Designer.cs
generated
65
Netch/Forms/SubscribeForm.Designer.cs
generated
@@ -32,7 +32,7 @@
|
|||||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SubscribeForm));
|
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SubscribeForm));
|
||||||
this.AddSubscriptionBox = new System.Windows.Forms.GroupBox();
|
this.AddSubscriptionBox = new System.Windows.Forms.GroupBox();
|
||||||
this.UserAgentTextBox = new System.Windows.Forms.TextBox();
|
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.AddButton = new System.Windows.Forms.Button();
|
||||||
this.UserAgentLabel = new System.Windows.Forms.Label();
|
this.UserAgentLabel = new System.Windows.Forms.Label();
|
||||||
this.LinkTextBox = new System.Windows.Forms.TextBox();
|
this.LinkTextBox = new System.Windows.Forms.TextBox();
|
||||||
@@ -48,19 +48,16 @@
|
|||||||
this.DeleteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
this.DeleteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.deleteServerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
this.deleteServerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.CopyLinkToolStripMenuItem = 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.MainTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
|
||||||
this.ControlsPanel = new System.Windows.Forms.Panel();
|
|
||||||
this.AddSubscriptionBox.SuspendLayout();
|
this.AddSubscriptionBox.SuspendLayout();
|
||||||
this.pContextMenuStrip.SuspendLayout();
|
this.pContextMenuStrip.SuspendLayout();
|
||||||
this.MainTableLayoutPanel.SuspendLayout();
|
this.MainTableLayoutPanel.SuspendLayout();
|
||||||
this.ControlsPanel.SuspendLayout();
|
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// AddSubscriptionBox
|
// AddSubscriptionBox
|
||||||
//
|
//
|
||||||
this.AddSubscriptionBox.Controls.Add(this.UserAgentTextBox);
|
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.AddButton);
|
||||||
this.AddSubscriptionBox.Controls.Add(this.UserAgentLabel);
|
this.AddSubscriptionBox.Controls.Add(this.UserAgentLabel);
|
||||||
this.AddSubscriptionBox.Controls.Add(this.LinkTextBox);
|
this.AddSubscriptionBox.Controls.Add(this.LinkTextBox);
|
||||||
@@ -68,9 +65,9 @@
|
|||||||
this.AddSubscriptionBox.Controls.Add(this.RemarkTextBox);
|
this.AddSubscriptionBox.Controls.Add(this.RemarkTextBox);
|
||||||
this.AddSubscriptionBox.Controls.Add(this.RemarkLabel);
|
this.AddSubscriptionBox.Controls.Add(this.RemarkLabel);
|
||||||
this.AddSubscriptionBox.Dock = System.Windows.Forms.DockStyle.Fill;
|
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.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.TabIndex = 1;
|
||||||
this.AddSubscriptionBox.TabStop = false;
|
this.AddSubscriptionBox.TabStop = false;
|
||||||
//
|
//
|
||||||
@@ -81,15 +78,15 @@
|
|||||||
this.UserAgentTextBox.Size = new System.Drawing.Size(545, 23);
|
this.UserAgentTextBox.Size = new System.Drawing.Size(545, 23);
|
||||||
this.UserAgentTextBox.TabIndex = 6;
|
this.UserAgentTextBox.TabIndex = 6;
|
||||||
//
|
//
|
||||||
// ClearButton
|
// UnselectButton
|
||||||
//
|
//
|
||||||
this.ClearButton.Location = new System.Drawing.Point(448, 103);
|
this.UnselectButton.Location = new System.Drawing.Point(448, 103);
|
||||||
this.ClearButton.Name = "ClearButton";
|
this.UnselectButton.Name = "UnselectButton";
|
||||||
this.ClearButton.Size = new System.Drawing.Size(87, 26);
|
this.UnselectButton.Size = new System.Drawing.Size(87, 26);
|
||||||
this.ClearButton.TabIndex = 7;
|
this.UnselectButton.TabIndex = 7;
|
||||||
this.ClearButton.Text = "Unselect";
|
this.UnselectButton.Text = "Unselect";
|
||||||
this.ClearButton.UseVisualStyleBackColor = true;
|
this.UnselectButton.UseVisualStyleBackColor = true;
|
||||||
this.ClearButton.Click += new System.EventHandler(this.ClearButton_Click);
|
this.UnselectButton.Click += new System.EventHandler(this.UnselectButton_Click);
|
||||||
//
|
//
|
||||||
// AddButton
|
// AddButton
|
||||||
//
|
//
|
||||||
@@ -97,7 +94,7 @@
|
|||||||
this.AddButton.Name = "AddButton";
|
this.AddButton.Name = "AddButton";
|
||||||
this.AddButton.Size = new System.Drawing.Size(113, 26);
|
this.AddButton.Size = new System.Drawing.Size(113, 26);
|
||||||
this.AddButton.TabIndex = 7;
|
this.AddButton.TabIndex = 7;
|
||||||
this.AddButton.Text = "Add / Modify";
|
this.AddButton.Text = "Add";
|
||||||
this.AddButton.UseVisualStyleBackColor = true;
|
this.AddButton.UseVisualStyleBackColor = true;
|
||||||
this.AddButton.Click += new System.EventHandler(this.AddButton_Click);
|
this.AddButton.Click += new System.EventHandler(this.AddButton_Click);
|
||||||
//
|
//
|
||||||
@@ -156,7 +153,7 @@
|
|||||||
this.SubscribeLinkListView.Location = new System.Drawing.Point(8, 8);
|
this.SubscribeLinkListView.Location = new System.Drawing.Point(8, 8);
|
||||||
this.SubscribeLinkListView.MultiSelect = false;
|
this.SubscribeLinkListView.MultiSelect = false;
|
||||||
this.SubscribeLinkListView.Name = "SubscribeLinkListView";
|
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.TabIndex = 0;
|
||||||
this.SubscribeLinkListView.UseCompatibleStateImageBehavior = false;
|
this.SubscribeLinkListView.UseCompatibleStateImageBehavior = false;
|
||||||
this.SubscribeLinkListView.View = System.Windows.Forms.View.Details;
|
this.SubscribeLinkListView.View = System.Windows.Forms.View.Details;
|
||||||
@@ -213,44 +210,23 @@
|
|||||||
this.CopyLinkToolStripMenuItem.Text = "CopyLink";
|
this.CopyLinkToolStripMenuItem.Text = "CopyLink";
|
||||||
this.CopyLinkToolStripMenuItem.Click += new System.EventHandler(this.CopyLinkToolStripMenuItem_Click);
|
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
|
// MainTableLayoutPanel
|
||||||
//
|
//
|
||||||
this.MainTableLayoutPanel.ColumnCount = 1;
|
this.MainTableLayoutPanel.ColumnCount = 1;
|
||||||
this.MainTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
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.SubscribeLinkListView, 0, 0);
|
||||||
this.MainTableLayoutPanel.Controls.Add(this.AddSubscriptionBox, 0, 1);
|
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.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
this.MainTableLayoutPanel.Location = new System.Drawing.Point(0, 0);
|
this.MainTableLayoutPanel.Location = new System.Drawing.Point(0, 0);
|
||||||
this.MainTableLayoutPanel.Name = "MainTableLayoutPanel";
|
this.MainTableLayoutPanel.Name = "MainTableLayoutPanel";
|
||||||
this.MainTableLayoutPanel.Padding = new System.Windows.Forms.Padding(5);
|
this.MainTableLayoutPanel.Padding = new System.Windows.Forms.Padding(5);
|
||||||
this.MainTableLayoutPanel.RowCount = 3;
|
this.MainTableLayoutPanel.RowCount = 2;
|
||||||
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, 62.99213F));
|
||||||
this.MainTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 41.64223F));
|
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.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 27F));
|
||||||
this.MainTableLayoutPanel.Size = new System.Drawing.Size(684, 391);
|
this.MainTableLayoutPanel.Size = new System.Drawing.Size(684, 391);
|
||||||
this.MainTableLayoutPanel.TabIndex = 11;
|
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
|
// SubscribeForm
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
|
||||||
@@ -266,20 +242,16 @@
|
|||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||||
this.Text = "Subscribe";
|
this.Text = "Subscribe";
|
||||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.SubscribeForm_FormClosing);
|
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.SubscribeForm_FormClosing);
|
||||||
this.Load += new System.EventHandler(this.SubscribeForm_Load);
|
|
||||||
this.AddSubscriptionBox.ResumeLayout(false);
|
this.AddSubscriptionBox.ResumeLayout(false);
|
||||||
this.AddSubscriptionBox.PerformLayout();
|
this.AddSubscriptionBox.PerformLayout();
|
||||||
this.pContextMenuStrip.ResumeLayout(false);
|
this.pContextMenuStrip.ResumeLayout(false);
|
||||||
this.MainTableLayoutPanel.ResumeLayout(false);
|
this.MainTableLayoutPanel.ResumeLayout(false);
|
||||||
this.ControlsPanel.ResumeLayout(false);
|
|
||||||
this.ControlsPanel.PerformLayout();
|
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
}
|
}
|
||||||
private System.Windows.Forms.ColumnHeader EnableColumnHeader;
|
private System.Windows.Forms.ColumnHeader EnableColumnHeader;
|
||||||
|
|
||||||
private System.Windows.Forms.Panel ControlsPanel;
|
|
||||||
private System.Windows.Forms.TableLayoutPanel MainTableLayoutPanel;
|
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.GroupBox AddSubscriptionBox;
|
||||||
private System.Windows.Forms.Label RemarkLabel;
|
private System.Windows.Forms.Label RemarkLabel;
|
||||||
private System.Windows.Forms.TextBox LinkTextBox;
|
private System.Windows.Forms.TextBox LinkTextBox;
|
||||||
@@ -295,7 +267,6 @@
|
|||||||
private System.Windows.Forms.Label UserAgentLabel;
|
private System.Windows.Forms.Label UserAgentLabel;
|
||||||
private System.Windows.Forms.TextBox UserAgentTextBox;
|
private System.Windows.Forms.TextBox UserAgentTextBox;
|
||||||
private System.Windows.Forms.ColumnHeader UserAgentHeader;
|
private System.Windows.Forms.ColumnHeader UserAgentHeader;
|
||||||
private System.Windows.Forms.CheckBox UseSelectedServerCheckBox;
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|||||||
@@ -8,88 +8,65 @@ namespace Netch.Forms
|
|||||||
{
|
{
|
||||||
public partial class SubscribeForm : Form
|
public partial class SubscribeForm : Form
|
||||||
{
|
{
|
||||||
private int _editingIndex = -1;
|
|
||||||
|
|
||||||
public SubscribeForm()
|
public SubscribeForm()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
|
||||||
|
|
||||||
public void InitSubscribeLink()
|
|
||||||
{
|
|
||||||
SubscribeLinkListView.Items.Clear();
|
|
||||||
|
|
||||||
foreach (var item in Global.Settings.SubscribeLink)
|
|
||||||
{
|
|
||||||
var viewItem = new ListViewItem(new[]
|
|
||||||
{
|
|
||||||
"",
|
|
||||||
item.Remark,
|
|
||||||
item.Link,
|
|
||||||
!string.IsNullOrEmpty(item.UserAgent) ? item.UserAgent : WebUtil.DefaultUserAgent
|
|
||||||
});
|
|
||||||
viewItem.Checked = item.Enable;
|
|
||||||
SubscribeLinkListView.Items.Add(viewItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SubscribeForm_Load(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
i18N.TranslateForm(this);
|
i18N.TranslateForm(this);
|
||||||
i18N.TranslateForm(pContextMenuStrip);
|
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();
|
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)
|
private void SubscribeForm_FormClosing(object sender, FormClosingEventArgs e)
|
||||||
{
|
{
|
||||||
Configuration.Save();
|
Configuration.Save();
|
||||||
Global.Settings.UseProxyToUpdateSubscription = UseSelectedServerCheckBox.Checked;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CopyLinkToolStripMenuItem_Click(object sender, EventArgs e)
|
#endregion
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DeleteToolStripMenuItem_Click(object sender, EventArgs e)
|
#region EditBox
|
||||||
{
|
|
||||||
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];
|
|
||||||
|
|
||||||
DeleteServersInGroup(item.SubItems[0].Text);
|
private void UnselectButton_Click(object sender, EventArgs e)
|
||||||
Global.Settings.SubscribeLink.RemoveAt(item.Index);
|
{
|
||||||
SubscribeLinkListView.Items.Remove(item);
|
ResetEditingGroup();
|
||||||
ResetEditingGroup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddButton_Click(object sender, EventArgs e)
|
private void AddButton_Click(object sender, EventArgs e)
|
||||||
@@ -112,7 +89,7 @@ namespace Netch.Forms
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_editingIndex == -1)
|
if (SelectedIndex == -1)
|
||||||
{
|
{
|
||||||
if (Global.Settings.SubscribeLink.Any(link => link.Remark.Equals(RemarkTextBox.Text)))
|
if (Global.Settings.SubscribeLink.Any(link => link.Remark.Equals(RemarkTextBox.Text)))
|
||||||
{
|
{
|
||||||
@@ -130,126 +107,107 @@ namespace Netch.Forms
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var target = Global.Settings.SubscribeLink[_editingIndex];
|
var subscribeLink = Global.Settings.SubscribeLink[SelectedIndex];
|
||||||
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);
|
|
||||||
}
|
|
||||||
ListViewItem listViewItem = SubscribeLinkListView.Items[_editingIndex];
|
|
||||||
|
|
||||||
target.Enable = listViewItem.Checked;
|
RenameServers(subscribeLink.Remark, RemarkTextBox.Text);
|
||||||
target.Link = LinkTextBox.Text;
|
subscribeLink.Link = LinkTextBox.Text;
|
||||||
target.Remark = RemarkTextBox.Text;
|
subscribeLink.Remark = RemarkTextBox.Text;
|
||||||
target.UserAgent = UserAgentTextBox.Text;
|
subscribeLink.UserAgent = UserAgentTextBox.Text;
|
||||||
}
|
}
|
||||||
|
|
||||||
Configuration.Save();
|
MessageBoxX.Show(i18N.Translate("Saved"));
|
||||||
Global.Settings.UseProxyToUpdateSubscription = UseSelectedServerCheckBox.Checked;
|
|
||||||
// MessageBoxX.Show(i18N.Translate("Saved"));
|
|
||||||
|
|
||||||
ResetEditingGroup();
|
|
||||||
|
|
||||||
InitSubscribeLink();
|
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);
|
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)
|
foreach (var server in Global.Settings.Server.Where(server => server.Group == oldGroup))
|
||||||
{
|
server.Group = newGroup;
|
||||||
if (server.Group == oldGroup)
|
|
||||||
{
|
|
||||||
server.Group = newGroup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
private void InitSubscribeLink()
|
||||||
/// 订阅列表选中节点
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender"></param>
|
|
||||||
/// <param name="e"></param>
|
|
||||||
private void SubscribeLinkListView_SelectedIndexChanged(object sender, EventArgs e)
|
|
||||||
{
|
{
|
||||||
var listView = (ListView) sender;
|
SubscribeLinkListView.Items.Clear();
|
||||||
if (listView.SelectedItems.Count == 0)
|
|
||||||
{
|
|
||||||
// 重置
|
|
||||||
ResetEditingGroup();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_editingIndex = listView.SelectedItems[0].Index;
|
|
||||||
|
|
||||||
ListViewItem target = SubscribeLinkListView.Items[_editingIndex];
|
foreach (var item in Global.Settings.SubscribeLink)
|
||||||
|
SubscribeLinkListView.Items.Add(new ListViewItem(new[]
|
||||||
AddSubscriptionBox.Text = target.SubItems[1].Text;
|
|
||||||
RemarkTextBox.Text = target.SubItems[1].Text;
|
|
||||||
LinkTextBox.Text = target.SubItems[2].Text;
|
|
||||||
UserAgentTextBox.Text = target.SubItems[3].Text;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SubscribeLinkListView_MouseUp(object sender, MouseEventArgs e)
|
|
||||||
{
|
|
||||||
if (e.Button == MouseButtons.Right)
|
|
||||||
{
|
|
||||||
if (SubscribeLinkListView.SelectedItems.Count > 0)
|
|
||||||
{
|
{
|
||||||
pContextMenuStrip.Show(SubscribeLinkListView, e.Location);
|
"",
|
||||||
}
|
item.Remark,
|
||||||
}
|
item.Link,
|
||||||
|
!string.IsNullOrEmpty(item.UserAgent) ? item.UserAgent : WebUtil.DefaultUserAgent
|
||||||
|
})
|
||||||
|
{
|
||||||
|
Checked = item.Enable
|
||||||
|
});
|
||||||
|
|
||||||
|
ResetEditingGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ResetEditingGroup()
|
private void ResetEditingGroup()
|
||||||
{
|
{
|
||||||
_editingIndex = -1;
|
|
||||||
AddSubscriptionBox.Text = string.Empty;
|
AddSubscriptionBox.Text = string.Empty;
|
||||||
RemarkTextBox.Text = string.Empty;
|
RemarkTextBox.Text = string.Empty;
|
||||||
LinkTextBox.Text = string.Empty;
|
LinkTextBox.Text = string.Empty;
|
||||||
UserAgentTextBox.Text = WebUtil.DefaultUserAgent;
|
UserAgentTextBox.Text = WebUtil.DefaultUserAgent;
|
||||||
}
|
}
|
||||||
|
private void SetEditingGroup(int index)
|
||||||
private void ClearButton_Click(object sender, EventArgs e)
|
|
||||||
{
|
{
|
||||||
ResetEditingGroup();
|
if (index == -1)
|
||||||
}
|
|
||||||
|
|
||||||
private void SubscribeLinkListView_ItemChecked(object sender, ItemCheckedEventArgs e)
|
|
||||||
{
|
|
||||||
_editingIndex = e.Item.Index;
|
|
||||||
ListViewItem listViewItem = SubscribeLinkListView.Items[e.Item.Index];
|
|
||||||
|
|
||||||
AddSubscriptionBox.Text = listViewItem.SubItems[1].Text;
|
|
||||||
RemarkTextBox.Text = listViewItem.SubItems[1].Text;
|
|
||||||
LinkTextBox.Text = listViewItem.SubItems[2].Text;
|
|
||||||
UserAgentTextBox.Text = listViewItem.SubItems[3].Text;
|
|
||||||
|
|
||||||
var settingSub = Global.Settings.SubscribeLink[_editingIndex];
|
|
||||||
settingSub.Enable = listViewItem.Checked;
|
|
||||||
settingSub.Remark = listViewItem.SubItems[1].Text;
|
|
||||||
settingSub.Link = listViewItem.SubItems[2].Text;
|
|
||||||
settingSub.UserAgent = listViewItem.SubItems[3].Text;
|
|
||||||
|
|
||||||
Configuration.Save();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deleteServerToolStripMenuItem_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
if (SubscribeLinkListView.SelectedItems.Count > 0)
|
|
||||||
{
|
{
|
||||||
var item = SubscribeLinkListView.SelectedItems[0];
|
ResetEditingGroup();
|
||||||
|
AddButton.Text = i18N.Translate("Add");
|
||||||
if (MessageBoxX.Show(i18N.Translate("Confirm deletion?"), confirm: true) != DialogResult.OK)
|
return;
|
||||||
return;
|
|
||||||
DeleteServersInGroup(item.SubItems[1].Text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,60 +3,59 @@
|
|||||||
namespace Netch.Models
|
namespace Netch.Models
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// TUN/TAP 适配器配置类
|
/// TUN/TAP 适配器配置类
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class TUNTAPConfig
|
public class TUNTAPConfig
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 地址
|
/// 地址
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Address = "10.0.236.10";
|
public string Address = "10.0.236.10";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 掩码
|
/// DNS
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Netmask = "255.255.255.0";
|
public List<string> DNS = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 网关
|
/// 网关
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Gateway = "10.0.236.1";
|
public string Gateway = "10.0.236.1";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// DNS
|
/// 掩码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<string> DNS = new List<string>();
|
public string Netmask = "255.255.255.0";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 使用自定义 DNS 设置
|
/// 模式 2 下是否代理 DNS
|
||||||
/// </summary>
|
|
||||||
public bool UseCustomDNS = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 模式 2 下是否代理 DNS
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool ProxyDNS = false;
|
public bool ProxyDNS = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 使用Fake DNS
|
/// 使用自定义 DNS 设置
|
||||||
|
/// </summary>
|
||||||
|
public bool UseCustomDNS = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 使用Fake DNS
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool UseFakeDNS = false;
|
public bool UseFakeDNS = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class KcpConfig
|
public class KcpConfig
|
||||||
{
|
{
|
||||||
|
public bool congestion = false;
|
||||||
|
|
||||||
|
public int downlinkCapacity = 100;
|
||||||
public int mtu = 1350;
|
public int mtu = 1350;
|
||||||
|
|
||||||
|
public int readBufferSize = 2;
|
||||||
|
|
||||||
public int tti = 50;
|
public int tti = 50;
|
||||||
|
|
||||||
public int uplinkCapacity = 12;
|
public int uplinkCapacity = 12;
|
||||||
|
|
||||||
public int downlinkCapacity = 100;
|
|
||||||
|
|
||||||
public bool congestion = false;
|
|
||||||
|
|
||||||
public int readBufferSize = 2;
|
|
||||||
|
|
||||||
public int writeBufferSize = 2;
|
public int writeBufferSize = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,20 +63,19 @@ namespace Netch.Models
|
|||||||
{
|
{
|
||||||
public bool AllowInsecure = true;
|
public bool AllowInsecure = true;
|
||||||
|
|
||||||
public KcpConfig KcpConfig = new KcpConfig();
|
public KcpConfig KcpConfig = new();
|
||||||
|
|
||||||
public bool UseMux = false;
|
public bool UseMux = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AioDNSConfig
|
public class AioDNSConfig
|
||||||
{
|
{
|
||||||
public string RulePath = "bin\\china_site_list";
|
|
||||||
|
|
||||||
public string ChinaDNS = "223.5.5.5";
|
public string ChinaDNS = "223.5.5.5";
|
||||||
|
|
||||||
public string OtherDNS = "1.1.1.1";
|
public string OtherDNS = "1.1.1.1";
|
||||||
|
|
||||||
public string Protocol = "tcp";
|
public string Protocol = "tcp";
|
||||||
|
public string RulePath = "bin\\china_site_list";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -85,35 +83,62 @@ namespace Netch.Models
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class Setting
|
public class Setting
|
||||||
{
|
{
|
||||||
|
|
||||||
public V2rayConfig V2RayConfig = new V2rayConfig();
|
|
||||||
|
|
||||||
public AioDNSConfig AioDNS = new AioDNSConfig();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 服务器选择位置
|
/// 服务器列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int ServerComboBoxSelectedIndex = 0;
|
public readonly List<Server> Server = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 模式选择位置
|
/// ACL规则
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int ModeComboBoxSelectedIndex = 0;
|
public string ACL = "https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/banAD.acl";
|
||||||
|
|
||||||
|
public AioDNSConfig AioDNS = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
public bool ExitWhenClosed = false;
|
public bool ExitWhenClosed = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否退出时停止
|
/// HTTP 本地端口
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool StopWhenExited = false;
|
public ushort HTTPLocalPort = 2802;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否打开软件时启动加速
|
/// 语言设置
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool StartWhenOpened = false;
|
public string Language = "System";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// HTTP 和 Socks5 本地代理地址
|
||||||
|
/// </summary>
|
||||||
|
public string LocalAddress = "127.0.0.1";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否启动后自动最小化
|
/// 是否启动后自动最小化
|
||||||
@@ -121,29 +146,9 @@ namespace Netch.Models
|
|||||||
public bool MinimizeWhenStarted = false;
|
public bool MinimizeWhenStarted = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否开机启动软件
|
/// 模式选择位置
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool RunAtStartup = false;
|
public int ModeComboBoxSelectedIndex = 0;
|
||||||
|
|
||||||
/// <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;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 要修改为的系统 DNS
|
/// 要修改为的系统 DNS
|
||||||
@@ -151,19 +156,14 @@ namespace Netch.Models
|
|||||||
public string ModifiedDNS = "1.1.1.1,8.8.8.8";
|
public string ModifiedDNS = "1.1.1.1,8.8.8.8";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 解析服务器主机名
|
/// 修改系统 DNS
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool ResolveServerHostname = false;
|
public bool ModifySystemDNS = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 网页请求超时 毫秒
|
/// GFWList
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int RequestTimeout = 10000;
|
public string PAC = "https://raw.githubusercontent.com/HMBSbige/Text_Translation/master/ShadowsocksR/ss_white.pac";
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// PAC URL
|
|
||||||
/// </summary>
|
|
||||||
public string Pac_Url = "";
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// PAC端口
|
/// PAC端口
|
||||||
@@ -171,64 +171,84 @@ namespace Netch.Models
|
|||||||
public int Pac_Port = 2803;
|
public int Pac_Port = 2803;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// HTTP 本地端口
|
/// PAC URL
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ushort HTTPLocalPort = 2802;
|
public string Pac_Url = "";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Socks5 本地端口
|
/// 不代理TCP
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ushort Socks5LocalPort = 2801;
|
public bool ProcessNoProxyForTcp = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Redirector TCP 占用端口
|
/// 不代理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>
|
/// </summary>
|
||||||
public ushort RedirectorTCPPort = 3901;
|
public ushort RedirectorTCPPort = 3901;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// UDP Socket 占用端口
|
/// 网页请求超时 毫秒
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ushort UDPSocketPort = 18291;
|
public int RequestTimeout = 10000;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// HTTP 和 Socks5 本地代理地址
|
/// 解析服务器主机名
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string LocalAddress = "127.0.0.1";
|
public bool ResolveServerHostname = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// TUNTAP 适配器配置
|
/// 是否开机启动软件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TUNTAPConfig TUNTAP = new TUNTAPConfig();
|
public bool RunAtStartup = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 使用代理更新订阅
|
/// 服务器选择位置
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool UseProxyToUpdateSubscription = false;
|
public int ServerComboBoxSelectedIndex = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 订阅链接列表
|
/// 服务器测试方式 false.ICMPing true.TCPing
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<SubscribeLink> SubscribeLink = new List<SubscribeLink>();
|
public bool ServerTCPing = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 服务器列表
|
/// Socks5 本地端口
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly List<Server> Server = new List<Server>();
|
public ushort Socks5LocalPort = 2801;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 全局绕过 IP 列表
|
/// 启动后延迟测试间隔/秒
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<string> BypassIPs = new List<string>();
|
public int StartedPingInterval = -1;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 已保存的快捷配置
|
/// 是否打开软件时启动加速
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<Profile> Profiles = new List<Profile>();
|
public bool StartWhenOpened = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 快捷配置数量
|
/// 是否退出时停止
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int ProfileCount = 4;
|
public bool StopWhenExited = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// STUN测试服务器
|
/// STUN测试服务器
|
||||||
@@ -241,53 +261,30 @@ namespace Netch.Models
|
|||||||
public int STUN_Server_Port = 3478;
|
public int STUN_Server_Port = 3478;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否启用启动后延迟测试
|
/// 订阅链接列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool StartedTcping = false;
|
public List<SubscribeLink> SubscribeLink = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 启动后延迟测试间隔/秒
|
/// TUNTAP 适配器配置
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int StartedTcping_Interval = 3;
|
public TUNTAPConfig TUNTAP = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ACL规则
|
/// UDP Socket 占用端口
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string ACL = "https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/banAD.acl";
|
public ushort UDPSocketPort = 18291;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// GFWList
|
/// 是否打开软件时更新订阅
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string PAC = "https://raw.githubusercontent.com/HMBSbige/Text_Translation/master/ShadowsocksR/ss_white.pac";
|
public bool UpdateServersWhenOpened = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否使用DLL启动Shadowsocks
|
/// 使用代理更新订阅
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool BootShadowsocksFromDLL = true;
|
public bool UseProxyToUpdateSubscription = false;
|
||||||
|
|
||||||
/// <summary>
|
public V2rayConfig V2RayConfig = new();
|
||||||
/// 语言设置
|
|
||||||
/// </summary>
|
|
||||||
public string Language = "System";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 服务器测试方式 false.ICMPing true.TCPing
|
|
||||||
/// </summary>
|
|
||||||
public bool ServerTCPing = true;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 是否使用RDR内置SS
|
|
||||||
/// </summary>
|
|
||||||
public bool RedirectorSS = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 不代理UDP
|
|
||||||
/// </summary>
|
|
||||||
public bool ProcessNoProxyForUdp = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 不代理TCP
|
|
||||||
/// </summary>
|
|
||||||
public bool ProcessNoProxyForTcp = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -13,7 +13,7 @@ namespace Netch
|
|||||||
/// <param name="index">适配器索引</param>
|
/// <param name="index">适配器索引</param>
|
||||||
/// <param name="metric">跃点数</param>
|
/// <param name="metric">跃点数</param>
|
||||||
/// <returns>是否成功</returns>
|
/// <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);
|
public static extern bool CreateRoute(string address, int cidr, string gateway, int index, int metric = 0);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -25,7 +25,7 @@ namespace Netch
|
|||||||
/// <param name="index">适配器索引</param>
|
/// <param name="index">适配器索引</param>
|
||||||
/// <param name="metric">跃点数</param>
|
/// <param name="metric">跃点数</param>
|
||||||
/// <returns>是否成功</returns>
|
/// <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);
|
public static extern bool DeleteRoute(string address, int cidr, string gateway, int index, int metric = 0);
|
||||||
|
|
||||||
[DllImport("dnsapi", EntryPoint = "DnsFlushResolverCache")]
|
[DllImport("dnsapi", EntryPoint = "DnsFlushResolverCache")]
|
||||||
|
|||||||
@@ -21,3 +21,5 @@ XCOPY /s /Y %SolutionDir%modes\mode %TargetDir%mode\ >NUL
|
|||||||
DEL /f %TargetDir%*.config >NUL 2>&1
|
DEL /f %TargetDir%*.config >NUL 2>&1
|
||||||
DEL /f %TargetDir%*.pdb >NUL 2>&1
|
DEL /f %TargetDir%*.pdb >NUL 2>&1
|
||||||
RD /s /Q %TargetDir%x86 >NUL 2>&1
|
RD /s /Q %TargetDir%x86 >NUL 2>&1
|
||||||
|
|
||||||
|
exit 0
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
"Import Servers From Clipboard": "从剪贴板导入服务器",
|
"Import Servers From Clipboard": "从剪贴板导入服务器",
|
||||||
"Import servers error!": "未找到可导入的链接!",
|
"Import servers error!": "未找到可导入的链接!",
|
||||||
"Add [{0}] Server": "添加 [{0}] 服务器",
|
"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": "发现新版本",
|
"New version available": "发现新版本",
|
||||||
"Already latest version": "已经是最新版本",
|
"Already latest version": "已经是最新版本",
|
||||||
"New version found failed": "寻找新版本失败",
|
"New version found failed": "寻找新版本失败",
|
||||||
@@ -66,6 +66,7 @@
|
|||||||
"Subscribe": "订阅",
|
"Subscribe": "订阅",
|
||||||
"Manage Subscribe Links": "管理订阅链接",
|
"Manage Subscribe Links": "管理订阅链接",
|
||||||
"Update Servers From Subscribe Links": "从订阅链接更新服务器",
|
"Update Servers From Subscribe Links": "从订阅链接更新服务器",
|
||||||
|
"Update Servers From Subscribe Links With Proxy": "使用代理从订阅链接更新服务器",
|
||||||
"No subscription link": "没有任何一条订阅链接",
|
"No subscription link": "没有任何一条订阅链接",
|
||||||
"Updating {0}": "正在更新 {0}",
|
"Updating {0}": "正在更新 {0}",
|
||||||
"Update {1} server(s) from {0}": "从 {0} 更新 {1} 个服务器",
|
"Update {1} server(s) from {0}": "从 {0} 更新 {1} 个服务器",
|
||||||
@@ -126,10 +127,10 @@
|
|||||||
"Add": "添加",
|
"Add": "添加",
|
||||||
"Scan": "扫描",
|
"Scan": "扫描",
|
||||||
"Save": "保存",
|
"Save": "保存",
|
||||||
"Add / Modify": "保存/修改",
|
"Modify": "修改",
|
||||||
"Select a folder": "选择一个目录",
|
"Select a folder": "选择一个目录",
|
||||||
"Please enter an process name (xxx.exe)": "请输入一个进程名(xxx.exe)",
|
"Please enter an process name (xxx.exe)": "请输入一个进程名(xxx.exe)",
|
||||||
"Rule does not conform to C++ regular expression syntax": "规则不符合C ++正则表达式语法",
|
"Rule does not conform to C++ regular expression syntax": "规则不符合 C++ 正则表达式语法",
|
||||||
"Scan completed": "扫描完成",
|
"Scan completed": "扫描完成",
|
||||||
"Mode added successfully": "模式添加成功",
|
"Mode added successfully": "模式添加成功",
|
||||||
"Mode updated successfully": "模式修改成功",
|
"Mode updated successfully": "模式修改成功",
|
||||||
@@ -163,18 +164,18 @@
|
|||||||
"Exit when closed": "关闭时退出",
|
"Exit when closed": "关闭时退出",
|
||||||
"Stop when exited": "退出时停止",
|
"Stop when exited": "退出时停止",
|
||||||
"Global Bypass IPs": "全局直连 IP",
|
"Global Bypass IPs": "全局直连 IP",
|
||||||
"Port value illegal. Try again.": "端口值非法。请重试。",
|
"Port value illegal. Try again.": "端口值非法。请重试",
|
||||||
"Check update when opened": "打开软件时检查更新",
|
"Check update when opened": "打开软件时检查更新",
|
||||||
"Check Beta update": "检查 Beta 更新",
|
"Check Beta update": "检查 Beta 更新",
|
||||||
"Update subscribeat when opened": "自动更新订阅",
|
"Update Servers when opened": "打开软件时更新服务器",
|
||||||
"SS DLL": "SS DLL",
|
"SS DLL": "SS DLL",
|
||||||
"Modify System DNS": "修改系统 DNS",
|
"Modify System DNS": "修改系统 DNS",
|
||||||
"No Proxy for Udp": "不代理Udp流量",
|
"No Proxy for Udp": "不代理 UDP 流量",
|
||||||
"No Proxy for Tcp": "不代理Tcp流量",
|
"No Proxy for Tcp": "不代理 TCP 流量",
|
||||||
"ProfileCount": "快捷配置数量",
|
"ProfileCount": "快捷配置数量",
|
||||||
"ProfileCount value illegal. Try again.": "快捷配置数值非法。请重试。",
|
"ProfileCount value illegal. Try again.": "快捷配置数值非法。请重试",
|
||||||
"STUN_ServerPort value illegal. Try again.": "STUN 端口数值非法。请重试。",
|
"STUN_ServerPort value illegal. Try again.": "STUN 端口数值非法。请重试",
|
||||||
"Detection interval value illegal. Try again.": "检测间隔值非法。请重试。",
|
"Detection interval value illegal. Try again.": "检测间隔值非法。请重试",
|
||||||
"TUN/TAP driver is not detected. Is it installed now?": "未检测到 TUN/TAP 驱动,是否现在安装?",
|
"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 官网下载依赖程序?",
|
"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": "启动后延迟测试",
|
"Delay test after start": "启动后延迟测试",
|
||||||
@@ -197,6 +198,7 @@
|
|||||||
"Unable to start? Click me to download": "无法启动?点我下载依赖",
|
"Unable to start? Click me to download": "无法启动?点我下载依赖",
|
||||||
|
|
||||||
"The {0} port is in use.": "{0} 端口已被占用",
|
"The {0} port is in use.": "{0} 端口已被占用",
|
||||||
|
"The {0} port is reserved by system.": "{0} 端口是系统保留端口",
|
||||||
|
|
||||||
"[Web Proxy] Bypass LAN": "[网页代理] 绕过局域网",
|
"[Web Proxy] Bypass LAN": "[网页代理] 绕过局域网",
|
||||||
"[Non Web Proxy] Bypass LAN": "[不设置代理] 绕过局域网",
|
"[Non Web Proxy] Bypass LAN": "[不设置代理] 绕过局域网",
|
||||||
@@ -204,4 +206,4 @@
|
|||||||
"[Web Proxy] Bypass LAN and China": "[网页代理] 绕过局域网和中国大陆",
|
"[Web Proxy] Bypass LAN and China": "[网页代理] 绕过局域网和中国大陆",
|
||||||
"[Non Web Proxy] Bypass LAN and China": "[不设置代理] 绕过局域网和中国大陆",
|
"[Non Web Proxy] Bypass LAN and China": "[不设置代理] 绕过局域网和中国大陆",
|
||||||
"[TUN/TAP] Bypass LAN and China": "[TUN/TAP] 绕过局域网和中国大陆"
|
"[TUN/TAP] Bypass LAN and China": "[TUN/TAP] 绕过局域网和中国大陆"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,12 +16,21 @@ namespace Netch.Utils
|
|||||||
|
|
||||||
public static readonly string ModeDirectory = Path.Combine(Global.NetchDir, $"{MODE_DIR}\\");
|
public static readonly string ModeDirectory = Path.Combine(Global.NetchDir, $"{MODE_DIR}\\");
|
||||||
|
|
||||||
public static string GetRelativePath(string fullName) => fullName.Substring(ModeDirectory.Length);
|
public static string GetRelativePath(string fullName)
|
||||||
public static string GetFullPath(string relativeName) => Path.Combine(ModeDirectory, relativeName);
|
{
|
||||||
public static string GetFullPath(Mode mode) => Path.Combine(ModeDirectory, mode.RelativePath);
|
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>
|
/// <summary>
|
||||||
/// 从模式文件夹读取模式并为 <see cref="Forms.MainForm.ModeComboBox"/> 绑定数据
|
/// 从模式文件夹读取模式并为 <see cref="Forms.MainForm.ModeComboBox" /> 绑定数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static void Load()
|
public static void Load()
|
||||||
{
|
{
|
||||||
@@ -99,16 +108,12 @@ namespace Netch.Utils
|
|||||||
public static void WriteFile(Mode mode)
|
public static void WriteFile(Mode mode)
|
||||||
{
|
{
|
||||||
if (!Directory.Exists(ModeDirectory))
|
if (!Directory.Exists(ModeDirectory))
|
||||||
{
|
|
||||||
Directory.CreateDirectory(ModeDirectory);
|
Directory.CreateDirectory(ModeDirectory);
|
||||||
}
|
|
||||||
|
|
||||||
var fullName = GetFullPath(mode.RelativePath ?? mode.FileName + ".txt");
|
var fullName = GetFullPath(mode.RelativePath ?? mode.FileName + ".txt");
|
||||||
|
|
||||||
if (mode.RelativePath == null && File.Exists(fullName))
|
if (mode.RelativePath == null && File.Exists(fullName))
|
||||||
{
|
|
||||||
throw new Exception("新建模式的文件名已存在,请贡献者检查代码");
|
throw new Exception("新建模式的文件名已存在,请贡献者检查代码");
|
||||||
}
|
|
||||||
|
|
||||||
// 写入到模式文件里
|
// 写入到模式文件里
|
||||||
File.WriteAllText(fullName, mode.ToFileString());
|
File.WriteAllText(fullName, mode.ToFileString());
|
||||||
@@ -131,9 +136,7 @@ namespace Netch.Utils
|
|||||||
{
|
{
|
||||||
var fullName = GetFullPath(mode);
|
var fullName = GetFullPath(mode);
|
||||||
if (File.Exists(fullName))
|
if (File.Exists(fullName))
|
||||||
{
|
|
||||||
File.Delete(fullName);
|
File.Delete(fullName);
|
||||||
}
|
|
||||||
|
|
||||||
Global.Modes.Remove(mode);
|
Global.Modes.Remove(mode);
|
||||||
Global.MainForm.InitMode();
|
Global.MainForm.InitMode();
|
||||||
@@ -166,6 +169,7 @@ namespace Netch.Utils
|
|||||||
modeController = new NFController();
|
modeController = new NFController();
|
||||||
port = Global.Settings.RedirectorTCPPort;
|
port = Global.Settings.RedirectorTCPPort;
|
||||||
portName = "Redirector TCP";
|
portName = "Redirector TCP";
|
||||||
|
portType = PortType.TCP;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
case 2:
|
case 2:
|
||||||
@@ -176,6 +180,7 @@ namespace Netch.Utils
|
|||||||
modeController = new HTTPController();
|
modeController = new HTTPController();
|
||||||
port = Global.Settings.HTTPLocalPort;
|
port = Global.Settings.HTTPLocalPort;
|
||||||
portName = "HTTP";
|
portName = "HTTP";
|
||||||
|
portType = PortType.TCP;
|
||||||
MainForm.StatusPortInfoText.HttpPort = (ushort) port;
|
MainForm.StatusPortInfoText.HttpPort = (ushort) port;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
|
|||||||
@@ -24,11 +24,21 @@ namespace Netch.Utils
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (PortHelper.PortInUse(Global.Settings.UDPSocketPort))
|
const int tryLimit = 3;
|
||||||
{
|
var i = tryLimit;
|
||||||
Global.Settings.UDPSocketPort = PortHelper.GetAvailablePort();
|
while (i > 0)
|
||||||
Configuration.Save();
|
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 data = new byte[1024];
|
||||||
var newsock = new UdpClient(new IPEndPoint(IPAddress.Loopback, Global.Settings.UDPSocketPort));
|
var newsock = new UdpClient(new IPEndPoint(IPAddress.Loopback, Global.Settings.UDPSocketPort));
|
||||||
@@ -38,9 +48,7 @@ namespace Netch.Utils
|
|||||||
var result = await newsock.ReceiveAsync();
|
var result = await newsock.ReceiveAsync();
|
||||||
data = result.Buffer;
|
data = result.Buffer;
|
||||||
if (Enum.TryParse<Commands>(Encoding.ASCII.GetString(data, 0, data.Length), out var command))
|
if (Enum.TryParse<Commands>(Encoding.ASCII.GetString(data, 0, data.Length), out var command))
|
||||||
{
|
|
||||||
OnCalled(command);
|
OnCalled(command);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -53,14 +61,12 @@ namespace Netch.Utils
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var udpClient = new UdpClient(Global.Settings.UDPSocketPort))
|
using var udpClient = new UdpClient(Global.Settings.UDPSocketPort);
|
||||||
{
|
udpClient.Connect(IPAddress.Loopback, Global.Settings.UDPSocketPort);
|
||||||
udpClient.Connect(IPAddress.Loopback, Global.Settings.UDPSocketPort);
|
var sendBytes = Encoding.ASCII.GetBytes(command.ToString());
|
||||||
var sendBytes = Encoding.ASCII.GetBytes(command.ToString());
|
await udpClient.SendAsync(sendBytes, sendBytes.Length);
|
||||||
await udpClient.SendAsync(sendBytes, sendBytes.Length);
|
|
||||||
|
|
||||||
udpClient.Close();
|
udpClient.Close();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,15 +8,16 @@ namespace Netch.Utils
|
|||||||
{
|
{
|
||||||
public static class PortHelper
|
public static class PortHelper
|
||||||
{
|
{
|
||||||
private static readonly List<ushort[]> TCPExcludedRanges = new List<ushort[]>();
|
private static readonly List<Range> TCPReservedRanges = new();
|
||||||
private static readonly List<ushort[]> UDPExcludedRanges = new List<ushort[]>();
|
private static readonly List<Range> UDPReservedRanges = new();
|
||||||
|
private static readonly IPGlobalProperties NetInfo = IPGlobalProperties.GetIPGlobalProperties();
|
||||||
|
|
||||||
static PortHelper()
|
static PortHelper()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
GetExcludedPortRange(PortType.TCP, ref TCPExcludedRanges);
|
GetReservedPortRange(PortType.TCP, ref TCPReservedRanges);
|
||||||
GetExcludedPortRange(PortType.UDP, ref UDPExcludedRanges);
|
GetReservedPortRange(PortType.UDP, ref UDPReservedRanges);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -24,7 +25,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 lines = new List<string>();
|
||||||
var process = new Process
|
var process = new Process
|
||||||
@@ -48,48 +49,22 @@ namespace Netch.Utils
|
|||||||
|
|
||||||
var splitLine = false;
|
var splitLine = false;
|
||||||
foreach (var line in lines)
|
foreach (var line in lines)
|
||||||
{
|
|
||||||
if (!splitLine)
|
if (!splitLine)
|
||||||
{
|
{
|
||||||
if (line.StartsWith("-"))
|
if (line.StartsWith("-"))
|
||||||
{
|
|
||||||
splitLine = true;
|
splitLine = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (line == string.Empty)
|
if (line == string.Empty)
|
||||||
break;
|
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;
|
targetList.Add(new Range(ushort.Parse(value[0]), ushort.Parse(value[1])));
|
||||||
var _ = (from s1 in value
|
|
||||||
where ushort.TryParse(s1, out port)
|
|
||||||
select port).ToArray();
|
|
||||||
|
|
||||||
targetList.Add(_);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <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>
|
/// <summary>
|
||||||
/// 指定类型的端口是否已经被使用了
|
/// 指定类型的端口是否已经被使用了
|
||||||
@@ -97,39 +72,101 @@ namespace Netch.Utils
|
|||||||
/// <param name="port">端口</param>
|
/// <param name="port">端口</param>
|
||||||
/// <param name="type">检查端口类型</param>
|
/// <param name="type">检查端口类型</param>
|
||||||
/// <returns>是否被占用</returns>
|
/// <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();
|
switch (type)
|
||||||
var isTcpUsed = type != PortType.UDP &&
|
{
|
||||||
(IsPortExcluded(port, PortType.TCP) ||
|
case PortType.Both:
|
||||||
netInfo.GetActiveTcpListeners().Any(ipEndPoint => ipEndPoint.Port == port));
|
CheckPort(port, PortType.TCP);
|
||||||
var isUdpUsed = type != PortType.TCP &&
|
CheckPort(port, PortType.UDP);
|
||||||
(IsPortExcluded(port, PortType.UDP) ||
|
break;
|
||||||
netInfo.GetActiveUdpListeners().Any(ipEndPoint => ipEndPoint.Port == port));
|
default:
|
||||||
var isPortExcluded = !UsingPorts.Contains(port);
|
CheckPortInUse(port, type);
|
||||||
|
CheckPortReserved(port, type);
|
||||||
return isPortExcluded && (isTcpUsed || isUdpUsed);
|
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();
|
var random = new Random();
|
||||||
for (ushort i = 0; i < 55535; i++)
|
for (ushort i = 0; i < 55535; i++)
|
||||||
{
|
{
|
||||||
var p = (ushort) random.Next(10000, 65535);
|
var p = (ushort) random.Next(10000, 65535);
|
||||||
if (!PortInUse(p))
|
try
|
||||||
{
|
{
|
||||||
|
CheckPort(p, portType);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Exception("Cant Generate Available Port");
|
throw new Exception();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal readonly struct Range
|
||||||
|
{
|
||||||
|
public int Start { get; }
|
||||||
|
|
||||||
|
public int End { get; }
|
||||||
|
|
||||||
|
public Range(int start, int end)
|
||||||
|
{
|
||||||
|
Start = start;
|
||||||
|
End = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public bool InRange(int num)
|
||||||
/// 记录Netch使用的端口
|
{
|
||||||
/// </summary>
|
return Start <= num && num <= End;
|
||||||
public static readonly List<ushort> UsingPorts = new List<ushort>();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -145,4 +182,7 @@ namespace Netch.Utils
|
|||||||
public class PortInUseException : Exception
|
public class PortInUseException : Exception
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
public class PortReservedException : Exception
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,8 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Timers;
|
||||||
using Netch.Models;
|
using Netch.Models;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
@@ -9,14 +11,79 @@ namespace Netch.Utils
|
|||||||
{
|
{
|
||||||
public static class ServerHelper
|
public static class ServerHelper
|
||||||
{
|
{
|
||||||
public static readonly IEnumerable<IServerUtil> ServerUtils;
|
|
||||||
|
|
||||||
static ServerHelper()
|
static ServerHelper()
|
||||||
{
|
{
|
||||||
var serversUtilsTypes = Assembly.GetExecutingAssembly().GetExportedTypes().Where(type => type.GetInterfaces().Contains(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);
|
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;
|
||||||
|
static DelayTestHelper()
|
||||||
|
{
|
||||||
|
Timer = new Timer
|
||||||
|
{
|
||||||
|
Interval = 10000,
|
||||||
|
AutoReset = true,
|
||||||
|
Enabled = false
|
||||||
|
};
|
||||||
|
|
||||||
|
Timer.Elapsed += (_, _) => TestAllDelay();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Enabled
|
||||||
|
{
|
||||||
|
get => Timer.Enabled;
|
||||||
|
set => Timer.Enabled = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int Interval => (int) (Timer.Interval / 1000);
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
var enabled = Enabled;
|
||||||
|
Timer.Stop();
|
||||||
|
if (Global.Settings.DetectionTick <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Timer.Interval = Global.Settings.DetectionTick * 1000;
|
||||||
|
if (enabled)
|
||||||
|
{
|
||||||
|
Task.Run(TestAllDelay);
|
||||||
|
Timer.Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Handler
|
||||||
|
|
||||||
|
public static readonly IEnumerable<IServerUtil> ServerUtils;
|
||||||
|
|
||||||
public static Server ParseJObject(JObject o)
|
public static Server ParseJObject(JObject o)
|
||||||
{
|
{
|
||||||
var handle = GetUtilByTypeName((string) o["Type"]);
|
var handle = GetUtilByTypeName((string) o["Type"]);
|
||||||
@@ -47,5 +114,7 @@ namespace Netch.Utils
|
|||||||
{
|
{
|
||||||
return ServerUtils.FirstOrDefault(i => i.UriScheme.Any(s => s.Equals(typeName)));
|
return ServerUtils.FirstOrDefault(i => i.UriScheme.Any(s => s.Equals(typeName)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -59,7 +59,7 @@ As well, Netch avoid the restricted NAT problem caused by SSTap. You can use an
|
|||||||
- [go-tun2socks](https://github.com/eycorsican/go-tun2socks)
|
- [go-tun2socks](https://github.com/eycorsican/go-tun2socks)
|
||||||
- [shadowsocks-libev](https://github.com/shadowsocks/shadowsocks-libev)
|
- [shadowsocks-libev](https://github.com/shadowsocks/shadowsocks-libev)
|
||||||
- [shadowsocksr-libev](https://github.com/shadowsocksrr/shadowsocksr-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)
|
- [trojan](https://github.com/trojan-gfw/trojan)
|
||||||
- [ACL4SSR](https://github.com/ACL4SSR/ACL4SSR)
|
- [ACL4SSR](https://github.com/ACL4SSR/ACL4SSR)
|
||||||
- [PAC](https://github.com/HMBSbige/Text_Translation/blob/master/ShadowsocksR/ss_white.pac)
|
- [PAC](https://github.com/HMBSbige/Text_Translation/blob/master/ShadowsocksR/ss_white.pac)
|
||||||
|
|||||||
2
binaries
2
binaries
Submodule binaries updated: 7b5ce30669...7d34d180e3
@@ -68,7 +68,7 @@ Netch 支持多种语言,在启动时会根据系统语言选择自身语言
|
|||||||
- [go-tun2socks](https://github.com/eycorsican/go-tun2socks)
|
- [go-tun2socks](https://github.com/eycorsican/go-tun2socks)
|
||||||
- [shadowsocks-libev](https://github.com/shadowsocks/shadowsocks-libev)
|
- [shadowsocks-libev](https://github.com/shadowsocks/shadowsocks-libev)
|
||||||
- [shadowsocksr-libev](https://github.com/shadowsocksrr/shadowsocksr-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)
|
- [trojan](https://github.com/trojan-gfw/trojan)
|
||||||
- [ACL4SSR](https://github.com/ACL4SSR/ACL4SSR)
|
- [ACL4SSR](https://github.com/ACL4SSR/ACL4SSR)
|
||||||
- [PAC](https://github.com/HMBSbige/Text_Translation/blob/master/ShadowsocksR/ss_white.pac)
|
- [PAC](https://github.com/HMBSbige/Text_Translation/blob/master/ShadowsocksR/ss_white.pac)
|
||||||
|
|||||||
Reference in New Issue
Block a user