Compare commits

...

39 Commits
1.6.9 ... 1.7.1

Author SHA1 Message Date
AmazingDM
325ad430fe Bump version to 1.7.1 2021-01-09 02:33:00 +00:00
ChsBuffer
4b374d3898 Disable Update PAC when started 2021-01-07 11:01:23 +08:00
ChsBuffer
b6afeab187 trim 2021-01-07 10:54:50 +08:00
ChsBuffer
6e499c3948 Update Option items Notification 2021-01-07 10:52:58 +08:00
ChsBuffer
5bfcbab543 Comment ExitToolStripMenuIten_Click Handler 2021-01-05 18:10:10 +08:00
ChsBuffer
fe69c5a67b Refactor show Bandwidth 2021-01-05 17:55:08 +08:00
ChsBuffer
1c974d295b Revert "️"
This reverts commit a544bd1a26.
2021-01-05 17:54:00 +08:00
AmazingDM
a544bd1a26 2021-01-05 17:37:14 +08:00
AmazingDM
3bfe03b99b 更新添加模式窗口汉化,优化代码 2021-01-05 17:21:36 +08:00
AmazingDM
1fa18ce787 Merge branch 'master' of https://github.com/NetchX/Netch 2021-01-05 17:12:50 +08:00
AmazingDM
f7ad2baa52 Optimized code 2021-01-05 17:11:11 +08:00
AmazingDM
447a25457b Update Advanced_Usage.zh-CN.md 2021-01-05 16:44:46 +08:00
AmazingDM
3a8351e6e4 Update README.md 2021-01-05 16:39:54 +08:00
AmazingDM
eb30300b24 Update README.zh-CN.md 2021-01-05 16:39:50 +08:00
AmazingDM
0b8373a21e Update README.md 2021-01-05 16:34:37 +08:00
AmazingDM
8a551b715e 订阅链接启用状态默认为true 2021-01-05 13:01:16 +08:00
AmazingDM
34814fe7f5 订阅窗口可右键删除订阅节点
新增订阅链接勾选项(订阅启用状态)
更新订阅窗口汉化
2021-01-05 11:55:04 +08:00
AmazingDM
528abe3fdd Socks5无验证时不显示流量统计
更新PAC
2021-01-04 18:45:01 +08:00
AmazingDM
a10410dafd Update ck-client to v2.5.2 https://github.com/cbeuw/Cloak/releases/tag/v2.5.2 2021-01-04 15:22:46 +08:00
AmazingDM
2ca98a94d5 rename UninstallTap method 2021-01-04 15:09:01 +08:00
AmazingDM
ac2e5e943e Update mode 2021-01-04 14:05:15 +08:00
AmazingDM
0957514e05 Bump version to 1.7.0 2021-01-04 14:01:20 +08:00
AmazingDM
35b9f168ff 添加测速方式(TCPing&ICMPing)切换设置选项 2021-01-04 13:59:19 +08:00
AmazingDM
ce15e9468e 不代理TCP流量设置
调整设置界面UI
2021-01-04 13:23:58 +08:00
AmazingDM
4c8508a838 Merge remote-tracking branch 'chsbuffer/fixJob' 2021-01-04 12:45:19 +08:00
ChsBuffer
f931adb005 Fix TrojanController ignores sni (host) value
closes #478, #487
2020-12-31 15:04:53 +08:00
Connection Refused
d4f829d4bd Merge pull request #486 from SekiBetu/dev
set mux to false by default
2020-12-30 09:26:44 +08:00
SekiBetu
51d4ba0fdb set mux to false by default 2020-12-30 06:37:02 +08:00
AmazingDM
ca0870889a 更新NTT,优化部分代码 2020-12-28 15:21:43 +08:00
ChsBuffer
ac3e39e9cd Update AioDNS 2020-12-25 22:44:44 +08:00
ChsBuffer
84765ab96d Delay Add Job 2020-12-25 17:12:03 +08:00
AmazingDM
a18851af15 Update binaries 2020-12-25 13:48:40 +08:00
AmazingDM
42366abcca Update README.md Quote 2020-12-25 13:43:33 +08:00
AmazingDM
cec8358922 PAC 2020-12-25 11:28:38 +08:00
AmazingDM
db8e964351 Update translations 2020-12-25 09:43:48 +08:00
AmazingDM
ad3053298a PAC替换ACL
sysproxy.dll 替换为 nuget WindowsProxy
2020-12-24 22:57:52 +08:00
ChsBuffer
669ca4902f Fix: set encoding only when RedireStd enabled 2020-12-24 16:14:41 +08:00
ChsBuffer
272bf61b0f Remove RedirecStandInput (Fix SS plugin start error) 2020-12-24 15:59:51 +08:00
ChsBuffer
0051e7bb50 Feat ICMPing 2020-12-24 13:32:06 +08:00
46 changed files with 1104 additions and 564 deletions

View File

@@ -6,7 +6,6 @@ namespace Netch.Controllers
{ {
public class DNSController : IController public class DNSController : IController
{ {
public string Name { get; } = "DNS Service"; public string Name { get; } = "DNS Service";
/// <summary> /// <summary>
@@ -15,13 +14,14 @@ namespace Netch.Controllers
/// <returns></returns> /// <returns></returns>
public bool Start() public bool Start()
{ {
if (!aiodns_dial(Encoding.UTF8.GetBytes(Path.GetFullPath(Global.Settings.AioDNS.RulePath)), aiodns_dial((int) NameList.TYPE_REST, null);
Encoding.UTF8.GetBytes($"{Global.Settings.AioDNS.ChinaDNS}:53"), aiodns_dial((int) NameList.TYPE_ADDR, Encoding.UTF8.GetBytes($"{Global.Settings.LocalAddress}:53"));
Encoding.UTF8.GetBytes($"{Global.Settings.AioDNS.OtherDNS}:53")) aiodns_dial((int) NameList.TYPE_LIST, Encoding.UTF8.GetBytes(Path.GetFullPath(Global.Settings.AioDNS.RulePath)));
) aiodns_dial((int) NameList.TYPE_CDNS, Encoding.UTF8.GetBytes($"{Global.Settings.AioDNS.ChinaDNS}:53"));
return false; aiodns_dial((int) NameList.TYPE_ODNS, Encoding.UTF8.GetBytes($"{Global.Settings.AioDNS.OtherDNS}:53"));
return aiodns_dial((int) NameList.TYPE_METH, Encoding.UTF8.GetBytes(Global.Settings.AioDNS.Protocol));
aiodns_init();
return aiodns_init();
} }
public void Stop() public void Stop()
@@ -32,7 +32,7 @@ namespace Netch.Controllers
#region NativeMethods #region NativeMethods
[DllImport("aiodns.bin", CallingConvention = CallingConvention.Cdecl)] [DllImport("aiodns.bin", CallingConvention = CallingConvention.Cdecl)]
public static extern bool aiodns_dial(byte[] chinacon, byte[] chinadns, byte[] otherdns); public static extern bool aiodns_dial(int name, byte[] value);
[DllImport("aiodns.bin", CallingConvention = CallingConvention.Cdecl)] [DllImport("aiodns.bin", CallingConvention = CallingConvention.Cdecl)]
public static extern bool aiodns_init(); public static extern bool aiodns_init();
@@ -40,6 +40,16 @@ namespace Netch.Controllers
[DllImport("aiodns.bin", CallingConvention = CallingConvention.Cdecl)] [DllImport("aiodns.bin", CallingConvention = CallingConvention.Cdecl)]
public static extern void aiodns_free(); public static extern void aiodns_free();
enum NameList : int
{
TYPE_REST,
TYPE_ADDR,
TYPE_LIST,
TYPE_CDNS,
TYPE_ODNS,
TYPE_METH
}
#endregion #endregion
} }
} }

View File

@@ -56,7 +56,7 @@ namespace Netch.Controllers
/// 程序输出的编码, /// 程序输出的编码,
/// 调用于基类的 <see cref="OnOutputDataReceived"/> /// 调用于基类的 <see cref="OnOutputDataReceived"/>
/// </summary> /// </summary>
protected string InstanceOutputEncoding { get; set; } = "gbk"; protected Encoding InstanceOutputEncoding { get; set; } = Encoding.GetEncoding("gbk");
/// <summary> /// <summary>
/// 停止进程 /// 停止进程
@@ -93,10 +93,11 @@ namespace Netch.Controllers
WorkingDirectory = $"{Global.NetchDir}\\bin", WorkingDirectory = $"{Global.NetchDir}\\bin",
Arguments = argument, Arguments = argument,
CreateNoWindow = true, CreateNoWindow = true,
RedirectStandardError = RedirectStd,
RedirectStandardInput = RedirectStd,
RedirectStandardOutput = RedirectStd,
UseShellExecute = !RedirectStd, UseShellExecute = !RedirectStd,
RedirectStandardOutput = RedirectStd,
StandardOutputEncoding = RedirectStd ? InstanceOutputEncoding : null,
RedirectStandardError = RedirectStd,
StandardErrorEncoding = RedirectStd ? InstanceOutputEncoding : null,
WindowStyle = ProcessWindowStyle.Hidden WindowStyle = ProcessWindowStyle.Hidden
} }
}; };
@@ -192,15 +193,13 @@ namespace Netch.Controllers
if (e.Data == null) if (e.Data == null)
return; return;
var info = Encoding.GetEncoding(InstanceOutputEncoding).GetBytes(e.Data); Write(e.Data);
var str = Encoding.UTF8.GetString(info);
Write(str);
// 检查启动 // 检查启动
if (State == State.Starting) if (State == State.Starting)
{ {
if (StartedKeywords.Any(s => str.Contains(s))) if (StartedKeywords.Any(s => e.Data.Contains(s)))
State = State.Started; State = State.Started;
else if (StoppedKeywords.Any(s => str.Contains(s))) else if (StoppedKeywords.Any(s => e.Data.Contains(s)))
State = State.Stopped; State = State.Stopped;
} }
} }

View File

@@ -4,8 +4,11 @@ using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
using Microsoft.Win32; using Microsoft.Win32;
using Netch.Models; using Netch.Models;
using Netch.Servers.Socks5;
using Netch.Utils; using Netch.Utils;
using WindowsProxy;
using Netch.Servers.Socks5;
using Netch.Servers.Trojan;
using Netch.Utils.HttpProxyHandler;
namespace Netch.Controllers namespace Netch.Controllers
{ {
@@ -36,7 +39,23 @@ namespace Netch.Controllers
Global.Job.AddProcess(pPrivoxyController.Instance); Global.Job.AddProcess(pPrivoxyController.Instance);
} }
if (mode.Type == 3) NativeMethods.SetGlobal($"127.0.0.1:{Global.Settings.HTTPLocalPort}", IEProxyExceptions); if (mode.Type == 3)
{
if ((MainController.Server is Socks5 or Trojan) && mode.BypassChina)
{
//启动PAC服务器
PACServerHandle.InitPACServer("127.0.0.1");
}
else
{
using var service = new ProxyService
{
Server = $"127.0.0.1:{Global.Settings.HTTPLocalPort}",
Bypass = IEProxyExceptions
};
service.Global();
}
}
} }
catch (Exception e) catch (Exception e)
{ {
@@ -85,18 +104,36 @@ namespace Netch.Controllers
{ {
var tasks = new[] var tasks = new[]
{ {
Task.Factory.StartNew(pPrivoxyController.Stop), Task.Run(pPrivoxyController.Stop),
Task.Factory.StartNew(() => Task.Run(() =>
{ {
if (prevEnabled) using var service = new ProxyService();
try
{ {
if (prevHTTP != "") PACServerHandle.Stop();
NativeMethods.SetGlobal(prevHTTP, prevBypass); if (prevEnabled)
if (prevPAC != "") {
NativeMethods.SetURL(prevPAC); if (prevHTTP != "")
{
service.Server = prevHTTP;
service.Bypass = prevBypass;
service.Global();
}
if (prevPAC != "")
{
service.AutoConfigUrl = prevPAC;
service.Pac();
}
}
else
{
service.Direct();
}
}
catch (Exception e)
{
Logging.Error($"{Name} 控制器出错:\n" + e);
} }
else
NativeMethods.SetDIRECT();
}) })
}; };
Task.WaitAll(tasks); Task.WaitAll(tasks);

View File

@@ -1,6 +1,7 @@
using System; using System;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Netch.Models; using Netch.Models;
using Netch.Servers.Socks5; using Netch.Servers.Socks5;
@@ -23,6 +24,7 @@ namespace Netch.Controllers
get => _udpServerController ?? _serverController; get => _udpServerController ?? _serverController;
set => _udpServerController = value; set => _udpServerController = value;
} }
public static Mode Mode;
/// TCP or Both Server /// TCP or Both Server
public static Server Server; public static Server Server;
@@ -52,6 +54,7 @@ namespace Netch.Controllers
{ {
Logging.Info($"启动主控制器: {server.Type} [{mode.Type}]{mode.Remark}"); Logging.Info($"启动主控制器: {server.Type} [{mode.Type}]{mode.Remark}");
Server = server; Server = server;
Mode = mode;
if (server is Socks5 && mode.Type == 4) if (server is Socks5 && mode.Type == 4)
{ {
@@ -149,7 +152,11 @@ namespace Netch.Controllers
{ {
if (guard.Instance != null) if (guard.Instance != null)
{ {
Global.Job.AddProcess(guard.Instance); Task.Run(() =>
{
Thread.Sleep(1000);
Global.Job.AddProcess(guard.Instance);
});
} }
} }

View File

@@ -55,8 +55,11 @@ namespace Netch.Controllers
#region aio_dial #region aio_dial
aio_dial((int) NameList.TYPE_FILTERLOOPBACK, "false"); aio_dial((int) NameList.TYPE_FILTERLOOPBACK, "false");
aio_dial((int) NameList.TYPE_FILTERTCP, "true");
aio_dial((int) NameList.TYPE_TCPLISN, Global.Settings.RedirectorTCPPort.ToString()); aio_dial((int) NameList.TYPE_TCPLISN, Global.Settings.RedirectorTCPPort.ToString());
if (Global.Settings.ProcessNoProxyForUdp && Global.Settings.ProcessNoProxyForTcp) MessageBoxX.Show("");
//UDP
if (Global.Settings.ProcessNoProxyForUdp) if (Global.Settings.ProcessNoProxyForUdp)
{ {
aio_dial((int) NameList.TYPE_FILTERUDP, "false"); aio_dial((int) NameList.TYPE_FILTERUDP, "false");
@@ -68,6 +71,18 @@ namespace Netch.Controllers
SetServer(PortType.Both); SetServer(PortType.Both);
} }
//TCP
if (Global.Settings.ProcessNoProxyForTcp)
{
aio_dial((int) NameList.TYPE_FILTERTCP, "false");
SetServer(PortType.UDP);
}
else
{
aio_dial((int) NameList.TYPE_FILTERTCP, "true");
SetServer(PortType.Both);
}
if (!CheckRule(mode.FullRule, out var list)) if (!CheckRule(mode.FullRule, out var list))
{ {
MessageBoxX.Show($"\"{string.Join("", list.Select(s => s + "\n"))}\" does not conform to C++ regular expression syntax"); MessageBoxX.Show($"\"{string.Join("", list.Select(s => s + "\n"))}\" does not conform to C++ regular expression syntax");
@@ -348,7 +363,6 @@ namespace Netch.Controllers
/// <returns>是否成功卸载</returns> /// <returns>是否成功卸载</returns>
public static bool UninstallDriver() public static bool UninstallDriver()
{ {
Global.MainForm.StatusText(i18N.TranslateFormat("Uninstalling {0}", "NF Service"));
Logging.Info("卸载 NF 驱动"); Logging.Info("卸载 NF 驱动");
try try
{ {

View File

@@ -1,5 +1,4 @@
using System; using System;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using Netch.Utils; using Netch.Utils;

View File

@@ -119,9 +119,9 @@ namespace Netch.Controllers
{ {
var tasks = new[] var tasks = new[]
{ {
Task.Factory.StartNew(StopInstance), Task.Run(StopInstance),
Task.Factory.StartNew(ClearRouteTable), Task.Run(ClearRouteTable),
Task.Factory.StartNew(DNSController.Stop) Task.Run(DNSController.Stop)
}; };
Task.WaitAll(tasks); Task.WaitAll(tasks);
} }

View File

@@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Net; using System.Net;
using Netch.Models.GitHubRelease; using Netch.Models.GitHubRelease;
using Netch.Utils; using Netch.Utils;
@@ -16,7 +15,7 @@ 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.6.9"; public const string AssemblyVersion = @"1.7.1";
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}")}";

View File

@@ -42,7 +42,7 @@ namespace Netch.Forms
if (await MainController.Start(server, mode)) if (await MainController.Start(server, mode))
{ {
State = State.Started; State = State.Started;
_ = Task.Run(() => { Bandwidth.NetTraffic(server, mode); }); _ = Task.Run(() => { Bandwidth.NetTraffic(); });
// 如果勾选启动后最小化 // 如果勾选启动后最小化
if (Global.Settings.MinimizeWhenStarted) if (Global.Settings.MinimizeWhenStarted)
{ {

View File

@@ -87,6 +87,7 @@
this.ProfileTable = new System.Windows.Forms.TableLayoutPanel(); this.ProfileTable = new System.Windows.Forms.TableLayoutPanel();
this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel(); this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
this.ButtomControlContainerControl = new System.Windows.Forms.ContainerControl(); this.ButtomControlContainerControl = new System.Windows.Forms.ContainerControl();
this.updatePACToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.MenuStrip.SuspendLayout(); this.MenuStrip.SuspendLayout();
this.ConfigurationGroupBox.SuspendLayout(); this.ConfigurationGroupBox.SuspendLayout();
this.configLayoutPanel.SuspendLayout(); this.configLayoutPanel.SuspendLayout();
@@ -196,6 +197,7 @@
this.CleanDNSCacheToolStripMenuItem, this.CleanDNSCacheToolStripMenuItem,
this.UpdateACLToolStripMenuItem, this.UpdateACLToolStripMenuItem,
this.updateACLWithProxyToolStripMenuItem, this.updateACLWithProxyToolStripMenuItem,
this.updatePACToolStripMenuItem,
this.UninstallServiceToolStripMenuItem, this.UninstallServiceToolStripMenuItem,
this.UninstallTapDriverToolStripMenuItem}); this.UninstallTapDriverToolStripMenuItem});
this.OptionsToolStripMenuItem.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1); this.OptionsToolStripMenuItem.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1);
@@ -243,7 +245,7 @@
this.UninstallTapDriverToolStripMenuItem.Name = "UninstallTapDriverToolStripMenuItem"; this.UninstallTapDriverToolStripMenuItem.Name = "UninstallTapDriverToolStripMenuItem";
this.UninstallTapDriverToolStripMenuItem.Size = new System.Drawing.Size(220, 22); this.UninstallTapDriverToolStripMenuItem.Size = new System.Drawing.Size(220, 22);
this.UninstallTapDriverToolStripMenuItem.Text = "Uninstall TUN/TAP driver"; this.UninstallTapDriverToolStripMenuItem.Text = "Uninstall TUN/TAP driver";
this.UninstallTapDriverToolStripMenuItem.Click += new System.EventHandler(this.reinstallTapDriverToolStripMenuItem_Click); this.UninstallTapDriverToolStripMenuItem.Click += new System.EventHandler(this.UninstallTapDriverToolStripMenuItem_Click);
// //
// HelpToolStripMenuItem // HelpToolStripMenuItem
// //
@@ -697,6 +699,13 @@
this.ButtomControlContainerControl.TabStop = false; this.ButtomControlContainerControl.TabStop = false;
this.ButtomControlContainerControl.Text = "groupBox1"; this.ButtomControlContainerControl.Text = "groupBox1";
// //
// updatePACToolStripMenuItem
//
this.updatePACToolStripMenuItem.Name = "updatePACToolStripMenuItem";
this.updatePACToolStripMenuItem.Size = new System.Drawing.Size(220, 22);
this.updatePACToolStripMenuItem.Text = "Update PAC";
this.updatePACToolStripMenuItem.Click += new System.EventHandler(this.updatePACToolStripMenuItem_Click);
//
// MainForm // MainForm
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
@@ -803,5 +812,6 @@
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1; private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
private System.Windows.Forms.ContainerControl ButtomControlContainerControl; private System.Windows.Forms.ContainerControl ButtomControlContainerControl;
private System.Windows.Forms.ToolStripMenuItem updatePACToolStripMenuItem;
} }
} }

View File

@@ -1,7 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
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;
@@ -208,12 +206,16 @@ namespace Netch.Forms
DNS.Cache.Clear(); DNS.Cache.Clear();
}); });
StatusText(i18N.Translate("DNS cache cleanup succeeded")); NotifyTip(i18N.Translate("DNS cache cleanup succeeded"));
} }
catch (Exception) catch (Exception)
{ {
// ignored // ignored
} }
finally
{
StatusText();
}
} }
private void updateACLWithProxyToolStripMenuItem_Click(object sender, EventArgs e) private void updateACLWithProxyToolStripMenuItem_Click(object sender, EventArgs e)
@@ -235,8 +237,7 @@ namespace Netch.Forms
} }
Enabled = false; Enabled = false;
StatusText(i18N.TranslateFormat("Updating {0}", "ACL"));
NotifyTip(i18N.Translate("Updating in the background"));
try try
{ {
if (useProxy) if (useProxy)
@@ -270,6 +271,34 @@ namespace Netch.Forms
State = State.Stopped; 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; Enabled = true;
} }
} }
@@ -284,24 +313,25 @@ namespace Netch.Forms
{ {
if (NFController.UninstallDriver()) if (NFController.UninstallDriver())
{ {
StatusText(i18N.TranslateFormat("{0} has been uninstalled", "NF Service")); NotifyTip(i18N.TranslateFormat("{0} has been uninstalled", "NF Service"));
} }
}); });
} }
finally finally
{ {
StatusText();
Enabled = true; Enabled = true;
} }
} }
private async void reinstallTapDriverToolStripMenuItem_Click(object sender, EventArgs e) private async void UninstallTapDriverToolStripMenuItem_Click(object sender, EventArgs e)
{ {
StatusText(i18N.TranslateFormat("Uninstalling {0}", "TUN/TAP driver"));
Enabled = false; Enabled = false;
StatusText(i18N.TranslateFormat("Uninstalling {0}", "TUN/TAP driver"));
try try
{ {
await Task.Run(TUNTAP.deltapall); await Task.Run(TUNTAP.deltapall);
StatusText(i18N.TranslateFormat("{0} has been uninstalled", "TUN/TAP driver")); NotifyTip(i18N.TranslateFormat("{0} has been uninstalled", "TUN/TAP driver"));
} }
catch (Exception exception) catch (Exception exception)
{ {
@@ -309,7 +339,7 @@ namespace Netch.Forms
} }
finally finally
{ {
State = State.Waiting; StatusText();
Enabled = true; Enabled = true;
} }
} }
@@ -317,6 +347,9 @@ namespace Netch.Forms
#endregion #endregion
/// <summary>
/// 菜单栏强制退出
/// </summary>
private void exitToolStripMenuItem_Click(object sender, EventArgs e) private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{ {
Exit(true); Exit(true);

View File

@@ -38,14 +38,15 @@ namespace Netch.Forms
UninstallServiceToolStripMenuItem.Enabled = UninstallServiceToolStripMenuItem.Enabled =
UpdateACLToolStripMenuItem.Enabled = UpdateACLToolStripMenuItem.Enabled =
updateACLWithProxyToolStripMenuItem.Enabled = updateACLWithProxyToolStripMenuItem.Enabled =
UpdateServersFromSubscribeLinksToolStripMenuItem.Enabled = updatePACToolStripMenuItem.Enabled =
UninstallTapDriverToolStripMenuItem.Enabled = UpdateServersFromSubscribeLinksToolStripMenuItem.Enabled =
ReloadModesToolStripMenuItem.Enabled = enabled; UninstallTapDriverToolStripMenuItem.Enabled =
ReloadModesToolStripMenuItem.Enabled = enabled;
} }
_state = value; _state = value;
StatusText(i18N.Translate(StateExtension.GetStatusString(value))); StatusText();
switch (value) switch (value)
{ {
case State.Waiting: case State.Waiting:
@@ -68,14 +69,13 @@ namespace Netch.Forms
ProfileGroupBox.Enabled = true; ProfileGroupBox.Enabled = true;
UsedBandwidthLabel.Visible /*= UploadSpeedLabel.Visible*/ = DownloadSpeedLabel.Visible = Global.Flags.IsWindows10Upper;
break; break;
case State.Stopping: case State.Stopping:
ControlButton.Enabled = false; ControlButton.Enabled = false;
ControlButton.Text = "..."; ControlButton.Text = "...";
ProfileGroupBox.Enabled = false; ProfileGroupBox.Enabled = false;
UsedBandwidthLabel.Visible /*= UploadSpeedLabel.Visible*/ = DownloadSpeedLabel.Visible = false; BandwidthState(false);
NatTypeStatusText(); NatTypeStatusText();
break; break;
case State.Stopped: case State.Stopped:
@@ -97,6 +97,11 @@ namespace Netch.Forms
} }
} }
public void BandwidthState(bool state)
{
UsedBandwidthLabel.Visible /*= UploadSpeedLabel.Visible*/ = DownloadSpeedLabel.Visible = state;
}
public void NatTypeStatusText(string text = "", string country = "") public void NatTypeStatusText(string text = "", string country = "")
{ {
if (InvokeRequired) if (InvokeRequired)
@@ -167,7 +172,7 @@ namespace Netch.Forms
/// 更新状态栏文本 /// 更新状态栏文本
/// </summary> /// </summary>
/// <param name="text"></param> /// <param name="text"></param>
public void StatusText(string text) public void StatusText(string text = null)
{ {
if (InvokeRequired) if (InvokeRequired)
{ {
@@ -175,6 +180,7 @@ namespace Netch.Forms
return; return;
} }
text ??= i18N.Translate(StateExtension.GetStatusString(State));
StatusLabel.Text = i18N.Translate("Status", ": ") + text; StatusLabel.Text = i18N.Translate("Status", ": ") + text;
} }

View File

@@ -348,12 +348,13 @@ namespace Netch.Forms
try try
{ {
await Task.Run(TestServer); await Task.Run(TestServer);
Refresh();
NotifyTip(i18N.Translate("Test done"));
} }
finally finally
{ {
Enabled = true; Enabled = true;
StatusText(i18N.Translate("Test done")); StatusText();
Refresh();
} }
} }
@@ -463,6 +464,9 @@ namespace Netch.Forms
Activate(); Activate();
} }
/// <summary>
/// 通知图标右键菜单退出
/// </summary>
private void ExitToolStripButton_Click(object sender, EventArgs e) private void ExitToolStripButton_Click(object sender, EventArgs e)
{ {
Exit(); Exit();

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,6 @@
using Netch.Utils; using Netch.Utils;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@@ -59,6 +58,14 @@ namespace Netch.Forms
c => Global.Settings.ResolveServerHostname = c, c => Global.Settings.ResolveServerHostname = c,
Global.Settings.ResolveServerHostname); Global.Settings.ResolveServerHostname);
BindRadioBox(ICMPingRadioBtn,
c => Global.Settings.ServerTCPing = c,
!Global.Settings.ServerTCPing);
BindRadioBox(TCPingRadioBtn,
c => Global.Settings.ServerTCPing = c,
Global.Settings.ServerTCPing);
BindTextBox<int>(ProfileCountTextBox, BindTextBox<int>(ProfileCountTextBox,
i => i > -1, i => i > -1,
i => Global.Settings.ProfileCount = i, i => Global.Settings.ProfileCount = i,
@@ -105,6 +112,10 @@ namespace Netch.Forms
s => Global.Settings.ProcessNoProxyForUdp = s, s => Global.Settings.ProcessNoProxyForUdp = s,
Global.Settings.ProcessNoProxyForUdp); Global.Settings.ProcessNoProxyForUdp);
BindCheckBox(NoProxyForTcpCheckBox,
s => Global.Settings.ProcessNoProxyForTcp = s,
Global.Settings.ProcessNoProxyForTcp);
#endregion #endregion
#region TUN/TAP #region TUN/TAP
@@ -310,10 +321,11 @@ namespace Netch.Forms
return; return;
} }
#endregion
#region CheckSTUN #region CheckSTUN
var stunFlag = true; var errFlag = false;
var stunServer = string.Empty; var stunServer = string.Empty;
ushort stunServerPort = 3478; ushort stunServerPort = 3478;
@@ -325,15 +337,15 @@ namespace Netch.Forms
if (stun.Length > 1) if (stun.Length > 1)
if (!ushort.TryParse(stun[1], out stunServerPort)) if (!ushort.TryParse(stun[1], out stunServerPort))
{ {
stunFlag = false; errFlag = true;
} }
} }
else else
{ {
stunFlag = false; errFlag = true;
} }
if (!stunFlag) if (errFlag)
{ {
Utils.Utils.ChangeControlForeColor(STUN_ServerComboBox, Color.Red); Utils.Utils.ChangeControlForeColor(STUN_ServerComboBox, Color.Red);
return; return;
@@ -341,8 +353,6 @@ namespace Netch.Forms
#endregion #endregion
#endregion
#region Save #region Save
foreach (var pair in _saveActions) foreach (var pair in _saveActions)
@@ -418,7 +428,13 @@ namespace Netch.Forms
{ {
control.Checked = value; control.Checked = value;
_checkActions.Add(control, s => true); _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)
{
control.Checked = value;
_checkActions.Add(control, s => true);
_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, Func<string, bool>> _checkActions = new Dictionary<Control, Func<string, bool>>();
@@ -429,5 +445,25 @@ namespace Netch.Forms
{ {
ModifiedDNSTextBox.Enabled = ModifySystemDNSCheckBox.Checked; ModifiedDNSTextBox.Enabled = ModifySystemDNSCheckBox.Checked;
} }
private void NoProxyForUdpCheckBox_CheckedChanged(object sender, EventArgs e)
{
if (NoProxyForUdpCheckBox.Checked) NoProxyForTcpCheckBox.Checked = false;
}
private void NoProxyForTcpCheckBox_CheckedChanged(object sender, EventArgs e)
{
if (NoProxyForTcpCheckBox.Checked) NoProxyForUdpCheckBox.Checked = false;
}
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;
}
} }
} }

View File

@@ -40,11 +40,13 @@
this.RemarkTextBox = new System.Windows.Forms.TextBox(); this.RemarkTextBox = new System.Windows.Forms.TextBox();
this.RemarkLabel = new System.Windows.Forms.Label(); this.RemarkLabel = new System.Windows.Forms.Label();
this.SubscribeLinkListView = new System.Windows.Forms.ListView(); this.SubscribeLinkListView = new System.Windows.Forms.ListView();
this.EnableColumnHeader = new System.Windows.Forms.ColumnHeader();
this.RemarkColumnHeader = new System.Windows.Forms.ColumnHeader(); this.RemarkColumnHeader = new System.Windows.Forms.ColumnHeader();
this.LinkColumnHeader = new System.Windows.Forms.ColumnHeader(); this.LinkColumnHeader = new System.Windows.Forms.ColumnHeader();
this.UserAgentHeader = new System.Windows.Forms.ColumnHeader(); this.UserAgentHeader = new System.Windows.Forms.ColumnHeader();
this.pContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components); this.pContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
this.DeleteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.DeleteToolStripMenuItem = 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.UseSelectedServerCheckBox = new System.Windows.Forms.CheckBox();
this.MainTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel(); this.MainTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
@@ -143,19 +145,29 @@
// SubscribeLinkListView // SubscribeLinkListView
// //
this.SubscribeLinkListView.AllowColumnReorder = true; this.SubscribeLinkListView.AllowColumnReorder = true;
this.SubscribeLinkListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {this.RemarkColumnHeader, this.LinkColumnHeader, this.UserAgentHeader}); this.SubscribeLinkListView.CheckBoxes = true;
this.SubscribeLinkListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[]
{
this.EnableColumnHeader, this.RemarkColumnHeader, this.LinkColumnHeader, this.UserAgentHeader
});
this.SubscribeLinkListView.Dock = System.Windows.Forms.DockStyle.Fill; this.SubscribeLinkListView.Dock = System.Windows.Forms.DockStyle.Fill;
this.SubscribeLinkListView.FullRowSelect = true; this.SubscribeLinkListView.FullRowSelect = true;
this.SubscribeLinkListView.HideSelection = false; this.SubscribeLinkListView.HideSelection = false;
this.SubscribeLinkListView.Location = new System.Drawing.Point(8, 8); this.SubscribeLinkListView.Location = new System.Drawing.Point(8, 8);
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, 200);
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;
this.SubscribeLinkListView.ItemChecked += new System.Windows.Forms.ItemCheckedEventHandler(this.SubscribeLinkListView_ItemChecked);
this.SubscribeLinkListView.SelectedIndexChanged += new System.EventHandler(this.SubscribeLinkListView_SelectedIndexChanged); this.SubscribeLinkListView.SelectedIndexChanged += new System.EventHandler(this.SubscribeLinkListView_SelectedIndexChanged);
this.SubscribeLinkListView.MouseUp += new System.Windows.Forms.MouseEventHandler(this.SubscribeLinkListView_MouseUp); this.SubscribeLinkListView.MouseUp += new System.Windows.Forms.MouseEventHandler(this.SubscribeLinkListView_MouseUp);
// //
// EnableColumnHeader
//
this.EnableColumnHeader.Text = "Status";
//
// RemarkColumnHeader // RemarkColumnHeader
// //
this.RemarkColumnHeader.Text = "Remark"; this.RemarkColumnHeader.Text = "Remark";
@@ -164,7 +176,7 @@
// LinkColumnHeader // LinkColumnHeader
// //
this.LinkColumnHeader.Text = "Link"; this.LinkColumnHeader.Text = "Link";
this.LinkColumnHeader.Width = 400; this.LinkColumnHeader.Width = 364;
// //
// UserAgentHeader // UserAgentHeader
// //
@@ -173,21 +185,31 @@
// //
// pContextMenuStrip // pContextMenuStrip
// //
this.pContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {this.DeleteToolStripMenuItem, this.CopyLinkToolStripMenuItem}); this.pContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[]
{
this.DeleteToolStripMenuItem, this.deleteServerToolStripMenuItem, this.CopyLinkToolStripMenuItem
});
this.pContextMenuStrip.Name = "pContextMenuStrip"; this.pContextMenuStrip.Name = "pContextMenuStrip";
this.pContextMenuStrip.Size = new System.Drawing.Size(130, 48); this.pContextMenuStrip.Size = new System.Drawing.Size(151, 70);
// //
// DeleteToolStripMenuItem // DeleteToolStripMenuItem
// //
this.DeleteToolStripMenuItem.Name = "DeleteToolStripMenuItem"; this.DeleteToolStripMenuItem.Name = "DeleteToolStripMenuItem";
this.DeleteToolStripMenuItem.Size = new System.Drawing.Size(129, 22); this.DeleteToolStripMenuItem.Size = new System.Drawing.Size(150, 22);
this.DeleteToolStripMenuItem.Text = "Delete"; this.DeleteToolStripMenuItem.Text = "Delete";
this.DeleteToolStripMenuItem.Click += new System.EventHandler(this.DeleteToolStripMenuItem_Click); this.DeleteToolStripMenuItem.Click += new System.EventHandler(this.DeleteToolStripMenuItem_Click);
// //
// deleteServerToolStripMenuItem
//
this.deleteServerToolStripMenuItem.Name = "deleteServerToolStripMenuItem";
this.deleteServerToolStripMenuItem.Size = new System.Drawing.Size(150, 22);
this.deleteServerToolStripMenuItem.Text = "DeleteServer";
this.deleteServerToolStripMenuItem.Click += new System.EventHandler(this.deleteServerToolStripMenuItem_Click);
//
// CopyLinkToolStripMenuItem // CopyLinkToolStripMenuItem
// //
this.CopyLinkToolStripMenuItem.Name = "CopyLinkToolStripMenuItem"; this.CopyLinkToolStripMenuItem.Name = "CopyLinkToolStripMenuItem";
this.CopyLinkToolStripMenuItem.Size = new System.Drawing.Size(129, 22); this.CopyLinkToolStripMenuItem.Size = new System.Drawing.Size(150, 22);
this.CopyLinkToolStripMenuItem.Text = "CopyLink"; this.CopyLinkToolStripMenuItem.Text = "CopyLink";
this.CopyLinkToolStripMenuItem.Click += new System.EventHandler(this.CopyLinkToolStripMenuItem_Click); this.CopyLinkToolStripMenuItem.Click += new System.EventHandler(this.CopyLinkToolStripMenuItem_Click);
// //
@@ -253,6 +275,7 @@
this.ControlsPanel.PerformLayout(); this.ControlsPanel.PerformLayout();
this.ResumeLayout(false); this.ResumeLayout(false);
} }
private System.Windows.Forms.ColumnHeader EnableColumnHeader;
private System.Windows.Forms.Panel ControlsPanel; private System.Windows.Forms.Panel ControlsPanel;
private System.Windows.Forms.TableLayoutPanel MainTableLayoutPanel; private System.Windows.Forms.TableLayoutPanel MainTableLayoutPanel;
@@ -275,5 +298,7 @@
private System.Windows.Forms.CheckBox UseSelectedServerCheckBox; private System.Windows.Forms.CheckBox UseSelectedServerCheckBox;
#endregion #endregion
private System.Windows.Forms.ToolStripMenuItem deleteServerToolStripMenuItem;
} }
} }

View File

@@ -21,12 +21,15 @@ namespace Netch.Forms
foreach (var item in Global.Settings.SubscribeLink) foreach (var item in Global.Settings.SubscribeLink)
{ {
SubscribeLinkListView.Items.Add(new ListViewItem(new[] var viewItem = new ListViewItem(new[]
{ {
"",
item.Remark, item.Remark,
item.Link, item.Link,
!string.IsNullOrEmpty(item.UserAgent) ? item.UserAgent : WebUtil.DefaultUserAgent !string.IsNullOrEmpty(item.UserAgent) ? item.UserAgent : WebUtil.DefaultUserAgent
})); });
viewItem.Checked = item.Enable;
SubscribeLinkListView.Items.Add(viewItem);
} }
} }
@@ -119,6 +122,7 @@ namespace Netch.Forms
Global.Settings.SubscribeLink.Add(new SubscribeLink Global.Settings.SubscribeLink.Add(new SubscribeLink
{ {
Enable = true,
Remark = RemarkTextBox.Text, Remark = RemarkTextBox.Text,
Link = LinkTextBox.Text, Link = LinkTextBox.Text,
UserAgent = UserAgentTextBox.Text UserAgent = UserAgentTextBox.Text
@@ -135,7 +139,9 @@ namespace Netch.Forms
{ {
RenameServersGroup(target.Remark, RemarkTextBox.Text); RenameServersGroup(target.Remark, RemarkTextBox.Text);
} }
ListViewItem listViewItem = SubscribeLinkListView.Items[_editingIndex];
target.Enable = listViewItem.Checked;
target.Link = LinkTextBox.Text; target.Link = LinkTextBox.Text;
target.Remark = RemarkTextBox.Text; target.Remark = RemarkTextBox.Text;
target.UserAgent = UserAgentTextBox.Text; target.UserAgent = UserAgentTextBox.Text;
@@ -173,31 +179,21 @@ namespace Netch.Forms
/// <param name="e"></param> /// <param name="e"></param>
private void SubscribeLinkListView_SelectedIndexChanged(object sender, EventArgs e) private void SubscribeLinkListView_SelectedIndexChanged(object sender, EventArgs e)
{ {
var editingCanOverwrite = true; var listView = (ListView) sender;
if (_editingIndex != -1) if (listView.SelectedItems.Count == 0)
{ {
var targetItem = SubscribeLinkListView.Items[_editingIndex].SubItems;
editingCanOverwrite = RemarkTextBox.Text == targetItem[0].Text &&
LinkTextBox.Text == targetItem[1].Text &&
UserAgentTextBox.Text == targetItem[2].Text;
}
if (SubscribeLinkListView.SelectedItems.Count == 1)
{
if (editingCanOverwrite)
{
SelectEditing(SubscribeLinkListView.SelectedItems[0].Index);
}
}
else if (SubscribeLinkListView.SelectedItems.Count > 1)
{
}
else if (editingCanOverwrite)
{
// 不选
// 重置 // 重置
ResetEditingGroup(); ResetEditingGroup();
return;
} }
_editingIndex = listView.SelectedItems[0].Index;
ListViewItem target = SubscribeLinkListView.Items[_editingIndex];
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) private void SubscribeLinkListView_MouseUp(object sender, MouseEventArgs e)
@@ -211,17 +207,6 @@ namespace Netch.Forms
} }
} }
private void SelectEditing(int index)
{
_editingIndex = index;
ListViewItem target;
target = SubscribeLinkListView.Items[index];
AddSubscriptionBox.Text = target.SubItems[0].Text;
RemarkTextBox.Text = target.SubItems[0].Text;
LinkTextBox.Text = target.SubItems[1].Text;
UserAgentTextBox.Text = target.SubItems[2].Text;
}
private void ResetEditingGroup() private void ResetEditingGroup()
{ {
_editingIndex = -1; _editingIndex = -1;
@@ -235,5 +220,36 @@ namespace Netch.Forms
{ {
ResetEditingGroup(); ResetEditingGroup();
} }
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];
if (MessageBoxX.Show(i18N.Translate("Confirm deletion?"), confirm: true) != DialogResult.OK)
return;
DeleteServersInGroup(item.SubItems[1].Text);
}
}
} }
} }

View File

@@ -4,7 +4,7 @@ using Netch.Utils;
namespace Netch.Models namespace Netch.Models
{ {
public class Server:ICloneable public class Server : ICloneable
{ {
/// <summary> /// <summary>
/// 备注 /// 备注
@@ -81,7 +81,7 @@ namespace Netch.Models
{ {
try try
{ {
return await Utils.Utils.TCPingAsync(destination, Port); return Global.Settings.ServerTCPing ? await Utils.Utils.TCPingAsync(destination, Port) : await Utils.Utils.ICMPing(destination, Port);
} }
catch (Exception) catch (Exception)
{ {

View File

@@ -1,6 +1,4 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
namespace Netch.Models namespace Netch.Models
{ {
@@ -68,7 +66,7 @@ namespace Netch.Models
public KcpConfig KcpConfig = new KcpConfig(); public KcpConfig KcpConfig = new KcpConfig();
public bool UseMux = true; public bool UseMux = false;
} }
public class AioDNSConfig public class AioDNSConfig
@@ -78,6 +76,8 @@ namespace Netch.Models
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";
} }
/// <summary> /// <summary>
@@ -85,6 +85,11 @@ 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>
@@ -155,6 +160,16 @@ namespace Netch.Models
/// </summary> /// </summary>
public int RequestTimeout = 10000; public int RequestTimeout = 10000;
/// <summary>
/// PAC URL
/// </summary>
public string Pac_Url = "";
/// <summary>
/// PAC端口
/// </summary>
public int Pac_Port = 2803;
/// <summary> /// <summary>
/// HTTP 本地端口 /// HTTP 本地端口
/// </summary> /// </summary>
@@ -240,6 +255,11 @@ namespace Netch.Models
/// </summary> /// </summary>
public string ACL = "https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/banAD.acl"; public string ACL = "https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/banAD.acl";
/// <summary>
/// GFWList
/// </summary>
public string PAC = "https://raw.githubusercontent.com/HMBSbige/Text_Translation/master/ShadowsocksR/ss_white.pac";
/// <summary> /// <summary>
/// 是否使用DLL启动Shadowsocks /// 是否使用DLL启动Shadowsocks
/// </summary> /// </summary>
@@ -250,12 +270,24 @@ namespace Netch.Models
/// </summary> /// </summary>
public string Language = "System"; public string Language = "System";
public V2rayConfig V2RayConfig = new V2rayConfig(); /// <summary>
/// 服务器测试方式 false.ICMPing true.TCPing
public AioDNSConfig AioDNS = new AioDNSConfig(); /// </summary>
public bool ServerTCPing = true;
/// <summary>
/// 是否使用RDR内置SS
/// </summary>
public bool RedirectorSS = false; public bool RedirectorSS = false;
/// <summary>
/// 不代理UDP
/// </summary>
public bool ProcessNoProxyForUdp = false; public bool ProcessNoProxyForUdp = false;
/// <summary>
/// 不代理TCP
/// </summary>
public bool ProcessNoProxyForTcp = false;
} }
} }

View File

@@ -2,6 +2,11 @@
{ {
public class SubscribeLink public class SubscribeLink
{ {
/// <summary>
/// 启用状态
/// </summary>
public bool Enable = true;
/// <summary> /// <summary>
/// 备注 /// 备注
/// </summary> /// </summary>
@@ -17,4 +22,4 @@
/// </summary> /// </summary>
public string UserAgent; public string UserAgent;
} }
} }

View File

@@ -28,30 +28,6 @@ namespace Netch
[DllImport("NetchCore", CallingConvention = CallingConvention.Cdecl, EntryPoint = "DeleteRoute")] [DllImport("NetchCore", 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);
/// <summary>
/// 设置直连
/// </summary>
/// <returns>是否成功</returns>
[DllImport("sysproxy", CallingConvention = CallingConvention.Cdecl)]
public static extern bool SetDIRECT();
/// <summary>
/// 设置全局
/// </summary>
/// <param name="remote">地址</param>
/// <param name="bypass">绕过</param>
/// <returns>是否成功</returns>
[DllImport("sysproxy", CallingConvention = CallingConvention.Cdecl)]
public static extern bool SetGlobal([MarshalAs(UnmanagedType.LPTStr)] string remote, [MarshalAs(UnmanagedType.LPTStr)] string bypass);
/// <summary>
/// 设置自动代理
/// </summary>
/// <param name="remote">URL</param>
/// <returns>是否成功</returns>
[DllImport("sysproxy", CallingConvention = CallingConvention.Cdecl)]
public static extern bool SetURL([MarshalAs(UnmanagedType.LPTStr)] string remote);
[DllImport("dnsapi", EntryPoint = "DnsFlushResolverCache")] [DllImport("dnsapi", EntryPoint = "DnsFlushResolverCache")]
public static extern uint FlushDNSResolverCache(); public static extern uint FlushDNSResolverCache();

View File

@@ -66,13 +66,14 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="ILMerge" Version="3.0.41" /> <PackageReference Include="ILMerge" Version="3.0.41" />
<PackageReference Include="MaxMind.GeoIP2" Version="3.3.0" /> <PackageReference Include="MaxMind.GeoIP2" Version="4.0.1" />
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="2.0.62" /> <PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="2.0.62" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="System.Collections.Immutable" Version="5.0.0" /> <PackageReference Include="System.Collections.Immutable" Version="5.0.0" />
<PackageReference Include="System.Reflection.Metadata" Version="5.0.0" /> <PackageReference Include="System.Reflection.Metadata" Version="5.0.0" />
<PackageReference Include="WindowsAPICodePack-Shell" Version="1.1.1" /> <PackageReference Include="WindowsAPICodePack-Shell" Version="1.1.1" />
<PackageReference Include="WindowsJobAPI" Version="5.0.0" /> <PackageReference Include="WindowsJobAPI" Version="5.0.1" />
<PackageReference Include="WindowsProxy" Version="5.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -60,6 +60,16 @@ namespace Netch.Properties {
} }
} }
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] abp_js {
get {
object obj = ResourceManager.GetObject("abp_js", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary> /// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap. /// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary> /// </summary>

View File

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

BIN
Netch/Resources/abp.js.gz Normal file

Binary file not shown.

View File

@@ -67,9 +67,16 @@
"Manage Subscribe Links": "管理订阅链接", "Manage Subscribe Links": "管理订阅链接",
"Update Servers From Subscribe Links": "从订阅链接更新服务器", "Update Servers From Subscribe Links": "从订阅链接更新服务器",
"No subscription link": "没有任何一条订阅链接", "No subscription link": "没有任何一条订阅链接",
"Updating in the background": "正在后台更新中", "Updating {0}": "正在更新 {0}",
"Update {1} server(s) from {0}": "从 {0} 更新 {1} 个服务器", "Update {1} server(s) from {0}": "从 {0} 更新 {1} 个服务器",
"Update servers error from {0}": "从 {0} 更新服务器失败", "Update servers error from {0}": "从 {0} 更新服务器失败",
"Delete the corresponding group of items in the server list?": "是否删除订阅对应服务器?",
"Confirm deletion?": "确认删除?",
"DeleteServer": "删除订阅节点",
"Status": "状态",
"Remark": "备注",
"Link": "链接",
"Unselect": "取消选择",
"Options": "选项", "Options": "选项",
"NF Service": "NF 服务", "NF Service": "NF 服务",
@@ -81,10 +88,16 @@
"Modes have been reload": "模式已重载", "Modes have been reload": "模式已重载",
"Clean DNS Cache": "清理 DNS 缓存", "Clean DNS Cache": "清理 DNS 缓存",
"DNS cache cleanup succeeded": "DNS 缓存清理成功", "DNS cache cleanup succeeded": "DNS 缓存清理成功",
"Update PAC": "更新 PAC",
"PAC updated successfully": "PAC 更新成功",
"PAC update failed": "PAC 更新失败",
"Update ACL": "更新 ACL 规则", "Update ACL": "更新 ACL 规则",
"Update ACL with proxy": "使用代理更新 ACL 规则", "Update ACL with proxy": "使用代理更新 ACL 规则",
"ACL updated successfully": "ACL 更新成功", "ACL updated successfully": "ACL 更新成功",
"ACL update failed": "ACL 更新失败", "ACL update failed": "ACL 更新失败",
"Open Directory": "打开目录", "Open Directory": "打开目录",
"About": "关于", "About": "关于",
@@ -116,6 +129,7 @@
"Add / Modify": "保存/修改", "Add / 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 ++正则表达式语法",
"Scan completed": "扫描完成", "Scan completed": "扫描完成",
"Mode added successfully": "模式添加成功", "Mode added successfully": "模式添加成功",
"Mode updated successfully": "模式修改成功", "Mode updated successfully": "模式修改成功",
@@ -156,6 +170,7 @@
"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流量",
"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 端口数值非法。请重试。",
@@ -164,6 +179,7 @@
"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": "启动后延迟测试",
"Enable": "启用", "Enable": "启用",
"ServerPingType": "测速方式",
"Detection interval(sec)": "检测间隔(秒)", "Detection interval(sec)": "检测间隔(秒)",
"STUN Server": "STUN 服务器", "STUN Server": "STUN 服务器",
"STUN Server Port": "STUN 服务器端口", "STUN Server Port": "STUN 服务器端口",

View File

@@ -1,7 +1,6 @@
using System.Text; using System.Text;
using Netch.Controllers; using Netch.Controllers;
using Netch.Models; using Netch.Models;
using Netch.Utils;
namespace Netch.Servers.ShadowsocksR namespace Netch.Servers.ShadowsocksR
{ {

View File

@@ -3,7 +3,6 @@ using System.IO;
using Netch.Controllers; using Netch.Controllers;
using Netch.Models; using Netch.Models;
using Netch.Servers.Trojan.Models; using Netch.Servers.Trojan.Models;
using Netch.Utils;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Netch.Servers.Trojan namespace Netch.Servers.Trojan
@@ -25,7 +24,7 @@ namespace Netch.Servers.Trojan
public bool Start(in Server s, in Mode mode) public bool Start(in Server s, in Mode mode)
{ {
var server = (Trojan) s; var server = (Trojan) s;
File.WriteAllText("data\\last.json", JsonConvert.SerializeObject(new TrojanConfig var trojanConfig = new TrojanConfig
{ {
local_addr = this.LocalAddress(), local_addr = this.LocalAddress(),
local_port = this.Socks5LocalPort(), local_port = this.Socks5LocalPort(),
@@ -35,8 +34,15 @@ namespace Netch.Servers.Trojan
{ {
server.Password server.Password
} }
})); };
if (!string.IsNullOrWhiteSpace(server.Host))
trojanConfig.ssl.sni = server.Host;
File.WriteAllText("data\\last.json", JsonConvert.SerializeObject(trojanConfig, Formatting.Indented, new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
}));
return StartInstanceAuto("-c ..\\data\\last.json"); return StartInstanceAuto("-c ..\\data\\last.json");
} }

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using Netch.Models;
using Netch.Servers.VMess; using Netch.Servers.VMess;
namespace Netch.Servers.VLESS namespace Netch.Servers.VLESS

View File

@@ -1,4 +1,3 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Netch.Models; using Netch.Models;
@@ -70,7 +69,7 @@ namespace Netch.Servers.VMess
/// <summary> /// <summary>
/// Mux 多路复用 /// Mux 多路复用
/// </summary> /// </summary>
public bool? UseMux { get; set; } = true; public bool? UseMux { get; set; } = false;
} }
public class VMessGlobal public class VMessGlobal

View File

@@ -1,5 +1,4 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -8,7 +7,6 @@ using Microsoft.Diagnostics.Tracing.Session;
using Netch.Controllers; using Netch.Controllers;
using Netch.Models; using Netch.Models;
using Netch.Servers.Shadowsocks; using Netch.Servers.Shadowsocks;
using Netch.Servers.Socks5;
namespace Netch.Utils namespace Netch.Utils
{ {
@@ -54,7 +52,7 @@ namespace Netch.Utils
/// <summary> /// <summary>
/// 根据程序名统计流量 /// 根据程序名统计流量
/// </summary> /// </summary>
public static void NetTraffic(in Server server, in Mode mode) public static void NetTraffic()
{ {
if (!Global.Flags.IsWindows10Upper) if (!Global.Flags.IsWindows10Upper)
return; return;
@@ -100,6 +98,13 @@ namespace Netch.Utils
Logging.Info("流量统计进程:" + string.Join(",", Logging.Info("流量统计进程:" + string.Join(",",
instances.Select(instance => $"({instance.Id})" + instance.ProcessName).ToArray())); instances.Select(instance => $"({instance.Id})" + instance.ProcessName).ToArray()));
received = 0;
if (!instances.Any())
return;
Global.MainForm.BandwidthState(true);
Task.Run(() => Task.Run(() =>
{ {
tSession = new TraceEventSession("KernelAndClrEventsSession"); tSession = new TraceEventSession("KernelAndClrEventsSession");

View File

@@ -0,0 +1,99 @@
using System;
using System.Net;
using System.Text;
using System.Threading;
namespace Netch.Utils.HttpProxyHandler
{
public class HttpWebServer
{
private HttpListener _listener;
private Func<HttpListenerRequest, string> _responderMethod;
public HttpWebServer(string[] prefixes, Func<HttpListenerRequest, string> method)
{
try
{
_listener = new HttpListener();
if (!HttpListener.IsSupported)
throw new NotSupportedException(
"Needs Windows XP SP2, Server 2003 or later.");
// URI prefixes are required, for example
// "http://localhost:8080/index/".
if (prefixes == null || prefixes.Length == 0)
throw new ArgumentException("prefixes");
// A responder method is required
if (method == null)
throw new ArgumentException("method");
foreach (string s in prefixes)
_listener.Prefixes.Add(s);
_responderMethod = method;
_listener.Start();
}
catch (Exception ex)
{
Logging.Error("HttpWebServer():" + ex.Message);
}
}
public HttpWebServer(Func<HttpListenerRequest, string> method, params string[] prefixes)
: this(prefixes, method)
{
}
public void Run()
{
ThreadPool.QueueUserWorkItem((o) =>
{
Logging.Info("Webserver running...");
try
{
while (_listener.IsListening)
{
ThreadPool.QueueUserWorkItem((c) =>
{
var ctx = c as HttpListenerContext;
try
{
string rstr = _responderMethod(ctx.Request);
byte[] buf = Encoding.UTF8.GetBytes(rstr);
ctx.Response.StatusCode = 200;
ctx.Response.ContentType = "application/x-ns-proxy-autoconfig";
ctx.Response.ContentLength64 = buf.Length;
ctx.Response.OutputStream.Write(buf, 0, buf.Length);
}
catch
{
} // suppress any exceptions
finally
{
// always close the stream
ctx.Response.OutputStream.Close();
}
}, _listener.GetContext());
}
}
catch (Exception ex)
{
//Logging.Error(ex.Message, ex);
Logging.Error(ex.Message);
} // suppress any exceptions
});
}
public void Stop()
{
if (_listener != null)
{
_listener.Stop();
_listener.Close();
_listener = null;
}
}
}
}

View File

@@ -0,0 +1,124 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using WindowsProxy;
namespace Netch.Utils.HttpProxyHandler
{
/// <summary>
/// 提供PAC功能支持
/// </summary>
class PACServerHandle
{
private static Hashtable httpWebServer = new Hashtable();
private static Hashtable pacList = new Hashtable();
public static void InitPACServer(string address)
{
try
{
if (!pacList.ContainsKey(address))
{
pacList.Add(address, GetPacList(address));
}
string prefixes = string.Format("http://{0}:{1}/pac/", address, Global.Settings.Pac_Port);
HttpWebServer ws = new HttpWebServer(SendResponse, prefixes);
ws.Run();
if (!httpWebServer.ContainsKey(address) && ws != null)
{
httpWebServer.Add(address, ws);
}
Global.Settings.Pac_Url = GetPacUrl();
using var service = new ProxyService
{
AutoConfigUrl = Global.Settings.Pac_Url
};
service.Pac();
Logging.Info(service.Set(service.Query()) + "");
Logging.Info($"Webserver InitServer OK: {Global.Settings.Pac_Url}");
}
catch (Exception ex)
{
Logging.Error("Webserver InitServer " + ex.Message);
}
}
public static string SendResponse(HttpListenerRequest request)
{
try
{
string[] arrAddress = request.UserHostAddress.Split(':');
string address = "127.0.0.1";
if (arrAddress.Length > 0)
{
address = arrAddress[0];
}
return pacList[address].ToString();
}
catch (Exception ex)
{
Logging.Error("Webserver SendResponse " + ex.Message);
return ex.Message;
}
}
public static void Stop()
{
try
{
if (httpWebServer == null)
{
return;
}
foreach (var key in httpWebServer.Keys)
{
Logging.Info("Webserver Stop " + key.ToString());
((HttpWebServer)httpWebServer[key]).Stop();
}
httpWebServer.Clear();
}
catch (Exception ex)
{
Logging.Error("Webserver Stop " + ex.Message);
}
}
private static string GetPacList(string address)
{
try
{
List<string> lstProxy = new List<string>();
lstProxy.Add(string.Format("PROXY {0}:{1};", address, Global.Settings.HTTPLocalPort));
var proxy = string.Join("", lstProxy.ToArray());
string strPacfile = Path.Combine(Global.NetchDir, $"bin\\pac.txt");
var pac = File.ReadAllText(strPacfile, Encoding.UTF8).Replace("__PROXY__", proxy);
return pac;
}
catch
{ }
return "No pac content";
}
/// <summary>
/// 获取PAC地址
/// </summary>
/// <returns></returns>
public static string GetPacUrl()
{
string pacUrl = string.Format("http://127.0.0.1:{0}/pac/?t={1}", Global.Settings.Pac_Port,
DateTime.Now.ToString("yyyyMMddHHmmssfff"));
return pacUrl;
}
}
}

View File

@@ -1,5 +1,4 @@
using System; using System;
using System.Linq;
using System.Management; using System.Management;
using Netch.Controllers; using Netch.Controllers;
using Netch.Models.WinFW; using Netch.Models.WinFW;

View File

@@ -13,7 +13,7 @@ namespace Netch.Utils
static ServerHelper() static ServerHelper()
{ {
var serversUtilsTypes = Assembly.GetExecutingAssembly().GetExportedTypes().Where(type => type.GetInterfaces().Any(t => t == typeof(IServerUtil))); var serversUtilsTypes = Assembly.GetExecutingAssembly().GetExportedTypes().Where(type => type.GetInterfaces().Contains(typeof(IServerUtil)));
ServerUtils = serversUtilsTypes.Select(t => (IServerUtil) Activator.CreateInstance(t)).OrderBy(util => util.Priority); ServerUtils = serversUtilsTypes.Select(t => (IServerUtil) Activator.CreateInstance(t)).OrderBy(util => util.Priority);
} }

View File

@@ -5,7 +5,6 @@ using System.Linq;
using System.Text; using System.Text;
using Netch.Servers.Shadowsocks; using Netch.Servers.Shadowsocks;
using Netch.Servers.Shadowsocks.Models; using Netch.Servers.Shadowsocks.Models;
using Netch.Servers.VMess;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Server = Netch.Models.Server; using Server = Netch.Models.Server;

46
Netch/Utils/StringEx.cs Normal file
View File

@@ -0,0 +1,46 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Netch.Utils
{
static class StringEx
{
public static bool IsNullOrEmpty(this string value)
{
return string.IsNullOrEmpty(value);
}
public static bool IsNullOrWhiteSpace(this string value)
{
return string.IsNullOrWhiteSpace(value);
}
public static bool BeginWithAny(this string s, IEnumerable<char> chars)
{
if (s.IsNullOrEmpty()) return false;
return chars.Contains(s[0]);
}
public static bool IsWhiteSpace(this string value)
{
foreach (var c in value)
{
if (char.IsWhiteSpace(c)) continue;
return false;
}
return true;
}
public static IEnumerable<string> NonWhiteSpaceLines(this TextReader reader)
{
string line;
while ((line = reader.ReadLine()) != null)
{
if (line.IsWhiteSpace()) continue;
yield return line;
}
}
}
}

View File

@@ -24,6 +24,10 @@ namespace Netch.Utils
{ {
try try
{ {
if (!item.Enable)
{
return;
}
var request = WebUtil.CreateRequest(item.Link); var request = WebUtil.CreateRequest(item.Link);
if (!string.IsNullOrEmpty(item.UserAgent)) request.UserAgent = item.UserAgent; if (!string.IsNullOrEmpty(item.UserAgent)) request.UserAgent = item.UserAgent;

View File

@@ -56,6 +56,18 @@ namespace Netch.Utils
return timeout; return timeout;
} }
public static async Task<int> ICMPing(IPAddress ip, int timeout = 1000)
{
var reply = new Ping().Send(ip, timeout);
if (reply?.Status == IPStatus.Success)
{
return Convert.ToInt32(reply.RoundtripTime);
}
return timeout;
}
public static string GetCityCode(string Hostname) public static string GetCityCode(string Hostname)
{ {
if (Hostname.Contains(":")) if (Hostname.Contains(":"))
@@ -204,6 +216,14 @@ namespace Netch.Utils
func.Invoke(component); func.Invoke(component);
switch (component) switch (component)
{ {
case ListView listView:
// ListView sub item
foreach (var item in listView.Columns.Cast<ColumnHeader>())
{
ComponentIterator(item, func);
}
break;
case ToolStripMenuItem toolStripMenuItem: case ToolStripMenuItem toolStripMenuItem:
// Iterator Menu strip sub item // Iterator Menu strip sub item
foreach (var item in toolStripMenuItem.DropDownItems.Cast<ToolStripItem>()) foreach (var item in toolStripMenuItem.DropDownItems.Cast<ToolStripItem>())

View File

@@ -121,6 +121,9 @@ namespace Netch.Utils
case ToolStripItem c: case ToolStripItem c:
c.Text = Translate(c.Text); c.Text = Translate(c.Text);
break; break;
case ColumnHeader c:
c.Text = Translate(c.Text);
break;
} }
}); });
} }

View File

@@ -5,7 +5,6 @@
[![Version](https://img.shields.io/github/v/release/NetchX/Netch)](https://github.com/NetchX/Netch/releases) [![Version](https://img.shields.io/github/v/release/NetchX/Netch)](https://github.com/NetchX/Netch/releases)
[![Downloads](https://img.shields.io/github/downloads/NetchX/Netch/total.svg)](https://github.com/NetchX/Netch/releases) [![Downloads](https://img.shields.io/github/downloads/NetchX/Netch/total.svg)](https://github.com/NetchX/Netch/releases)
[![Netch CI](https://github.com/NetchX/Netch/workflows/Netch%20CI/badge.svg)](https://github.com/NetchX/Netch/actions) [![Netch CI](https://github.com/NetchX/Netch/workflows/Netch%20CI/badge.svg)](https://github.com/NetchX/Netch/actions)
[![Website](https://img.shields.io/website?url=https%3A%2F%2Fnetch.org)](https://netch.org/)
[![License](https://img.shields.io/badge/license-MIT-yellow.svg)](LICENSE) [![License](https://img.shields.io/badge/license-MIT-yellow.svg)](LICENSE)
[中文说明](/docs/README.zh-CN.md) [中文说明](/docs/README.zh-CN.md)
@@ -63,6 +62,7 @@ As well, Netch avoid the restricted NAT problem caused by SSTap. You can use an
- [v2ray-core](https://github.com/v2ray/v2ray-core) - [v2ray-core](https://github.com/v2ray/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)
- [dnsmasq-china-list](https://github.com/felixonmars/dnsmasq-china-list) - [dnsmasq-china-list](https://github.com/felixonmars/dnsmasq-china-list)
- [tap-windows6](https://github.com/OpenVPN/tap-windows6) - [tap-windows6](https://github.com/OpenVPN/tap-windows6)
- [Privoxy](https://www.privoxy.org/) - [Privoxy](https://www.privoxy.org/)

View File

@@ -34,19 +34,21 @@
### 模式 1 进程代理模式 ### 模式 1 进程代理模式
- 根据进程名进行代理 - 根据进程名进行代理
- 底层依赖于 [NetFilter SDK](https://netfiltersdk.com) 和 Redirector.exe未开源 - 底层依赖于 [NetFilter SDK](https://netfiltersdk.com)
- 对于第一次使用 Netch 的用户而言,不需要做多余的事情 - 对于第一次使用 Netch 的用户而言,不需要做多余的事情
- 若 [NetFilter SDK](https://netfiltersdk.com) 的驱动不存在,会自动安装 - 若 [NetFilter SDK](https://netfiltersdk.com) 的驱动不存在,会自动安装
- 若驱动版本过低,会自动更新 - 若驱动版本过低,会自动更新
范例文件 范例文件
在这个模式里,第一行只有备注是有用的 在这个模式里,第一行只有备注是有用的规则内容支持C++正则表达式
``` ```
# 备注 # 备注
进程名 1会被代理 进程名 1会被代理
进程名 2 !进程名 2(不会被代理)
csgo.exe
\\steam\\代理运行路径包含steam的所有程序
... ...
``` ```
@@ -131,7 +133,7 @@
## Socks 5 代理中转 ## Socks 5 代理中转
说明一下Netch 并非是以网页代理为目的开发的程序,如果需要网络代理为目的的程序,需要 PAC规则分流订阅管理等功能的请参考使用以下软件而非 Netch均为 Windows 平台) 说明一下Netch 并非是以网页代理为目的开发的程序,如果需要网络代理为目的的程序,需要 PAC规则分流订阅管理等功能的尽量参考使用以下软件而非 Netch均为 Windows 平台)
ShadowsocksR ShadowsocksR

View File

@@ -5,7 +5,6 @@
[![版本](https://img.shields.io/github/v/release/NetchX/Netch)](https://github.com/NetchX/Netch/releases) [![版本](https://img.shields.io/github/v/release/NetchX/Netch)](https://github.com/NetchX/Netch/releases)
[![下载](https://img.shields.io/github/downloads/NetchX/Netch/total.svg)](https://github.com/NetchX/Netch/releases) [![下载](https://img.shields.io/github/downloads/NetchX/Netch/total.svg)](https://github.com/NetchX/Netch/releases)
[![Netch CI](https://github.com/NetchX/Netch/workflows/Netch%20CI/badge.svg)](https://github.com/NetchX/Netch/actions) [![Netch CI](https://github.com/NetchX/Netch/workflows/Netch%20CI/badge.svg)](https://github.com/NetchX/Netch/actions)
[![网站](https://img.shields.io/website?url=https%3A%2F%2Fnetch.org)](https://netch.org/)
[![License](https://img.shields.io/badge/license-MIT-yellow.svg)](LICENSE) [![License](https://img.shields.io/badge/license-MIT-yellow.svg)](LICENSE)
游戏加速工具 游戏加速工具
@@ -72,6 +71,7 @@ Netch 支持多种语言,在启动时会根据系统语言选择自身语言
- [v2ray-core](https://github.com/v2ray/v2ray-core) - [v2ray-core](https://github.com/v2ray/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)
- [dnsmasq-china-list](https://github.com/felixonmars/dnsmasq-china-list) - [dnsmasq-china-list](https://github.com/felixonmars/dnsmasq-china-list)
- [tap-windows6](https://github.com/OpenVPN/tap-windows6) - [tap-windows6](https://github.com/OpenVPN/tap-windows6)
- [Privoxy](https://www.privoxy.org/) - [Privoxy](https://www.privoxy.org/)

2
modes

Submodule modes updated: 90ffd0c66a...e3ae0d5406