mirror of
https://github.com/netchx/netch.git
synced 2026-03-14 17:43:18 +08:00
Make Task Analyzer Happy
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Netch.Interfaces;
|
||||
using static Netch.Interops.AioDNS;
|
||||
|
||||
@@ -9,9 +10,9 @@ namespace Netch.Controllers
|
||||
{
|
||||
public string Name => "DNS Service";
|
||||
|
||||
public void Stop()
|
||||
public async Task StopAsync()
|
||||
{
|
||||
Free();
|
||||
await FreeAsync();
|
||||
}
|
||||
|
||||
public void Start()
|
||||
|
||||
@@ -4,8 +4,8 @@ using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.Threading;
|
||||
using Netch.Models;
|
||||
using Netch.Utils;
|
||||
using Serilog;
|
||||
@@ -67,7 +67,7 @@ namespace Netch.Controllers
|
||||
Instance.Dispose();
|
||||
}
|
||||
|
||||
protected void StartGuard(string argument, ProcessPriorityClass priority = ProcessPriorityClass.Normal)
|
||||
protected async Task StartGuardAsync(string argument, ProcessPriorityClass priority = ProcessPriorityClass.Normal)
|
||||
{
|
||||
State = State.Starting;
|
||||
|
||||
@@ -82,8 +82,8 @@ namespace Netch.Controllers
|
||||
|
||||
if (RedirectOutput)
|
||||
{
|
||||
Task.Run(() => ReadOutput(Instance.StandardOutput));
|
||||
Task.Run(() => ReadOutput(Instance.StandardError));
|
||||
Task.Run(() => ReadOutput(Instance.StandardOutput)).Forget();
|
||||
Task.Run(() => ReadOutput(Instance.StandardError)).Forget();
|
||||
|
||||
if (!StartedKeywords.Any())
|
||||
{
|
||||
@@ -95,20 +95,20 @@ namespace Netch.Controllers
|
||||
// wait ReadOutput change State
|
||||
for (var i = 0; i < 1000; i++)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
await Task.Delay(50);
|
||||
switch (State)
|
||||
{
|
||||
case State.Started:
|
||||
OnStarted();
|
||||
return;
|
||||
case State.Stopped:
|
||||
StopGuard();
|
||||
await StopGuardAsync();
|
||||
OnStartFailed();
|
||||
throw new MessageException($"{Name} 控制器启动失败");
|
||||
}
|
||||
}
|
||||
|
||||
StopGuard();
|
||||
await StopGuardAsync();
|
||||
throw new MessageException($"{Name} 控制器启动超时");
|
||||
}
|
||||
}
|
||||
@@ -136,12 +136,12 @@ namespace Netch.Controllers
|
||||
State = State.Stopped;
|
||||
}
|
||||
|
||||
public virtual void Stop()
|
||||
public virtual async Task StopAsync()
|
||||
{
|
||||
StopGuard();
|
||||
await StopGuardAsync();
|
||||
}
|
||||
|
||||
protected void StopGuard()
|
||||
protected async Task StopGuardAsync()
|
||||
{
|
||||
_logStreamWriter?.Close();
|
||||
_logFileStream?.Close();
|
||||
@@ -151,7 +151,7 @@ namespace Netch.Controllers
|
||||
if (Instance is { HasExited: false })
|
||||
{
|
||||
Instance.Kill();
|
||||
Instance.WaitForExit();
|
||||
await Instance.WaitForExitAsync();
|
||||
}
|
||||
}
|
||||
catch (Win32Exception e)
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Netch.Controllers
|
||||
{
|
||||
Log.Information("启动主控制器: {Server} {Mode}", $"{server.Type}", $"[{(int) mode.Type}]{mode.Remark}");
|
||||
|
||||
if (DnsUtils.Lookup(server.Hostname) == null)
|
||||
if (await DnsUtils.LookupAsync(server.Hostname) == null)
|
||||
throw new MessageException(i18N.Translate("Lookup Server hostname failed"));
|
||||
|
||||
Mode = mode;
|
||||
@@ -45,9 +45,9 @@ namespace Netch.Controllers
|
||||
try
|
||||
{
|
||||
if (!ModeHelper.SkipServerController(server, mode))
|
||||
server = await Task.Run(() => StartServer(server));
|
||||
server = await StartServerAsync(server);
|
||||
|
||||
await Task.Run(() => StartMode(server, mode));
|
||||
await StartModeAsync(server, mode);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -67,7 +67,7 @@ namespace Netch.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
private static Server StartServer(Server server)
|
||||
private static async Task<Server> StartServerAsync(Server server)
|
||||
{
|
||||
ServerController = ServerHelper.GetUtilByTypeName(server.Type).GetController();
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace Netch.Controllers
|
||||
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ServerController.Name));
|
||||
|
||||
Log.Debug("Server Information: {Data}", $"{server.Type} {server.MaskedData()}");
|
||||
var socks5 = ServerController.Start(server);
|
||||
var socks5 = await ServerController.StartAsync(server);
|
||||
|
||||
StatusPortInfoText.Socks5Port = socks5.Port;
|
||||
StatusPortInfoText.UpdateShareLan();
|
||||
@@ -84,7 +84,7 @@ namespace Netch.Controllers
|
||||
return socks5;
|
||||
}
|
||||
|
||||
private static void StartMode(Server server, Mode mode)
|
||||
private static async Task StartModeAsync(Server server, Mode mode)
|
||||
{
|
||||
ModeController = ModeHelper.GetModeControllerByType(mode.Type, out var port, out var portName);
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace Netch.Controllers
|
||||
|
||||
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ModeController.Name));
|
||||
|
||||
ModeController.Start(server, mode);
|
||||
await ModeController.StartAsync(server, mode);
|
||||
}
|
||||
|
||||
public static async Task StopAsync()
|
||||
@@ -103,12 +103,12 @@ namespace Netch.Controllers
|
||||
|
||||
StatusPortInfoText.Reset();
|
||||
|
||||
Task.Run(() => NTTController.Stop()).Forget();
|
||||
Task.Run(() => NTTController.StopAsync()).Forget();
|
||||
|
||||
var tasks = new[]
|
||||
{
|
||||
Task.Run(() => ServerController?.Stop()),
|
||||
Task.Run(() => ModeController?.Stop())
|
||||
Task.Run(() => ServerController?.StopAsync()),
|
||||
Task.Run(() => ModeController?.StopAsync())
|
||||
};
|
||||
|
||||
try
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.ServiceProcess;
|
||||
using System.Threading.Tasks;
|
||||
using Netch.Interfaces;
|
||||
using Netch.Interops;
|
||||
using Netch.Models;
|
||||
@@ -27,7 +28,7 @@ namespace Netch.Controllers
|
||||
|
||||
public string Name => "Redirector";
|
||||
|
||||
public void Start(Server server, Mode mode)
|
||||
public async Task StartAsync(Server server, Mode mode)
|
||||
{
|
||||
_server = server;
|
||||
_mode = mode;
|
||||
@@ -43,7 +44,7 @@ namespace Netch.Controllers
|
||||
// Server
|
||||
Dial(NameList.TYPE_FILTERUDP, _rdrConfig.FilterProtocol.HasFlag(PortType.UDP).ToString().ToLower());
|
||||
Dial(NameList.TYPE_FILTERTCP, _rdrConfig.FilterProtocol.HasFlag(PortType.TCP).ToString().ToLower());
|
||||
dial_Server(_rdrConfig.FilterProtocol, _server);
|
||||
await DialServerAsync(_rdrConfig.FilterProtocol, _server);
|
||||
|
||||
// Mode Rule
|
||||
dial_Name(_mode);
|
||||
@@ -51,13 +52,13 @@ namespace Netch.Controllers
|
||||
// Features
|
||||
Dial(NameList.TYPE_DNSHOST, _rdrConfig.DNSHijack ? _rdrConfig.DNSHijackHost : "");
|
||||
|
||||
if (!Init())
|
||||
if (!await InitAsync())
|
||||
throw new MessageException("Redirector start failed.");
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
public async Task StopAsync()
|
||||
{
|
||||
Free();
|
||||
await FreeAsync();
|
||||
}
|
||||
|
||||
#region CheckRule
|
||||
@@ -102,12 +103,12 @@ namespace Netch.Controllers
|
||||
|
||||
#endregion
|
||||
|
||||
private void dial_Server(PortType portType, in Server server)
|
||||
private async Task DialServerAsync(PortType portType, Server server)
|
||||
{
|
||||
if (portType == PortType.Both)
|
||||
{
|
||||
dial_Server(PortType.TCP, server);
|
||||
dial_Server(PortType.UDP, server);
|
||||
await DialServerAsync(PortType.TCP, server);
|
||||
await DialServerAsync(PortType.UDP, server);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -116,7 +117,7 @@ namespace Netch.Controllers
|
||||
if (server is Socks5 socks5)
|
||||
{
|
||||
Dial(NameList.TYPE_TCPTYPE + offset, "Socks5");
|
||||
Dial(NameList.TYPE_TCPHOST + offset, $"{socks5.AutoResolveHostname()}:{socks5.Port}");
|
||||
Dial(NameList.TYPE_TCPHOST + offset, $"{await socks5.AutoResolveHostnameAsync()}:{socks5.Port}");
|
||||
Dial(NameList.TYPE_TCPUSER + offset, socks5.Username ?? string.Empty);
|
||||
Dial(NameList.TYPE_TCPPASS + offset, socks5.Password ?? string.Empty);
|
||||
Dial(NameList.TYPE_TCPMETH + offset, string.Empty);
|
||||
@@ -124,7 +125,7 @@ namespace Netch.Controllers
|
||||
else if (server is Shadowsocks shadowsocks && !shadowsocks.HasPlugin() && _rdrConfig.RedirectorSS)
|
||||
{
|
||||
Dial(NameList.TYPE_TCPTYPE + offset, "Shadowsocks");
|
||||
Dial(NameList.TYPE_TCPHOST + offset, $"{shadowsocks.AutoResolveHostname()}:{shadowsocks.Port}");
|
||||
Dial(NameList.TYPE_TCPHOST + offset, $"{await shadowsocks.AutoResolveHostnameAsync()}:{shadowsocks.Port}");
|
||||
Dial(NameList.TYPE_TCPMETH + offset, shadowsocks.EncryptMethod);
|
||||
Dial(NameList.TYPE_TCPPASS + offset, shadowsocks.Password);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Netch.Controllers
|
||||
/// 启动 NatTypeTester
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<(string? result, string? localEnd, string? publicEnd)> Start()
|
||||
public async Task<(string? result, string? localEnd, string? publicEnd)> StartAsync()
|
||||
{
|
||||
string? localEnd = null, publicEnd = null, result = null, bindingTest = null;
|
||||
|
||||
@@ -87,7 +87,7 @@ namespace Netch.Controllers
|
||||
Log.Error(e, "{Name} 控制器启动异常", Name);
|
||||
try
|
||||
{
|
||||
Stop();
|
||||
await StopAsync();
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.Threading;
|
||||
using Netch.Forms;
|
||||
using Netch.Interfaces;
|
||||
using Netch.Models;
|
||||
@@ -29,7 +30,7 @@ namespace Netch.Controllers
|
||||
|
||||
public override string Name => "pcap2socks";
|
||||
|
||||
public void Start(Server server, Mode mode)
|
||||
public async Task StartAsync(Server server, Mode mode)
|
||||
{
|
||||
_server = server;
|
||||
_mode = mode;
|
||||
@@ -38,18 +39,18 @@ namespace Netch.Controllers
|
||||
|
||||
var argument = new StringBuilder($@"-i \Device\NPF_{outboundNetworkInterface.Id}");
|
||||
if (_server is Socks5 socks5 && !socks5.Auth())
|
||||
argument.Append($" --destination {socks5.AutoResolveHostname()}:{socks5.Port}");
|
||||
argument.Append($" --destination {await socks5.AutoResolveHostnameAsync()}:{socks5.Port}");
|
||||
else
|
||||
argument.Append($" --destination 127.0.0.1:{Global.Settings.Socks5LocalPort}");
|
||||
|
||||
argument.Append($" {_mode.GetRules().FirstOrDefault() ?? "-P n"}");
|
||||
StartGuard(argument.ToString());
|
||||
await StartGuardAsync(argument.ToString());
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
public override async Task StopAsync()
|
||||
{
|
||||
Global.MainForm.Invoke(new Action(() => { _form.Close(); }));
|
||||
StopGuard();
|
||||
await StopGuardAsync();
|
||||
}
|
||||
|
||||
~PcapController()
|
||||
@@ -79,7 +80,7 @@ namespace Netch.Controllers
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
Utils.Utils.Open("https://github.com/zhxie/pcap2socks#dependencies");
|
||||
});
|
||||
}).Forget();
|
||||
|
||||
throw new MessageException("Pleases install pcap2socks's dependency");
|
||||
}
|
||||
|
||||
@@ -30,13 +30,13 @@ namespace Netch.Controllers
|
||||
|
||||
public string Name => "tun2socks";
|
||||
|
||||
public void Start(Server server, Mode mode)
|
||||
public async Task StartAsync(Server server, Mode mode)
|
||||
{
|
||||
_mode = mode;
|
||||
_tunConfig = Global.Settings.TUNTAP;
|
||||
|
||||
if (server is Socks5Bridge socks5Bridge)
|
||||
_serverRemoteAddress = DnsUtils.Lookup(socks5Bridge.RemoteHostname);
|
||||
_serverRemoteAddress = await DnsUtils.LookupAsync(socks5Bridge.RemoteHostname);
|
||||
|
||||
if (_serverRemoteAddress != null && IPAddress.IsLoopback(_serverRemoteAddress))
|
||||
_serverRemoteAddress = null;
|
||||
@@ -58,9 +58,9 @@ namespace Netch.Controllers
|
||||
|
||||
if (server is Socks5 socks5)
|
||||
{
|
||||
Dial(NameList.TYPE_TCPHOST, $"{socks5.AutoResolveHostname()}:{socks5.Port}");
|
||||
Dial(NameList.TYPE_TCPHOST, $"{await socks5.AutoResolveHostnameAsync()}:{socks5.Port}");
|
||||
|
||||
Dial(NameList.TYPE_UDPHOST, $"{socks5.AutoResolveHostname()}:{socks5.Port}");
|
||||
Dial(NameList.TYPE_UDPHOST, $"{await socks5.AutoResolveHostnameAsync()}:{socks5.Port}");
|
||||
|
||||
if (socks5.Auth())
|
||||
{
|
||||
@@ -106,16 +106,16 @@ namespace Netch.Controllers
|
||||
SetupRouteTable();
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
public async Task StopAsync()
|
||||
{
|
||||
var tasks = new[]
|
||||
{
|
||||
Task.Run(Free),
|
||||
FreeAsync(),
|
||||
Task.Run(ClearRouteTable),
|
||||
Task.Run(_aioDnsController.Stop)
|
||||
_aioDnsController.StopAsync()
|
||||
};
|
||||
|
||||
Task.WaitAll(tasks);
|
||||
await Task.WhenAll(tasks);
|
||||
}
|
||||
|
||||
private void CheckDriver()
|
||||
|
||||
@@ -37,14 +37,14 @@ namespace Netch.Controllers
|
||||
|
||||
public static event EventHandler? NewVersionNotFound;
|
||||
|
||||
public static async Task Check(bool isPreRelease)
|
||||
public static async Task CheckAsync(bool isPreRelease)
|
||||
{
|
||||
try
|
||||
{
|
||||
var updater = new GitHubRelease(Owner, Repo);
|
||||
var url = updater.AllReleaseUrl;
|
||||
|
||||
var json = await WebUtil.DownloadStringAsync(WebUtil.CreateRequest(url));
|
||||
var (_, json) = await WebUtil.DownloadStringAsync(WebUtil.CreateRequest(url));
|
||||
|
||||
var releases = JsonSerializer.Deserialize<List<Release>>(json)!;
|
||||
LatestRelease = GetLatestRelease(releases, isPreRelease);
|
||||
@@ -52,12 +52,12 @@ namespace Netch.Controllers
|
||||
if (VersionUtil.CompareVersion(LatestRelease.tag_name, Version) > 0)
|
||||
{
|
||||
Log.Information("发现新版本");
|
||||
NewVersionFound?.Invoke(null, new EventArgs());
|
||||
NewVersionFound?.Invoke(null, EventArgs.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Information("目前是最新版本");
|
||||
NewVersionNotFound?.Invoke(null, new EventArgs());
|
||||
NewVersionNotFound?.Invoke(null, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
@@ -93,23 +93,17 @@ namespace Netch.Forms
|
||||
// 加载快速配置
|
||||
LoadProfiles();
|
||||
|
||||
BeginInvoke(new Action(async () =>
|
||||
{
|
||||
// 检查更新
|
||||
if (Global.Settings.CheckUpdateWhenOpened)
|
||||
await CheckUpdate();
|
||||
}));
|
||||
// 检查更新
|
||||
if (Global.Settings.CheckUpdateWhenOpened)
|
||||
CheckUpdateAsync().Forget();
|
||||
|
||||
BeginInvoke(new Action(async () =>
|
||||
{
|
||||
// 检查订阅更新
|
||||
if (Global.Settings.UpdateServersWhenOpened)
|
||||
await UpdateServersFromSubscribe();
|
||||
// 检查订阅更新
|
||||
if (Global.Settings.UpdateServersWhenOpened)
|
||||
UpdateServersFromSubscribeAsync().Forget();
|
||||
|
||||
// 打开软件时启动加速,产生开始按钮点击事件
|
||||
if (Global.Settings.StartWhenOpened)
|
||||
ControlButton_Click(null, null);
|
||||
}));
|
||||
// 打开软件时启动加速,产生开始按钮点击事件
|
||||
if (Global.Settings.StartWhenOpened)
|
||||
ControlButton.PerformClick();
|
||||
|
||||
Netch.SingleInstance.ListenForArgumentsFromSuccessiveInstances();
|
||||
}
|
||||
@@ -275,10 +269,10 @@ namespace Netch.Forms
|
||||
|
||||
private async void UpdateServersFromSubscribeLinksToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
await UpdateServersFromSubscribe();
|
||||
await UpdateServersFromSubscribeAsync();
|
||||
}
|
||||
|
||||
private async Task UpdateServersFromSubscribe()
|
||||
private async Task UpdateServersFromSubscribeAsync()
|
||||
{
|
||||
void DisableItems(bool v)
|
||||
{
|
||||
@@ -333,7 +327,7 @@ namespace Netch.Forms
|
||||
{
|
||||
UpdateChecker.NewVersionNotFound += OnNewVersionNotFound;
|
||||
UpdateChecker.NewVersionFoundFailed += OnNewVersionFoundFailed;
|
||||
await CheckUpdate();
|
||||
await CheckUpdateAsync();
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -394,7 +388,6 @@ namespace Netch.Forms
|
||||
|
||||
private void ShowHideConsoleToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
var windowStyles = (WINDOW_STYLE)PInvoke.GetWindowLong(new HWND(Netch.ConsoleHwnd), WINDOW_LONG_PTR_INDEX.GWL_STYLE);
|
||||
var visible = windowStyles.HasFlag(WINDOW_STYLE.WS_VISIBLE);
|
||||
PInvoke.ShowWindow(Netch.ConsoleHwnd, visible ? SHOW_WINDOW_CMD.SW_HIDE : SHOW_WINDOW_CMD.SW_SHOWNOACTIVATE);
|
||||
@@ -468,7 +461,7 @@ namespace Netch.Forms
|
||||
}
|
||||
|
||||
ModeHelper.SuspendWatcher = true;
|
||||
await Stop();
|
||||
await StopAsync();
|
||||
await Configuration.SaveAsync();
|
||||
|
||||
// Update
|
||||
@@ -515,7 +508,7 @@ namespace Netch.Forms
|
||||
{
|
||||
if (!IsWaiting())
|
||||
{
|
||||
await StopCore();
|
||||
await StopCoreAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -551,28 +544,31 @@ namespace Netch.Forms
|
||||
State = State.Started;
|
||||
|
||||
Task.Run(Bandwidth.NetTraffic).Forget();
|
||||
Task.Run(NatTest).Forget();
|
||||
NatTestAsync().Forget();
|
||||
|
||||
if (Global.Settings.MinimizeWhenStarted)
|
||||
Minimize();
|
||||
|
||||
// 自动检测延迟
|
||||
Task.Run(() =>
|
||||
async Task StartedPingAsync()
|
||||
{
|
||||
while (State == State.Started)
|
||||
{
|
||||
while (State == State.Started)
|
||||
if (Global.Settings.StartedPingInterval >= 0)
|
||||
{
|
||||
server.Test();
|
||||
ServerComboBox.Refresh();
|
||||
if (Global.Settings.StartedPingInterval >= 0)
|
||||
{
|
||||
await server.PingAsync();
|
||||
ServerComboBox.Refresh();
|
||||
|
||||
Thread.Sleep(Global.Settings.StartedPingInterval * 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread.Sleep(5000);
|
||||
}
|
||||
})
|
||||
.Forget();
|
||||
await Task.Delay(Global.Settings.StartedPingInterval * 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
await Task.Delay(5000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StartedPingAsync().Forget();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -650,7 +646,7 @@ namespace Netch.Forms
|
||||
Show();
|
||||
}
|
||||
|
||||
private void SpeedPictureBox_Click(object sender, EventArgs e)
|
||||
private async void SpeedPictureBox_Click(object sender, EventArgs e)
|
||||
{
|
||||
void Enable()
|
||||
{
|
||||
@@ -664,19 +660,13 @@ namespace Netch.Forms
|
||||
|
||||
if (!IsWaiting() || ModifierKeys == Keys.Control)
|
||||
{
|
||||
(ServerComboBox.SelectedItem as Server)?.Test();
|
||||
(ServerComboBox.SelectedItem as Server)?.PingAsync();
|
||||
Enable();
|
||||
}
|
||||
else
|
||||
{
|
||||
ServerHelper.DelayTestHelper.TestDelayFinished += OnTestDelayFinished;
|
||||
Task.Run(ServerHelper.DelayTestHelper.TestAllDelay).Forget();
|
||||
|
||||
void OnTestDelayFinished(object? o1, EventArgs? e1)
|
||||
{
|
||||
ServerHelper.DelayTestHelper.TestDelayFinished -= OnTestDelayFinished;
|
||||
Enable();
|
||||
}
|
||||
await ServerHelper.DelayTestHelper.TestAllDelayAsync();
|
||||
Enable();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1057,15 +1047,15 @@ namespace Netch.Forms
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Stop()
|
||||
public async Task StopAsync()
|
||||
{
|
||||
if (IsWaiting())
|
||||
return;
|
||||
|
||||
await StopCore();
|
||||
await StopCoreAsync();
|
||||
}
|
||||
|
||||
private async Task StopCore()
|
||||
private async Task StopCoreAsync()
|
||||
{
|
||||
State = State.Stopping;
|
||||
await MainController.StopAsync();
|
||||
@@ -1172,7 +1162,7 @@ namespace Netch.Forms
|
||||
private async void NatTypeStatusLabel_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (_state == State.Started && !Monitor.IsEntered(_natTestLock))
|
||||
await NatTest();
|
||||
await NatTestAsync();
|
||||
}
|
||||
|
||||
private bool _natTestLock = true;
|
||||
@@ -1180,7 +1170,7 @@ namespace Netch.Forms
|
||||
/// <summary>
|
||||
/// 测试 NAT
|
||||
/// </summary>
|
||||
private async Task NatTest()
|
||||
private async Task NatTestAsync()
|
||||
{
|
||||
if (!MainController.Mode!.TestNatRequired())
|
||||
return;
|
||||
@@ -1194,11 +1184,11 @@ namespace Netch.Forms
|
||||
{
|
||||
NatTypeStatusText(i18N.Translate("Testing NAT"));
|
||||
|
||||
var (result, _, publicEnd) = await MainController.NTTController.Start();
|
||||
var (result, _, publicEnd) = await MainController.NTTController.StartAsync();
|
||||
|
||||
if (!string.IsNullOrEmpty(publicEnd))
|
||||
{
|
||||
var country = Utils.Utils.GetCityCode(publicEnd!);
|
||||
var country = await Utils.Utils.GetCityCodeAsync(publicEnd!);
|
||||
NatTypeStatusText(result, country);
|
||||
}
|
||||
else
|
||||
@@ -1285,7 +1275,7 @@ namespace Netch.Forms
|
||||
if (File.Exists(file))
|
||||
File.Delete(file);
|
||||
|
||||
await Stop();
|
||||
await StopAsync();
|
||||
|
||||
Dispose();
|
||||
Environment.Exit(Environment.ExitCode);
|
||||
@@ -1315,12 +1305,12 @@ namespace Netch.Forms
|
||||
|
||||
#region Updater
|
||||
|
||||
private async Task CheckUpdate()
|
||||
private async Task CheckUpdateAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
UpdateChecker.NewVersionFound += OnUpdateCheckerOnNewVersionFound;
|
||||
await UpdateChecker.Check(Global.Settings.CheckBetaUpdate);
|
||||
await UpdateChecker.CheckAsync(Global.Settings.CheckBetaUpdate);
|
||||
if (Flags.AlwaysShowNewVersionFound)
|
||||
OnUpdateCheckerOnNewVersionFound(null!, null!);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
namespace Netch.Interfaces
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Netch.Interfaces
|
||||
{
|
||||
public interface IController
|
||||
{
|
||||
public string Name { get; }
|
||||
|
||||
public void Stop();
|
||||
public Task StopAsync();
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
using System.Threading.Tasks;
|
||||
using Netch.Models;
|
||||
|
||||
namespace Netch.Interfaces
|
||||
{
|
||||
public interface IModeController : IController
|
||||
{
|
||||
public void Start(Server server, Mode mode);
|
||||
public Task StartAsync(Server server, Mode mode);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Netch.Models;
|
||||
using System.Threading.Tasks;
|
||||
using Netch.Models;
|
||||
using Netch.Servers;
|
||||
|
||||
namespace Netch.Interfaces
|
||||
@@ -9,7 +10,7 @@ namespace Netch.Interfaces
|
||||
|
||||
public string? LocalAddress { get; set; }
|
||||
|
||||
public Socks5 Start(in Server s);
|
||||
public Task<Socks5> StartAsync(Server s);
|
||||
}
|
||||
|
||||
public static class ServerControllerExtension
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Serilog;
|
||||
|
||||
namespace Netch.Interops
|
||||
@@ -14,6 +15,11 @@ namespace Netch.Interops
|
||||
return aiodns_dial(name, Encoding.UTF8.GetBytes(value));
|
||||
}
|
||||
|
||||
public static async Task FreeAsync()
|
||||
{
|
||||
await Task.Run(Free).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
[DllImport(aiodns_bin, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern bool aiodns_dial(NameList name, byte[] value);
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using Serilog;
|
||||
|
||||
namespace Netch.Interops
|
||||
@@ -47,14 +48,15 @@ namespace Netch.Interops
|
||||
return aio_dial(name, value);
|
||||
}
|
||||
|
||||
public static bool Init()
|
||||
public static async Task<bool> InitAsync()
|
||||
{
|
||||
return aio_init();
|
||||
return await Task.Run(aio_init).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public static bool Free()
|
||||
public static async Task<bool> FreeAsync()
|
||||
{
|
||||
return aio_free();
|
||||
|
||||
return await Task.Run(aio_free).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public const int UdpNameListOffset = (int)NameList.TYPE_UDPLISN - (int)NameList.TYPE_TCPLISN;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Serilog;
|
||||
|
||||
namespace Netch.Interops
|
||||
@@ -46,9 +47,9 @@ namespace Netch.Interops
|
||||
return tun_init();
|
||||
}
|
||||
|
||||
public static bool Free()
|
||||
public static async Task<bool> FreeAsync()
|
||||
{
|
||||
return tun_free();
|
||||
return await Task.Run(tun_free).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private const string tun2socks_bin = "tun2socks.bin";
|
||||
|
||||
@@ -48,7 +48,6 @@ namespace Netch.Models
|
||||
// ReSharper disable once CollectionNeverUpdated.Global
|
||||
public Dictionary<string, object> ExtensionData { get; set; } = new();
|
||||
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
return MemberwiseClone();
|
||||
@@ -68,39 +67,42 @@ namespace Netch.Models
|
||||
}
|
||||
|
||||
public abstract string MaskedData();
|
||||
|
||||
/// <summary>
|
||||
/// 测试延迟
|
||||
/// </summary>
|
||||
/// <returns>延迟</returns>
|
||||
public int Test()
|
||||
public async Task<int> PingAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var destination = DnsUtils.Lookup(Hostname);
|
||||
var destination = await DnsUtils.LookupAsync(Hostname);
|
||||
if (destination == null)
|
||||
return Delay = -2;
|
||||
|
||||
var list = new Task<int>[3];
|
||||
for (var i = 0; i < 3; i++)
|
||||
list[i] = Task.Run(async () =>
|
||||
{
|
||||
async Task<int> PingCoreAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
return Global.Settings.ServerTCPing
|
||||
? await Utils.Utils.TCPingAsync(destination, Port)
|
||||
: Utils.Utils.ICMPing(destination, Port);
|
||||
: await Utils.Utils.ICMPingAsync(destination);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return -4;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Task.WaitAll(list[0], list[1], list[2]);
|
||||
list[i] = PingCoreAsync();
|
||||
}
|
||||
|
||||
var min = Math.Min(list[0].Result, list[1].Result);
|
||||
min = Math.Min(min, list[2].Result);
|
||||
return Delay = min;
|
||||
var resTask = await Task.WhenAny(list[0], list[1], list[2]);
|
||||
|
||||
return Delay = await resTask;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -111,9 +113,9 @@ namespace Netch.Models
|
||||
|
||||
public static class ServerExtension
|
||||
{
|
||||
public static string AutoResolveHostname(this Server server)
|
||||
public static async Task<string> AutoResolveHostnameAsync(this Server server)
|
||||
{
|
||||
return Global.Settings.ResolveServerHostname ? DnsUtils.Lookup(server.Hostname)!.ToString() : server.Hostname;
|
||||
return Global.Settings.ResolveServerHostname ? (await DnsUtils.LookupAsync(server.Hostname))!.ToString() : server.Hostname;
|
||||
}
|
||||
|
||||
public static bool Valid(this Server server)
|
||||
|
||||
@@ -8,7 +8,7 @@ using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.Foundation;
|
||||
using Windows.Win32.UI.WindowsAndMessaging;
|
||||
using Microsoft.VisualStudio.Threading;
|
||||
using Netch.Controllers;
|
||||
using Netch.Forms;
|
||||
using Netch.Services;
|
||||
@@ -83,7 +83,7 @@ namespace Netch
|
||||
Environment.Exit(2);
|
||||
}
|
||||
|
||||
Task.Run(LogEnvironment);
|
||||
Task.Run(LogEnvironment).Forget();
|
||||
|
||||
// 绑定错误捕获
|
||||
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<IsPackable>false</IsPackable>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>VSTHRD002;VSTHRD200;VSTHRD100;VSTHRD101;VSTHRD110;VSTHRD130</NoWarn>
|
||||
<NoWarn>VSTHRD100</NoWarn>
|
||||
<EnableNETAnalyzers>false</EnableNETAnalyzers>
|
||||
<AnalysisMode>Default</AnalysisMode>
|
||||
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using Netch.Controllers;
|
||||
using Netch.Interfaces;
|
||||
using Netch.Models;
|
||||
@@ -22,13 +23,13 @@ namespace Netch.Servers.Shadowsocks
|
||||
|
||||
public string? LocalAddress { get; set; }
|
||||
|
||||
public Socks5 Start(in Server s)
|
||||
public async Task<Socks5> StartAsync(Server s)
|
||||
{
|
||||
var server = (Shadowsocks)s;
|
||||
|
||||
var command = new SSParameter
|
||||
{
|
||||
s = server.AutoResolveHostname(),
|
||||
s = await server.AutoResolveHostnameAsync(),
|
||||
p = server.Port,
|
||||
b = this.LocalAddress(),
|
||||
l = this.Socks5LocalPort(),
|
||||
@@ -39,7 +40,7 @@ namespace Netch.Servers.Shadowsocks
|
||||
plugin_opts = server.PluginOption
|
||||
};
|
||||
|
||||
StartGuard(command.ToString());
|
||||
await StartGuardAsync(command.ToString());
|
||||
return new Socks5Bridge(IPAddress.Loopback.ToString(), this.Socks5LocalPort(), server.Hostname);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using Netch.Controllers;
|
||||
using Netch.Interfaces;
|
||||
using Netch.Models;
|
||||
@@ -22,13 +23,13 @@ namespace Netch.Servers.ShadowsocksR
|
||||
|
||||
public string? LocalAddress { get; set; }
|
||||
|
||||
public Socks5 Start(in Server s)
|
||||
public async Task<Socks5> StartAsync(Server s)
|
||||
{
|
||||
var server = (ShadowsocksR)s;
|
||||
|
||||
var command = new SSRParameter
|
||||
{
|
||||
s = server.AutoResolveHostname(),
|
||||
s = await server.AutoResolveHostnameAsync(),
|
||||
p = server.Port,
|
||||
k = server.Password,
|
||||
m = server.EncryptMethod,
|
||||
@@ -42,7 +43,7 @@ namespace Netch.Servers.ShadowsocksR
|
||||
u = true
|
||||
};
|
||||
|
||||
StartGuard(command.ToString());
|
||||
await StartGuardAsync(command.ToString());
|
||||
return new Socks5Bridge(IPAddress.Loopback.ToString(), this.Socks5LocalPort(),server.Hostname);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System.Threading.Tasks;
|
||||
using Netch.Models;
|
||||
using Netch.Servers;
|
||||
|
||||
namespace Netch.Servers
|
||||
{
|
||||
@@ -7,11 +7,11 @@ namespace Netch.Servers
|
||||
{
|
||||
public override string Name { get; } = "Socks5";
|
||||
|
||||
public override Socks5 Start(in Server s)
|
||||
public override async Task<Socks5> StartAsync(Server s)
|
||||
{
|
||||
var server = (Socks5)s;
|
||||
if (server.Auth())
|
||||
base.Start(s);
|
||||
await base.StartAsync(s);
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Netch.Controllers;
|
||||
using Netch.Interfaces;
|
||||
using Netch.Models;
|
||||
@@ -26,14 +27,14 @@ namespace Netch.Servers
|
||||
|
||||
public string? LocalAddress { get; set; }
|
||||
|
||||
public Socks5 Start(in Server s)
|
||||
public async Task<Socks5> StartAsync(Server s)
|
||||
{
|
||||
var server = (Trojan)s;
|
||||
var trojanConfig = new TrojanConfig
|
||||
{
|
||||
local_addr = this.LocalAddress(),
|
||||
local_port = this.Socks5LocalPort(),
|
||||
remote_addr = server.AutoResolveHostname(),
|
||||
remote_addr = await server.AutoResolveHostnameAsync(),
|
||||
remote_port = server.Port,
|
||||
password = new List<string>
|
||||
{
|
||||
@@ -45,12 +46,12 @@ namespace Netch.Servers
|
||||
}
|
||||
};
|
||||
|
||||
using (var fileStream = new FileStream(Constants.TempConfig, FileMode.Create, FileAccess.Write))
|
||||
await using (var fileStream = new FileStream(Constants.TempConfig, FileMode.Create, FileAccess.Write, FileShare.Read))
|
||||
{
|
||||
JsonSerializer.SerializeAsync(fileStream, trojanConfig, Global.NewCustomJsonSerializerOptions()).Wait();
|
||||
await JsonSerializer.SerializeAsync(fileStream, trojanConfig, Global.NewCustomJsonSerializerOptions());
|
||||
}
|
||||
|
||||
StartGuard("-c ..\\data\\last.json");
|
||||
await StartGuardAsync("-c ..\\data\\last.json");
|
||||
return new Socks5Bridge(IPAddress.Loopback.ToString(), this.Socks5LocalPort(), server.Hostname);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
using Netch.Models;
|
||||
using System.Threading.Tasks;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.V2ray.Models;
|
||||
using Netch.Utils;
|
||||
using V2rayConfig = Netch.Servers.V2ray.Models.V2rayConfig;
|
||||
|
||||
#pragma warning disable VSTHRD200
|
||||
|
||||
namespace Netch.Servers.Utils
|
||||
{
|
||||
public static class V2rayConfigUtils
|
||||
{
|
||||
public static V2rayConfig GenerateClientConfig(Server server)
|
||||
public static async Task<V2rayConfig> GenerateClientConfigAsync(Server server)
|
||||
{
|
||||
var v2rayConfig = new V2rayConfig
|
||||
{
|
||||
@@ -26,12 +29,12 @@ namespace Netch.Servers.Utils
|
||||
}
|
||||
};
|
||||
|
||||
v2rayConfig.outbounds = new[] { outbound(server) };
|
||||
v2rayConfig.outbounds = new[] { await outbound(server) };
|
||||
|
||||
return v2rayConfig;
|
||||
}
|
||||
|
||||
private static Outbound outbound(Server server)
|
||||
private static async Task<Outbound> outbound(Server server)
|
||||
{
|
||||
var outbound = new Outbound
|
||||
{
|
||||
@@ -48,7 +51,7 @@ namespace Netch.Servers.Utils
|
||||
{
|
||||
new
|
||||
{
|
||||
address = server.AutoResolveHostname(),
|
||||
address = await server.AutoResolveHostnameAsync(),
|
||||
port = server.Port,
|
||||
users = socks5.Auth()
|
||||
? new[]
|
||||
@@ -75,7 +78,7 @@ namespace Netch.Servers.Utils
|
||||
{
|
||||
new VnextItem
|
||||
{
|
||||
address = server.AutoResolveHostname(),
|
||||
address = await server.AutoResolveHostnameAsync(),
|
||||
port = server.Port,
|
||||
users = new[]
|
||||
{
|
||||
@@ -111,7 +114,7 @@ namespace Netch.Servers.Utils
|
||||
{
|
||||
new VnextItem
|
||||
{
|
||||
address = server.AutoResolveHostname(),
|
||||
address = await server.AutoResolveHostnameAsync(),
|
||||
port = server.Port,
|
||||
users = new[]
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Netch.Controllers;
|
||||
using Netch.Interfaces;
|
||||
using Netch.Models;
|
||||
@@ -27,14 +28,14 @@ namespace Netch.Servers
|
||||
|
||||
public string? LocalAddress { get; set; }
|
||||
|
||||
public virtual Socks5 Start(in Server s)
|
||||
public virtual async Task<Socks5> StartAsync(Server s)
|
||||
{
|
||||
using (var fileStream = new FileStream(Constants.TempConfig, FileMode.Create, FileAccess.Write))
|
||||
using (var fileStream = new FileStream(Constants.TempConfig, FileMode.Create, FileAccess.Write, FileShare.Read))
|
||||
{
|
||||
JsonSerializer.SerializeAsync(fileStream, V2rayConfigUtils.GenerateClientConfig(s), Global.NewCustomJsonSerializerOptions()).Wait();
|
||||
await JsonSerializer.SerializeAsync(fileStream, await V2rayConfigUtils.GenerateClientConfigAsync(s), Global.NewCustomJsonSerializerOptions());
|
||||
}
|
||||
|
||||
StartGuard("-config ..\\data\\last.json");
|
||||
await StartGuardAsync("-config ..\\data\\last.json");
|
||||
return new Socks5Bridge(IPAddress.Loopback.ToString(), this.Socks5LocalPort(), s.Hostname);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Diagnostics.Tracing.Parsers;
|
||||
using Microsoft.Diagnostics.Tracing.Session;
|
||||
using Microsoft.VisualStudio.Threading;
|
||||
using Netch.Controllers;
|
||||
using Netch.Models;
|
||||
using Serilog;
|
||||
@@ -114,7 +115,7 @@ namespace Netch.Utils
|
||||
};
|
||||
|
||||
tSession.Source.Process();
|
||||
});
|
||||
}).Forget();
|
||||
|
||||
while (Global.MainForm.State != State.Stopped)
|
||||
{
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.Threading;
|
||||
using Netch.Models;
|
||||
@@ -46,11 +45,11 @@ namespace Netch.Utils
|
||||
return;
|
||||
}
|
||||
|
||||
if (await LoadAsyncCore(FileFullName))
|
||||
if (await LoadCoreAsync(FileFullName))
|
||||
return;
|
||||
|
||||
Log.Information("尝试加载备份配置文件 {FileName}", BackupFileFullName);
|
||||
await LoadAsyncCore(BackupFileFullName);
|
||||
await LoadCoreAsync(BackupFileFullName);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -59,7 +58,7 @@ namespace Netch.Utils
|
||||
}
|
||||
}
|
||||
|
||||
private static async ValueTask<bool> LoadAsyncCore(string filename)
|
||||
private static async ValueTask<bool> LoadCoreAsync(string filename)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -3,6 +3,8 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using Serilog;
|
||||
|
||||
namespace Netch.Utils
|
||||
{
|
||||
@@ -13,7 +15,7 @@ namespace Netch.Utils
|
||||
/// </summary>
|
||||
private static readonly Hashtable Cache = new();
|
||||
|
||||
public static IPAddress? Lookup(string hostname, int timeout = 3000)
|
||||
public static async Task<IPAddress?> LookupAsync(string hostname, int timeout = 3000)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -21,18 +23,26 @@ namespace Netch.Utils
|
||||
return Cache[hostname] as IPAddress;
|
||||
|
||||
var task = Dns.GetHostAddressesAsync(hostname);
|
||||
if (!task.Wait(timeout))
|
||||
return null;
|
||||
|
||||
if (task.Result.Length == 0)
|
||||
return null;
|
||||
var resTask = await Task.WhenAny(task, Task.Delay(timeout)).ConfigureAwait(false);
|
||||
|
||||
Cache.Add(hostname, task.Result[0]);
|
||||
if (resTask == task)
|
||||
{
|
||||
var result = await task;
|
||||
|
||||
return task.Result[0];
|
||||
if (result.Length == 0)
|
||||
return null;
|
||||
|
||||
Cache.Add(hostname, result[0]);
|
||||
|
||||
return result[0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Verbose(e, "Lookup hostname {Hostname} failed", hostname);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.Threading;
|
||||
using Netch.Interfaces;
|
||||
using Netch.Models;
|
||||
using Timer = System.Timers.Timer;
|
||||
@@ -33,6 +34,8 @@ namespace Netch.Utils
|
||||
private static readonly Timer Timer;
|
||||
private static readonly object TestAllLock = new();
|
||||
|
||||
private static readonly SemaphoreSlim SemaphoreSlim = new(1, 16);
|
||||
|
||||
public static readonly NumberRange Range = new(0, int.MaxValue / 1000);
|
||||
|
||||
static DelayTestHelper()
|
||||
@@ -43,7 +46,7 @@ namespace Netch.Utils
|
||||
AutoReset = true
|
||||
};
|
||||
|
||||
Timer.Elapsed += (_, _) => TestAllDelay();
|
||||
Timer.Elapsed += (_, _) => TestAllDelayAsync().Forget();
|
||||
}
|
||||
|
||||
public static bool Enabled
|
||||
@@ -65,17 +68,27 @@ namespace Netch.Utils
|
||||
return value != 0 && Range.InRange(value);
|
||||
}
|
||||
|
||||
public static event EventHandler? TestDelayFinished;
|
||||
|
||||
public static void TestAllDelay()
|
||||
public static async Task TestAllDelayAsync()
|
||||
{
|
||||
if (!Monitor.TryEnter(TestAllLock))
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
Parallel.ForEach(Global.Settings.Server, new ParallelOptions { MaxDegreeOfParallelism = 16 }, server => { server.Test(); });
|
||||
TestDelayFinished?.Invoke(null, new EventArgs());
|
||||
var tasks = Global.Settings.Server.Select(async s =>
|
||||
{
|
||||
await SemaphoreSlim.WaitAsync();
|
||||
try
|
||||
{
|
||||
await s.PingAsync();
|
||||
}
|
||||
finally
|
||||
{
|
||||
SemaphoreSlim.Release();
|
||||
}
|
||||
});
|
||||
|
||||
await Task.WhenAll(tasks);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -95,8 +108,9 @@ namespace Netch.Utils
|
||||
return;
|
||||
|
||||
Timer.Interval = Global.Settings.DetectionTick * 1000;
|
||||
Task.Run(TestAllDelay);
|
||||
Timer.Start();
|
||||
|
||||
TestAllDelayAsync().Forget();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using Netch.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using Netch.Models;
|
||||
using Serilog;
|
||||
|
||||
namespace Netch.Utils
|
||||
@@ -14,10 +14,10 @@ namespace Netch.Utils
|
||||
|
||||
public static async Task UpdateServersAsync(string? proxyServer = default)
|
||||
{
|
||||
await Task.WhenAll(Global.Settings.SubscribeLink.Select(item => Task.Run(() => UpdateServer(item, proxyServer))).ToArray());
|
||||
await Task.WhenAll(Global.Settings.SubscribeLink.Select(item => UpdateServerCoreAsync(item, proxyServer)));
|
||||
}
|
||||
|
||||
public static void UpdateServer(SubscribeLink item, string? proxyServer)
|
||||
private static async Task UpdateServerCoreAsync(SubscribeLink item, string? proxyServer)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -34,11 +34,11 @@ namespace Netch.Utils
|
||||
|
||||
List<Server> servers;
|
||||
|
||||
var result = WebUtil.DownloadString(request, out var rep);
|
||||
if (rep.StatusCode == HttpStatusCode.OK)
|
||||
var (code, result) = await WebUtil.DownloadStringAsync(request);
|
||||
if (code == HttpStatusCode.OK)
|
||||
servers = ShareLink.ParseText(result);
|
||||
else
|
||||
throw new Exception($"{item.Remark} Response Status Code: {rep.StatusCode}");
|
||||
throw new Exception($"{item.Remark} Response Status Code: {code}");
|
||||
|
||||
foreach (var server in servers)
|
||||
server.Group = item.Remark;
|
||||
|
||||
@@ -57,33 +57,34 @@ namespace Netch.Utils
|
||||
return timeout;
|
||||
}
|
||||
|
||||
public static int ICMPing(IPAddress ip, int timeout = 1000)
|
||||
public static async Task<int> ICMPingAsync(IPAddress ip, int timeout = 1000)
|
||||
{
|
||||
var reply = new Ping().Send(ip, timeout);
|
||||
var reply = await new Ping().SendPingAsync(ip, timeout);
|
||||
|
||||
if (reply?.Status == IPStatus.Success)
|
||||
if (reply.Status == IPStatus.Success)
|
||||
return Convert.ToInt32(reply.RoundtripTime);
|
||||
|
||||
return timeout;
|
||||
}
|
||||
|
||||
public static string GetCityCode(string Hostname)
|
||||
public static async Task<string> GetCityCodeAsync(string address)
|
||||
{
|
||||
if (Hostname.Contains(":"))
|
||||
Hostname = Hostname.Split(':')[0];
|
||||
var i = address.IndexOf(':');
|
||||
if (i != -1)
|
||||
address = address[..i];
|
||||
|
||||
string? country = null;
|
||||
try
|
||||
{
|
||||
var databaseReader = new DatabaseReader("bin\\GeoLite2-Country.mmdb");
|
||||
|
||||
if (IPAddress.TryParse(Hostname, out _))
|
||||
if (IPAddress.TryParse(address, out _))
|
||||
{
|
||||
country = databaseReader.Country(Hostname).Country.IsoCode;
|
||||
country = databaseReader.Country(address).Country.IsoCode;
|
||||
}
|
||||
else
|
||||
{
|
||||
var dnsResult = DnsUtils.Lookup(Hostname);
|
||||
var dnsResult = await DnsUtils.LookupAsync(address);
|
||||
|
||||
if (dnsResult != null)
|
||||
country = databaseReader.Country(dnsResult).Country.IsoCode;
|
||||
|
||||
@@ -38,9 +38,9 @@ namespace Netch.Utils
|
||||
/// <returns></returns>
|
||||
public static async Task<byte[]> DownloadBytesAsync(HttpWebRequest req)
|
||||
{
|
||||
using var webResponse = req.GetResponseAsync();
|
||||
using var webResponse = await req.GetResponseAsync();
|
||||
await using var memoryStream = new MemoryStream();
|
||||
await using var input = webResponse.Result.GetResponseStream();
|
||||
await using var input = webResponse.GetResponseStream();
|
||||
|
||||
await input.CopyToAsync(memoryStream);
|
||||
return memoryStream.ToArray();
|
||||
@@ -53,14 +53,14 @@ namespace Netch.Utils
|
||||
/// <param name="rep"></param>
|
||||
/// <param name="encoding">编码,默认UTF-8</param>
|
||||
/// <returns></returns>
|
||||
public static string DownloadString(HttpWebRequest req, out HttpWebResponse rep, Encoding? encoding = null)
|
||||
public static (HttpStatusCode, string) DownloadString(HttpWebRequest req, Encoding? encoding = null)
|
||||
{
|
||||
encoding ??= Encoding.UTF8;
|
||||
rep = (HttpWebResponse)req.GetResponse();
|
||||
using var rep = (HttpWebResponse)req.GetResponse();
|
||||
using var responseStream = rep.GetResponseStream();
|
||||
using var streamReader = new StreamReader(responseStream, encoding);
|
||||
|
||||
return streamReader.ReadToEnd();
|
||||
return (rep.StatusCode, streamReader.ReadToEnd());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -69,14 +69,14 @@ namespace Netch.Utils
|
||||
/// <param name="req"></param>
|
||||
/// <param name="encoding">编码,默认UTF-8</param>
|
||||
/// <returns></returns>
|
||||
public static async Task<string> DownloadStringAsync(HttpWebRequest req, Encoding? encoding = null)
|
||||
public static async Task<(HttpStatusCode, string)> DownloadStringAsync(HttpWebRequest req, Encoding? encoding = null)
|
||||
{
|
||||
encoding ??= Encoding.UTF8;
|
||||
using var webResponse = await req.GetResponseAsync();
|
||||
using var webResponse = (HttpWebResponse)await req.GetResponseAsync();
|
||||
await using var responseStream = webResponse.GetResponseStream();
|
||||
using var streamReader = new StreamReader(responseStream, encoding);
|
||||
|
||||
return await streamReader.ReadToEndAsync();
|
||||
return (webResponse.StatusCode, await streamReader.ReadToEndAsync());
|
||||
}
|
||||
|
||||
public static async Task DownloadFileAsync(string address, string fileFullPath, IProgress<int>? progress = null)
|
||||
@@ -92,7 +92,7 @@ namespace Netch.Utils
|
||||
using (var downloadTask = input.CopyToAsync(fileStream))
|
||||
{
|
||||
if (progress != null)
|
||||
ReportProgress(webResponse.ContentLength, downloadTask, fileStream, progress, 200).Forget();
|
||||
ReportProgressAsync(webResponse.ContentLength, downloadTask, fileStream, progress, 200).Forget();
|
||||
|
||||
await downloadTask;
|
||||
}
|
||||
@@ -100,7 +100,7 @@ namespace Netch.Utils
|
||||
progress?.Report(100);
|
||||
}
|
||||
|
||||
private static async Task ReportProgress(long total, IAsyncResult downloadTask, Stream stream, IProgress<int> progress, int interval)
|
||||
private static async Task ReportProgressAsync(long total, IAsyncResult downloadTask, Stream stream, IProgress<int> progress, int interval)
|
||||
{
|
||||
var n = 0;
|
||||
while (!downloadTask.IsCompleted)
|
||||
|
||||
Reference in New Issue
Block a user