mirror of
https://github.com/2dust/v2rayN.git
synced 2025-10-26 18:24:43 +00:00
Compare commits
4 commits
4104964e38
...
51ac7cc8be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
51ac7cc8be | ||
|
|
3144f1d1c2 | ||
|
|
a176e7b912 | ||
|
|
1198ec0f74 |
28 changed files with 494 additions and 391 deletions
|
|
@ -86,17 +86,43 @@ public static class ProcUtils
|
||||||
GetProcessKeyInfo(proc, review, out var procId, out var fileName, out var processName);
|
GetProcessKeyInfo(proc, review, out var procId, out var fileName, out var processName);
|
||||||
|
|
||||||
try
|
try
|
||||||
{ proc?.Kill(true); }
|
{
|
||||||
catch (Exception ex) { Logging.SaveLog(_tag, ex); }
|
if (Utils.IsNonWindows())
|
||||||
|
{
|
||||||
|
proc?.Kill(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.SaveLog(_tag, ex);
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{ proc?.Kill(); }
|
{
|
||||||
catch (Exception ex) { Logging.SaveLog(_tag, ex); }
|
proc?.Kill();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.SaveLog(_tag, ex);
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{ proc?.Close(); }
|
{
|
||||||
catch (Exception ex) { Logging.SaveLog(_tag, ex); }
|
proc?.Close();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.SaveLog(_tag, ex);
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{ proc?.Dispose(); }
|
{
|
||||||
catch (Exception ex) { Logging.SaveLog(_tag, ex); }
|
proc?.Dispose();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.SaveLog(_tag, ex);
|
||||||
|
}
|
||||||
|
|
||||||
await Task.Delay(300);
|
await Task.Delay(300);
|
||||||
await ProcessKillByKeyInfo(review, procId, fileName, processName);
|
await ProcessKillByKeyInfo(review, procId, fileName, processName);
|
||||||
|
|
|
||||||
|
|
@ -433,10 +433,22 @@ namespace ServiceLib.Common
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var ipProperties = IPGlobalProperties.GetIPGlobalProperties();
|
List<IPEndPoint> lstIpEndPoints = new();
|
||||||
var ipEndPoints = ipProperties.GetActiveTcpListeners();
|
List<TcpConnectionInformation> lstTcpConns = new();
|
||||||
//var lstIpEndPoints = new List<IPEndPoint>(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners());
|
|
||||||
return ipEndPoints.Any(endPoint => endPoint.Port == port);
|
lstIpEndPoints.AddRange(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners());
|
||||||
|
lstIpEndPoints.AddRange(IPGlobalProperties.GetIPGlobalProperties().GetActiveUdpListeners());
|
||||||
|
lstTcpConns.AddRange(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpConnections());
|
||||||
|
|
||||||
|
if (lstIpEndPoints?.FindIndex(it => it.Port == port) >= 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lstTcpConns?.FindIndex(it => it.LocalEndPoint.Port == port) >= 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
@ -786,6 +798,24 @@ namespace ServiceLib.Common
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string GetBinConfigPath(string filename = "")
|
||||||
|
{
|
||||||
|
var tempPath = Path.Combine(StartupPath(), "binConfigs");
|
||||||
|
if (!Directory.Exists(tempPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(tempPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Utils.IsNullOrEmpty(filename))
|
||||||
|
{
|
||||||
|
return tempPath;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Path.Combine(tempPath, filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion TempPath
|
#endregion TempPath
|
||||||
|
|
||||||
#region Platform
|
#region Platform
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ namespace ServiceLib
|
||||||
public const string ConfigFileName = "guiNConfig.json";
|
public const string ConfigFileName = "guiNConfig.json";
|
||||||
public const string CoreConfigFileName = "config.json";
|
public const string CoreConfigFileName = "config.json";
|
||||||
public const string CorePreConfigFileName = "configPre.json";
|
public const string CorePreConfigFileName = "configPre.json";
|
||||||
public const string CoreSpeedtestConfigFileName = "configSpeedtest.json";
|
public const string CoreSpeedtestConfigFileName = "configTest{0}.json";
|
||||||
public const string CoreMultipleLoadConfigFileName = "configMultipleLoad.json";
|
public const string CoreMultipleLoadConfigFileName = "configMultipleLoad.json";
|
||||||
public const string ClashMixinConfigFileName = "Mixin.yaml";
|
public const string ClashMixinConfigFileName = "Mixin.yaml";
|
||||||
|
|
||||||
|
|
@ -64,8 +64,6 @@ namespace ServiceLib
|
||||||
public const string GrpcGunMode = "gun";
|
public const string GrpcGunMode = "gun";
|
||||||
public const string GrpcMultiMode = "multi";
|
public const string GrpcMultiMode = "multi";
|
||||||
public const int MaxPort = 65536;
|
public const int MaxPort = 65536;
|
||||||
public const string DelayUnit = "";
|
|
||||||
public const string SpeedUnit = "";
|
|
||||||
public const int MinFontSize = 8;
|
public const int MinFontSize = 8;
|
||||||
public const string RebootAs = "rebootas";
|
public const string RebootAs = "rebootas";
|
||||||
public const string AvaAssets = "avares://v2rayN/Assets/";
|
public const string AvaAssets = "avares://v2rayN/Assets/";
|
||||||
|
|
@ -105,10 +103,10 @@ namespace ServiceLib
|
||||||
|
|
||||||
public static readonly List<string> SpeedTestUrls =
|
public static readonly List<string> SpeedTestUrls =
|
||||||
[
|
[
|
||||||
@"https://speed.cloudflare.com/__down?bytes=100000000",
|
@"https://cachefly.cachefly.net/50mb.test",
|
||||||
@"https://speed.cloudflare.com/__down?bytes=50000000",
|
|
||||||
@"https://speed.cloudflare.com/__down?bytes=10000000",
|
@"https://speed.cloudflare.com/__down?bytes=10000000",
|
||||||
@"https://cachefly.cachefly.net/50mb.test"
|
@"https://speed.cloudflare.com/__down?bytes=50000000",
|
||||||
|
@"https://speed.cloudflare.com/__down?bytes=100000000",
|
||||||
];
|
];
|
||||||
|
|
||||||
public static readonly List<string> SpeedPingTestUrls =
|
public static readonly List<string> SpeedPingTestUrls =
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
namespace ServiceLib.Handler
|
namespace ServiceLib.Handler
|
||||||
{
|
{
|
||||||
public sealed class AppHandler
|
public sealed class AppHandler
|
||||||
{
|
{
|
||||||
|
|
@ -98,6 +98,7 @@
|
||||||
{
|
{
|
||||||
FileManager.DeleteExpiredFiles(Utils.GetLogPath(), DateTime.Now.AddMonths(-1));
|
FileManager.DeleteExpiredFiles(Utils.GetLogPath(), DateTime.Now.AddMonths(-1));
|
||||||
FileManager.DeleteExpiredFiles(Utils.GetTempPath(), DateTime.Now.AddMonths(-1));
|
FileManager.DeleteExpiredFiles(Utils.GetTempPath(), DateTime.Now.AddMonths(-1));
|
||||||
|
FileManager.DeleteExpiredFiles(Utils.GetBinConfigPath(), DateTime.Now.AddHours(-1));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -252,4 +253,4 @@
|
||||||
|
|
||||||
#endregion Core Type
|
#endregion Core Type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -754,9 +754,9 @@ namespace ServiceLib.Handler
|
||||||
Security = t.Security,
|
Security = t.Security,
|
||||||
Network = t.Network,
|
Network = t.Network,
|
||||||
StreamSecurity = t.StreamSecurity,
|
StreamSecurity = t.StreamSecurity,
|
||||||
Delay = t33 == null ? 0 : t33.Delay,
|
Delay = t33?.Delay ?? 0,
|
||||||
Speed = t33 == null ? 0 : t33.Speed,
|
Speed = t33?.Speed ?? 0,
|
||||||
Sort = t33 == null ? 0 : t33.Sort
|
Sort = t33?.Sort ?? 0
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
Enum.TryParse(colName, true, out EServerColName name);
|
Enum.TryParse(colName, true, out EServerColName name);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
namespace ServiceLib.Handler
|
namespace ServiceLib.Handler
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Core configuration file processing class
|
/// Core configuration file processing class
|
||||||
|
|
@ -109,6 +109,30 @@
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async Task<RetResult> GenerateClientSpeedtestConfig(Config config, ProfileItem node, ServerTestItem testItem, string fileName)
|
||||||
|
{
|
||||||
|
var result = new RetResult();
|
||||||
|
var initPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.speedtest);
|
||||||
|
var port = Utils.GetFreePort(initPort + testItem.QueueNum);
|
||||||
|
testItem.Port = port;
|
||||||
|
|
||||||
|
if (AppHandler.Instance.GetCoreType(node, node.ConfigType) == ECoreType.sing_box)
|
||||||
|
{
|
||||||
|
result = await new CoreConfigSingboxService(config).GenerateClientSpeedtestConfig(node, port);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = await new CoreConfigV2rayService(config).GenerateClientSpeedtestConfig(node, port);
|
||||||
|
}
|
||||||
|
if (result.Success != true)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
await File.WriteAllTextAsync(fileName, result.Data.ToString());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public static async Task<RetResult> GenerateClientMultipleLoadConfig(Config config, string fileName, List<ProfileItem> selecteds, ECoreType coreType)
|
public static async Task<RetResult> GenerateClientMultipleLoadConfig(Config config, string fileName, List<ProfileItem> selecteds, ECoreType coreType)
|
||||||
{
|
{
|
||||||
var result = new RetResult();
|
var result = new RetResult();
|
||||||
|
|
@ -129,4 +153,4 @@
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ namespace ServiceLib.Handler
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var fileName = Utils.GetConfigPath(Global.CoreConfigFileName);
|
var fileName = Utils.GetBinConfigPath(Global.CoreConfigFileName);
|
||||||
var result = await CoreConfigHandler.GenerateClientConfig(node, fileName);
|
var result = await CoreConfigHandler.GenerateClientConfig(node, fileName);
|
||||||
if (result.Success != true)
|
if (result.Success != true)
|
||||||
{
|
{
|
||||||
|
|
@ -101,7 +101,8 @@ namespace ServiceLib.Handler
|
||||||
public async Task<int> LoadCoreConfigSpeedtest(List<ServerTestItem> selecteds)
|
public async Task<int> LoadCoreConfigSpeedtest(List<ServerTestItem> selecteds)
|
||||||
{
|
{
|
||||||
var coreType = selecteds.Exists(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard) ? ECoreType.sing_box : ECoreType.Xray;
|
var coreType = selecteds.Exists(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard) ? ECoreType.sing_box : ECoreType.Xray;
|
||||||
var configPath = Utils.GetConfigPath(Global.CoreSpeedtestConfigFileName);
|
var fileName = string.Format(Global.CoreSpeedtestConfigFileName, Utils.GetGuid(false));
|
||||||
|
var configPath = Utils.GetBinConfigPath(fileName);
|
||||||
var result = await CoreConfigHandler.GenerateClientSpeedtestConfig(_config, configPath, selecteds, coreType);
|
var result = await CoreConfigHandler.GenerateClientSpeedtestConfig(_config, configPath, selecteds, coreType);
|
||||||
UpdateFunc(false, result.Msg);
|
UpdateFunc(false, result.Msg);
|
||||||
if (result.Success != true)
|
if (result.Success != true)
|
||||||
|
|
@ -113,7 +114,34 @@ namespace ServiceLib.Handler
|
||||||
UpdateFunc(false, configPath);
|
UpdateFunc(false, configPath);
|
||||||
|
|
||||||
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType);
|
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType);
|
||||||
var proc = await RunProcess(coreInfo, Global.CoreSpeedtestConfigFileName, true, false);
|
var proc = await RunProcess(coreInfo, fileName, true, false);
|
||||||
|
if (proc is null)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return proc.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> LoadCoreConfigSpeedtest(ServerTestItem testItem)
|
||||||
|
{
|
||||||
|
var node = await AppHandler.Instance.GetProfileItem(testItem.IndexId);
|
||||||
|
if (node is null)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var fileName = string.Format(Global.CoreSpeedtestConfigFileName, Utils.GetGuid(false));
|
||||||
|
var configPath = Utils.GetBinConfigPath(fileName);
|
||||||
|
var result = await CoreConfigHandler.GenerateClientSpeedtestConfig(_config, node, testItem, configPath);
|
||||||
|
if (result.Success != true)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var coreType = AppHandler.Instance.GetCoreType(node, node.ConfigType);
|
||||||
|
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType);
|
||||||
|
var proc = await CoreHandler.Instance.RunProcess(coreInfo, fileName, true, false);
|
||||||
if (proc is null)
|
if (proc is null)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -175,7 +203,7 @@ namespace ServiceLib.Handler
|
||||||
if (itemSocks != null)
|
if (itemSocks != null)
|
||||||
{
|
{
|
||||||
var preCoreType = itemSocks.CoreType ?? ECoreType.sing_box;
|
var preCoreType = itemSocks.CoreType ?? ECoreType.sing_box;
|
||||||
var fileName = Utils.GetConfigPath(Global.CorePreConfigFileName);
|
var fileName = Utils.GetBinConfigPath(Global.CorePreConfigFileName);
|
||||||
var result = await CoreConfigHandler.GenerateClientConfig(itemSocks, fileName);
|
var result = await CoreConfigHandler.GenerateClientConfig(itemSocks, fileName);
|
||||||
if (result.Success)
|
if (result.Success)
|
||||||
{
|
{
|
||||||
|
|
@ -225,8 +253,8 @@ namespace ServiceLib.Handler
|
||||||
StartInfo = new()
|
StartInfo = new()
|
||||||
{
|
{
|
||||||
FileName = fileName,
|
FileName = fileName,
|
||||||
Arguments = string.Format(coreInfo.Arguments, coreInfo.AbsolutePath ? Utils.GetConfigPath(configPath) : configPath),
|
Arguments = string.Format(coreInfo.Arguments, coreInfo.AbsolutePath ? Utils.GetBinConfigPath(configPath) : configPath),
|
||||||
WorkingDirectory = Utils.GetConfigPath(),
|
WorkingDirectory = Utils.GetBinConfigPath(),
|
||||||
UseShellExecute = false,
|
UseShellExecute = false,
|
||||||
RedirectStandardOutput = displayLog,
|
RedirectStandardOutput = displayLog,
|
||||||
RedirectStandardError = displayLog,
|
RedirectStandardError = displayLog,
|
||||||
|
|
@ -298,7 +326,7 @@ namespace ServiceLib.Handler
|
||||||
|
|
||||||
private async Task RunProcessAsLinuxSudo(Process proc, string fileName, CoreInfo coreInfo, string configPath)
|
private async Task RunProcessAsLinuxSudo(Process proc, string fileName, CoreInfo coreInfo, string configPath)
|
||||||
{
|
{
|
||||||
var cmdLine = $"{fileName.AppendQuotes()} {string.Format(coreInfo.Arguments, Utils.GetConfigPath(configPath).AppendQuotes())}";
|
var cmdLine = $"{fileName.AppendQuotes()} {string.Format(coreInfo.Arguments, Utils.GetBinConfigPath(configPath).AppendQuotes())}";
|
||||||
|
|
||||||
var shFilePath = await CreateLinuxShellFile(cmdLine, "run_as_sudo.sh");
|
var shFilePath = await CreateLinuxShellFile(cmdLine, "run_as_sudo.sh");
|
||||||
proc.StartInfo.FileName = shFilePath;
|
proc.StartInfo.FileName = shFilePath;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
//using System.Reactive.Linq;
|
//using System.Reactive.Linq;
|
||||||
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace ServiceLib.Handler
|
||||||
{
|
{
|
||||||
private static readonly Lazy<ProfileExHandler> _instance = new(() => new());
|
private static readonly Lazy<ProfileExHandler> _instance = new(() => new());
|
||||||
private ConcurrentBag<ProfileExItem> _lstProfileEx = [];
|
private ConcurrentBag<ProfileExItem> _lstProfileEx = [];
|
||||||
private Queue<string> _queIndexIds = new();
|
private readonly Queue<string> _queIndexIds = new();
|
||||||
public static ProfileExHandler Instance => _instance.Value;
|
public static ProfileExHandler Instance => _instance.Value;
|
||||||
private static readonly string _tag = "ProfileExHandler";
|
private static readonly string _tag = "ProfileExHandler";
|
||||||
|
|
||||||
|
|
@ -59,7 +59,7 @@ namespace ServiceLib.Handler
|
||||||
List<ProfileExItem> lstInserts = [];
|
List<ProfileExItem> lstInserts = [];
|
||||||
List<ProfileExItem> lstUpdates = [];
|
List<ProfileExItem> lstUpdates = [];
|
||||||
|
|
||||||
for (int i = 0; i < cnt; i++)
|
for (var i = 0; i < cnt; i++)
|
||||||
{
|
{
|
||||||
var id = _queIndexIds.Dequeue();
|
var id = _queIndexIds.Dequeue();
|
||||||
var item = lstExists.FirstOrDefault(t => t.IndexId == id);
|
var item = lstExists.FirstOrDefault(t => t.IndexId == id);
|
||||||
|
|
@ -78,13 +78,18 @@ namespace ServiceLib.Handler
|
||||||
lstInserts.Add(itemNew);
|
lstInserts.Add(itemNew);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (lstInserts.Count() > 0)
|
if (lstInserts.Count > 0)
|
||||||
|
{
|
||||||
await SQLiteHelper.Instance.InsertAllAsync(lstInserts);
|
await SQLiteHelper.Instance.InsertAllAsync(lstInserts);
|
||||||
|
}
|
||||||
|
|
||||||
if (lstUpdates.Count() > 0)
|
if (lstUpdates.Count > 0)
|
||||||
|
{
|
||||||
await SQLiteHelper.Instance.UpdateAllAsync(lstUpdates);
|
await SQLiteHelper.Instance.UpdateAllAsync(lstUpdates);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
@ -93,17 +98,24 @@ namespace ServiceLib.Handler
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddProfileEx(string indexId, ref ProfileExItem? profileEx)
|
private ProfileExItem AddProfileEx(string indexId)
|
||||||
{
|
{
|
||||||
profileEx = new()
|
var profileEx = new ProfileExItem()
|
||||||
{
|
{
|
||||||
IndexId = indexId,
|
IndexId = indexId,
|
||||||
Delay = 0,
|
Delay = 0,
|
||||||
Speed = 0,
|
Speed = 0,
|
||||||
Sort = 0
|
Sort = 0,
|
||||||
|
Message = string.Empty
|
||||||
};
|
};
|
||||||
_lstProfileEx.Add(profileEx);
|
_lstProfileEx.Add(profileEx);
|
||||||
IndexIdEnqueue(indexId);
|
IndexIdEnqueue(indexId);
|
||||||
|
return profileEx;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ProfileExItem GetProfileExItem(string? indexId)
|
||||||
|
{
|
||||||
|
return _lstProfileEx.FirstOrDefault(t => t.IndexId == indexId) ?? AddProfileEx(indexId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task ClearAll()
|
public async Task ClearAll()
|
||||||
|
|
@ -124,39 +136,34 @@ namespace ServiceLib.Handler
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetTestDelay(string indexId, string delayVal)
|
public void SetTestDelay(string indexId, int delay)
|
||||||
{
|
{
|
||||||
var profileEx = _lstProfileEx.FirstOrDefault(t => t.IndexId == indexId);
|
var profileEx = GetProfileExItem(indexId);
|
||||||
if (profileEx == null)
|
|
||||||
{
|
|
||||||
AddProfileEx(indexId, ref profileEx);
|
|
||||||
}
|
|
||||||
|
|
||||||
int.TryParse(delayVal, out int delay);
|
|
||||||
profileEx.Delay = delay;
|
profileEx.Delay = delay;
|
||||||
IndexIdEnqueue(indexId);
|
IndexIdEnqueue(indexId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetTestSpeed(string indexId, string speedVal)
|
public void SetTestSpeed(string indexId, decimal speed)
|
||||||
{
|
{
|
||||||
var profileEx = _lstProfileEx.FirstOrDefault(t => t.IndexId == indexId);
|
var profileEx = GetProfileExItem(indexId);
|
||||||
if (profileEx == null)
|
|
||||||
{
|
|
||||||
AddProfileEx(indexId, ref profileEx);
|
|
||||||
}
|
|
||||||
|
|
||||||
decimal.TryParse(speedVal, out decimal speed);
|
|
||||||
profileEx.Speed = speed;
|
profileEx.Speed = speed;
|
||||||
IndexIdEnqueue(indexId);
|
IndexIdEnqueue(indexId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetTestMessage(string indexId, string message)
|
||||||
|
{
|
||||||
|
var profileEx = GetProfileExItem(indexId);
|
||||||
|
|
||||||
|
profileEx.Message = message;
|
||||||
|
IndexIdEnqueue(indexId);
|
||||||
|
}
|
||||||
|
|
||||||
public void SetSort(string indexId, int sort)
|
public void SetSort(string indexId, int sort)
|
||||||
{
|
{
|
||||||
var profileEx = _lstProfileEx.FirstOrDefault(t => t.IndexId == indexId);
|
var profileEx = GetProfileExItem(indexId);
|
||||||
if (profileEx == null)
|
|
||||||
{
|
|
||||||
AddProfileEx(indexId, ref profileEx);
|
|
||||||
}
|
|
||||||
profileEx.Sort = sort;
|
profileEx.Sort = sort;
|
||||||
IndexIdEnqueue(indexId);
|
IndexIdEnqueue(indexId);
|
||||||
}
|
}
|
||||||
|
|
@ -180,4 +187,4 @@ namespace ServiceLib.Handler
|
||||||
return _lstProfileEx.Max(t => t == null ? 0 : t.Sort);
|
return _lstProfileEx.Max(t => t == null ? 0 : t.Sort);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
namespace ServiceLib.Models
|
namespace ServiceLib.Models
|
||||||
{
|
{
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class CoreBasicItem
|
public class CoreBasicItem
|
||||||
|
|
@ -156,7 +156,6 @@
|
||||||
public int SpeedTestTimeout { get; set; }
|
public int SpeedTestTimeout { get; set; }
|
||||||
public string SpeedTestUrl { get; set; }
|
public string SpeedTestUrl { get; set; }
|
||||||
public string SpeedPingTestUrl { get; set; }
|
public string SpeedPingTestUrl { get; set; }
|
||||||
public int SpeedTestPageSize { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
|
|
@ -244,4 +243,4 @@
|
||||||
public string? Length { get; set; }
|
public string? Length { get; set; }
|
||||||
public string? Interval { get; set; }
|
public string? Interval { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
using SQLite;
|
using SQLite;
|
||||||
|
|
||||||
namespace ServiceLib.Models
|
namespace ServiceLib.Models
|
||||||
{
|
{
|
||||||
|
|
@ -11,5 +11,6 @@ namespace ServiceLib.Models
|
||||||
public int Delay { get; set; }
|
public int Delay { get; set; }
|
||||||
public decimal Speed { get; set; }
|
public decimal Speed { get; set; }
|
||||||
public int Sort { get; set; }
|
public int Sort { get; set; }
|
||||||
|
public string? Message { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
namespace ServiceLib.Models
|
namespace ServiceLib.Models
|
||||||
{
|
{
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class ServerTestItem
|
public class ServerTestItem
|
||||||
|
|
@ -8,6 +8,6 @@
|
||||||
public int Port { get; set; }
|
public int Port { get; set; }
|
||||||
public EConfigType ConfigType { get; set; }
|
public EConfigType ConfigType { get; set; }
|
||||||
public bool AllowTest { get; set; }
|
public bool AllowTest { get; set; }
|
||||||
public int Delay { get; set; }
|
public int QueueNum { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
11
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
11
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
|
|
@ -196,7 +196,7 @@ namespace ServiceLib.Resx {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Failed to run Core, please see the log 的本地化字符串。
|
/// 查找类似 Failed to run Core, please check the prompt information 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string FailedToRunCore {
|
public static string FailedToRunCore {
|
||||||
get {
|
get {
|
||||||
|
|
@ -3355,15 +3355,6 @@ namespace ServiceLib.Resx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查找类似 Number per time for auto batch during speedtest(max 1000) 的本地化字符串。
|
|
||||||
/// </summary>
|
|
||||||
public static string TbSettingsSpeedTestPageSize {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("TbSettingsSpeedTestPageSize", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 SpeedTest Single Timeout Value 的本地化字符串。
|
/// 查找类似 SpeedTest Single Timeout Value 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -1372,9 +1372,6 @@
|
||||||
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
||||||
<value>هنگام بستن پنجره در سینی پنهان شوید</value>
|
<value>هنگام بستن پنجره در سینی پنهان شوید</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
|
|
||||||
<value>تعداد در هر زمان برای دسته خودکار در طول تست سرعت (حداکثر 1000)</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
||||||
<value>موارد استثنا: از سرور پروکسی برای آدرس های زیر استفاده نکنید. برای جدا کردن ورودی ها از کاما (،) استفاده کنید.</value>
|
<value>موارد استثنا: از سرور پروکسی برای آدرس های زیر استفاده نکنید. برای جدا کردن ورودی ها از کاما (،) استفاده کنید.</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -1396,4 +1393,4 @@
|
||||||
<data name="SpeedtestingTestFailedPart" xml:space="preserve">
|
<data name="SpeedtestingTestFailedPart" xml:space="preserve">
|
||||||
<value>شروع آزمایش مجدد قطعات ناموفق، {0} باقی مانده است. برای خاتمه ESC را فشار دهید...</value>
|
<value>شروع آزمایش مجدد قطعات ناموفق، {0} باقی مانده است. برای خاتمه ESC را فشار دهید...</value>
|
||||||
</data>
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
@ -1372,9 +1372,6 @@
|
||||||
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
||||||
<value>Minimálás tálcára ablak zárásakor</value>
|
<value>Minimálás tálcára ablak zárásakor</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
|
|
||||||
<value>Szám / időszak az automatikus batch során a sebességvizsgálat során (maximum 1000)</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
||||||
<value>Kivétel. Ne használj proxy szervert a címeknél, évezz pontosvesszőt (,)</value>
|
<value>Kivétel. Ne használj proxy szervert a címeknél, évezz pontosvesszőt (,)</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
|
||||||
|
|
@ -926,7 +926,7 @@
|
||||||
<value>Speed(M/s)</value>
|
<value>Speed(M/s)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="FailedToRunCore" xml:space="preserve">
|
<data name="FailedToRunCore" xml:space="preserve">
|
||||||
<value>Failed to run Core, please see the log</value>
|
<value>Failed to run Core, please check the prompt information</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LvFilter" xml:space="preserve">
|
<data name="LvFilter" xml:space="preserve">
|
||||||
<value>Remarks regular filter</value>
|
<value>Remarks regular filter</value>
|
||||||
|
|
@ -1372,9 +1372,6 @@
|
||||||
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
||||||
<value>Hide to tray when closing the window</value>
|
<value>Hide to tray when closing the window</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
|
|
||||||
<value>Number per time for auto batch during speedtest(max 1000)</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
||||||
<value>Exclusions: Do not use proxy server for the following addresses. Use comma (,) to separate entries.</value>
|
<value>Exclusions: Do not use proxy server for the following addresses. Use comma (,) to separate entries.</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
|
||||||
|
|
@ -1372,9 +1372,6 @@
|
||||||
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
||||||
<value>Hide to tray when closing the window</value>
|
<value>Hide to tray when closing the window</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
|
|
||||||
<value>Number per time for auto batch during speedtest(max 1000)</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
||||||
<value>Exception. Do not use proxy server for addresses,with a comma (,)</value>
|
<value>Exception. Do not use proxy server for addresses,with a comma (,)</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
|
||||||
|
|
@ -926,7 +926,7 @@
|
||||||
<value>速度(M/s)</value>
|
<value>速度(M/s)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="FailedToRunCore" xml:space="preserve">
|
<data name="FailedToRunCore" xml:space="preserve">
|
||||||
<value>运行Core失败,请查看日志</value>
|
<value>运行 Core 失败,请查看提示信息</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LvFilter" xml:space="preserve">
|
<data name="LvFilter" xml:space="preserve">
|
||||||
<value>别名正则过滤</value>
|
<value>别名正则过滤</value>
|
||||||
|
|
@ -1369,9 +1369,6 @@
|
||||||
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
||||||
<value>关闭窗口时隐藏至托盘</value>
|
<value>关闭窗口时隐藏至托盘</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
|
|
||||||
<value>测试时自动分批的每批数量(最大1000)</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
||||||
<value>例外:对于下列地址不使用代理配置文件。使用逗号(,)分隔。</value>
|
<value>例外:对于下列地址不使用代理配置文件。使用逗号(,)分隔。</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
|
||||||
|
|
@ -927,7 +927,7 @@
|
||||||
<value>速度(M/s)</value>
|
<value>速度(M/s)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="FailedToRunCore" xml:space="preserve">
|
<data name="FailedToRunCore" xml:space="preserve">
|
||||||
<value>執行Core失敗,請查閲日誌</value>
|
<value>執行Core失敗,請查看提示訊息</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LvFilter" xml:space="preserve">
|
<data name="LvFilter" xml:space="preserve">
|
||||||
<value>別名正則過濾</value>
|
<value>別名正則過濾</value>
|
||||||
|
|
@ -1370,9 +1370,6 @@
|
||||||
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
||||||
<value>關閉視窗時隱藏至托盤</value>
|
<value>關閉視窗時隱藏至托盤</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
|
|
||||||
<value>測試時自動分批的每批數量(最大1000)</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
||||||
<value>例外:對於下列位址不使用代理設定檔,使用逗號(,)分隔。</value>
|
<value>例外:對於下列位址不使用代理設定檔,使用逗號(,)分隔。</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
|
||||||
|
|
@ -242,6 +242,66 @@ namespace ServiceLib.Services.CoreConfig
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<RetResult> GenerateClientSpeedtestConfig(ProfileItem node, int port)
|
||||||
|
{
|
||||||
|
var ret = new RetResult();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (node is not { Port: > 0 })
|
||||||
|
{
|
||||||
|
ret.Msg = ResUI.CheckServerSettings;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (node.GetNetwork() is nameof(ETransport.kcp) or nameof(ETransport.xhttp))
|
||||||
|
{
|
||||||
|
ret.Msg = ResUI.Incorrectconfiguration + $" - {node.GetNetwork()}";
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.Msg = ResUI.InitialConfiguration;
|
||||||
|
|
||||||
|
var result = EmbedUtils.GetEmbedText(Global.SingboxSampleClient);
|
||||||
|
if (Utils.IsNullOrEmpty(result))
|
||||||
|
{
|
||||||
|
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
var singboxConfig = JsonUtils.Deserialize<SingboxConfig>(result);
|
||||||
|
if (singboxConfig == null)
|
||||||
|
{
|
||||||
|
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
await GenLog(singboxConfig);
|
||||||
|
await GenOutbound(node, singboxConfig.outbounds.First());
|
||||||
|
await GenMoreOutbounds(node, singboxConfig);
|
||||||
|
await GenDnsDomains(null, singboxConfig, null);
|
||||||
|
|
||||||
|
singboxConfig.route.rules.Clear();
|
||||||
|
singboxConfig.inbounds.Clear();
|
||||||
|
singboxConfig.inbounds.Add(new()
|
||||||
|
{
|
||||||
|
tag = $"{EInboundProtocol.mixed}{port}",
|
||||||
|
listen = Global.Loopback,
|
||||||
|
listen_port = port,
|
||||||
|
type = EInboundProtocol.mixed.ToString(),
|
||||||
|
});
|
||||||
|
|
||||||
|
ret.Msg = string.Format(ResUI.SuccessfulConfiguration, "");
|
||||||
|
ret.Success = true;
|
||||||
|
ret.Data = JsonUtils.Serialize(singboxConfig);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.SaveLog(_tag, ex);
|
||||||
|
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<RetResult> GenerateClientMultipleLoadConfig(List<ProfileItem> selecteds)
|
public async Task<RetResult> GenerateClientMultipleLoadConfig(List<ProfileItem> selecteds)
|
||||||
{
|
{
|
||||||
var ret = new RetResult();
|
var ret = new RetResult();
|
||||||
|
|
@ -1264,7 +1324,7 @@ namespace ServiceLib.Services.CoreConfig
|
||||||
singboxConfig.experimental.cache_file = new CacheFile4Sbox()
|
singboxConfig.experimental.cache_file = new CacheFile4Sbox()
|
||||||
{
|
{
|
||||||
enabled = true,
|
enabled = true,
|
||||||
path = Utils.GetConfigPath("cache.db")
|
path = Utils.GetBinConfigPath("cache.db")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -353,6 +353,64 @@ namespace ServiceLib.Services.CoreConfig
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<RetResult> GenerateClientSpeedtestConfig(ProfileItem node, int port)
|
||||||
|
{
|
||||||
|
var ret = new RetResult();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (node is not { Port: > 0 })
|
||||||
|
{
|
||||||
|
ret.Msg = ResUI.CheckServerSettings;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.GetNetwork() is nameof(ETransport.quic))
|
||||||
|
{
|
||||||
|
ret.Msg = ResUI.Incorrectconfiguration + $" - {node.GetNetwork()}";
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = EmbedUtils.GetEmbedText(Global.V2raySampleClient);
|
||||||
|
if (Utils.IsNullOrEmpty(result))
|
||||||
|
{
|
||||||
|
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
var v2rayConfig = JsonUtils.Deserialize<V2rayConfig>(result);
|
||||||
|
if (v2rayConfig == null)
|
||||||
|
{
|
||||||
|
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
await GenLog(v2rayConfig);
|
||||||
|
await GenOutbound(node, v2rayConfig.outbounds.First());
|
||||||
|
await GenMoreOutbounds(node, v2rayConfig);
|
||||||
|
|
||||||
|
v2rayConfig.routing.rules.Clear();
|
||||||
|
v2rayConfig.inbounds.Clear();
|
||||||
|
v2rayConfig.inbounds.Add(new()
|
||||||
|
{
|
||||||
|
tag = $"{EInboundProtocol.socks}{port}",
|
||||||
|
listen = Global.Loopback,
|
||||||
|
port = port,
|
||||||
|
protocol = EInboundProtocol.socks.ToString(),
|
||||||
|
});
|
||||||
|
|
||||||
|
ret.Msg = string.Format(ResUI.SuccessfulConfiguration, "");
|
||||||
|
ret.Success = true;
|
||||||
|
ret.Data = JsonUtils.Serialize(v2rayConfig);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.SaveLog(_tag, ex);
|
||||||
|
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion public gen function
|
#endregion public gen function
|
||||||
|
|
||||||
#region private gen function
|
#region private gen function
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,11 @@ namespace ServiceLib.Services
|
||||||
{
|
{
|
||||||
Task.Run(async () =>
|
Task.Run(async () =>
|
||||||
{
|
{
|
||||||
var exitLoopKey = Utils.GetGuid(false);
|
await RunAsync(actionType, selecteds);
|
||||||
_lstExitLoop.Add(exitLoopKey);
|
await ProfileExHandler.Instance.SaveTo();
|
||||||
|
|
||||||
var lstSelected = GetClearItem(actionType, selecteds);
|
|
||||||
await RunAsync(actionType, lstSelected, exitLoopKey);
|
|
||||||
UpdateFunc("", ResUI.SpeedtestingCompleted);
|
UpdateFunc("", ResUI.SpeedtestingCompleted);
|
||||||
|
|
||||||
|
FileManager.DeleteExpiredFiles(Utils.GetBinConfigPath(), DateTime.Now.AddHours(-1));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -41,49 +40,30 @@ namespace ServiceLib.Services
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task RunAsync(ESpeedActionType actionType, List<ServerTestItem> lstSelected, string exitLoopKey, int pageSize = 0)
|
private async Task RunAsync(ESpeedActionType actionType, List<ProfileItem> selecteds)
|
||||||
{
|
{
|
||||||
if (actionType == ESpeedActionType.Tcping)
|
var exitLoopKey = Utils.GetGuid(false);
|
||||||
{
|
_lstExitLoop.Add(exitLoopKey);
|
||||||
await RunTcpingAsync(lstSelected);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pageSize <= 0)
|
var lstSelected = GetClearItem(actionType, selecteds);
|
||||||
{
|
|
||||||
pageSize = lstSelected.Count < Global.SpeedTestPageSize ? lstSelected.Count : Global.SpeedTestPageSize;
|
|
||||||
}
|
|
||||||
var lstTest = GetTestBatchItem(lstSelected, pageSize);
|
|
||||||
|
|
||||||
List<ServerTestItem> lstFailed = new();
|
switch (actionType)
|
||||||
foreach (var lst in lstTest)
|
|
||||||
{
|
{
|
||||||
var ret = actionType switch
|
case ESpeedActionType.Tcping:
|
||||||
{
|
await RunTcpingAsync(lstSelected);
|
||||||
ESpeedActionType.Realping => await RunRealPingAsync(lst, exitLoopKey),
|
break;
|
||||||
ESpeedActionType.Speedtest => await RunSpeedTestAsync(lst, exitLoopKey),
|
|
||||||
ESpeedActionType.Mixedtest => await RunMixedTestAsync(lst, exitLoopKey),
|
|
||||||
_ => true
|
|
||||||
};
|
|
||||||
if (ret == false)
|
|
||||||
{
|
|
||||||
lstFailed.AddRange(lst);
|
|
||||||
}
|
|
||||||
await Task.Delay(100);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Retest the failed part
|
case ESpeedActionType.Realping:
|
||||||
var pageSizeNext = pageSize / 2;
|
await RunRealPingBatchAsync(lstSelected, exitLoopKey);
|
||||||
if (lstFailed.Count > 0 && pageSizeNext > 0)
|
break;
|
||||||
{
|
|
||||||
if (_lstExitLoop.Any(p => p == exitLoopKey) == false)
|
|
||||||
{
|
|
||||||
UpdateFunc("", ResUI.SpeedtestingSkip);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateFunc("", string.Format(ResUI.SpeedtestingTestFailedPart, lstFailed.Count));
|
case ESpeedActionType.Speedtest:
|
||||||
await RunAsync(actionType, lstFailed, exitLoopKey, pageSizeNext);
|
await RunMixedTestAsync(lstSelected, 1, true, exitLoopKey);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ESpeedActionType.Mixedtest:
|
||||||
|
await RunMixedTestAsync(lstSelected, 6, true, exitLoopKey);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -107,7 +87,8 @@ namespace ServiceLib.Services
|
||||||
IndexId = it.IndexId,
|
IndexId = it.IndexId,
|
||||||
Address = it.Address,
|
Address = it.Address,
|
||||||
Port = it.Port,
|
Port = it.Port,
|
||||||
ConfigType = it.ConfigType
|
ConfigType = it.ConfigType,
|
||||||
|
QueueNum = selecteds.IndexOf(it)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -119,18 +100,18 @@ namespace ServiceLib.Services
|
||||||
case ESpeedActionType.Tcping:
|
case ESpeedActionType.Tcping:
|
||||||
case ESpeedActionType.Realping:
|
case ESpeedActionType.Realping:
|
||||||
UpdateFunc(it.IndexId, ResUI.Speedtesting, "");
|
UpdateFunc(it.IndexId, ResUI.Speedtesting, "");
|
||||||
ProfileExHandler.Instance.SetTestDelay(it.IndexId, "0");
|
ProfileExHandler.Instance.SetTestDelay(it.IndexId, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ESpeedActionType.Speedtest:
|
case ESpeedActionType.Speedtest:
|
||||||
UpdateFunc(it.IndexId, "", ResUI.SpeedtestingWait);
|
UpdateFunc(it.IndexId, "", ResUI.SpeedtestingWait);
|
||||||
ProfileExHandler.Instance.SetTestSpeed(it.IndexId, "0");
|
ProfileExHandler.Instance.SetTestSpeed(it.IndexId, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ESpeedActionType.Mixedtest:
|
case ESpeedActionType.Mixedtest:
|
||||||
UpdateFunc(it.IndexId, ResUI.Speedtesting, ResUI.SpeedtestingWait);
|
UpdateFunc(it.IndexId, ResUI.Speedtesting, ResUI.SpeedtestingWait);
|
||||||
ProfileExHandler.Instance.SetTestDelay(it.IndexId, "0");
|
ProfileExHandler.Instance.SetTestDelay(it.IndexId, 0);
|
||||||
ProfileExHandler.Instance.SetTestSpeed(it.IndexId, "0");
|
ProfileExHandler.Instance.SetTestSpeed(it.IndexId, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -138,60 +119,73 @@ namespace ServiceLib.Services
|
||||||
return lstSelected;
|
return lstSelected;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<List<ServerTestItem>> GetTestBatchItem(List<ServerTestItem> lstSelected, int pageSize)
|
|
||||||
{
|
|
||||||
List<List<ServerTestItem>> lstTest = new();
|
|
||||||
var lst1 = lstSelected.Where(t => t.ConfigType is not (EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard)).ToList();
|
|
||||||
var lst2 = lstSelected.Where(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard).ToList();
|
|
||||||
|
|
||||||
for (var num = 0; num < (int)Math.Ceiling(lst1.Count * 1.0 / pageSize); num++)
|
|
||||||
{
|
|
||||||
lstTest.Add(lst1.Skip(num * pageSize).Take(pageSize).ToList());
|
|
||||||
}
|
|
||||||
for (var num = 0; num < (int)Math.Ceiling(lst2.Count * 1.0 / pageSize); num++)
|
|
||||||
{
|
|
||||||
lstTest.Add(lst2.Skip(num * pageSize).Take(pageSize).ToList());
|
|
||||||
}
|
|
||||||
|
|
||||||
return lstTest;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task RunTcpingAsync(List<ServerTestItem> selecteds)
|
private async Task RunTcpingAsync(List<ServerTestItem> selecteds)
|
||||||
{
|
{
|
||||||
try
|
List<Task> tasks = [];
|
||||||
|
foreach (var it in selecteds)
|
||||||
{
|
{
|
||||||
List<Task> tasks = [];
|
if (it.ConfigType == EConfigType.Custom)
|
||||||
foreach (var it in selecteds)
|
|
||||||
{
|
{
|
||||||
if (it.ConfigType == EConfigType.Custom)
|
continue;
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
tasks.Add(Task.Run(async () =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var time = await GetTcpingTime(it.Address, it.Port);
|
|
||||||
var output = FormatOut(time, Global.DelayUnit);
|
|
||||||
|
|
||||||
ProfileExHandler.Instance.SetTestDelay(it.IndexId, output);
|
|
||||||
UpdateFunc(it.IndexId, output);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logging.SaveLog(_tag, ex);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
Task.WaitAll([.. tasks]);
|
tasks.Add(Task.Run(async () =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var responseTime = await GetTcpingTime(it.Address, it.Port);
|
||||||
|
|
||||||
|
ProfileExHandler.Instance.SetTestDelay(it.IndexId, responseTime);
|
||||||
|
UpdateFunc(it.IndexId, responseTime.ToString());
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.SaveLog(_tag, ex);
|
||||||
|
}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
Task.WaitAll([.. tasks]);
|
||||||
|
await Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task RunRealPingBatchAsync(List<ServerTestItem> lstSelected, string exitLoopKey, int pageSize = 0)
|
||||||
|
{
|
||||||
|
if (pageSize <= 0)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(_tag, ex);
|
pageSize = lstSelected.Count < Global.SpeedTestPageSize ? lstSelected.Count : Global.SpeedTestPageSize;
|
||||||
}
|
}
|
||||||
finally
|
var lstTest = GetTestBatchItem(lstSelected, pageSize);
|
||||||
|
|
||||||
|
List<ServerTestItem> lstFailed = new();
|
||||||
|
foreach (var lst in lstTest)
|
||||||
{
|
{
|
||||||
await ProfileExHandler.Instance.SaveTo();
|
var ret = await RunRealPingAsync(lst, exitLoopKey);
|
||||||
|
if (ret == false)
|
||||||
|
{
|
||||||
|
lstFailed.AddRange(lst);
|
||||||
|
}
|
||||||
|
await Task.Delay(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Retest the failed part
|
||||||
|
var pageSizeNext = pageSize / 2;
|
||||||
|
if (lstFailed.Count > 0 && pageSizeNext > 0)
|
||||||
|
{
|
||||||
|
if (_lstExitLoop.Any(p => p == exitLoopKey) == false)
|
||||||
|
{
|
||||||
|
UpdateFunc("", ResUI.SpeedtestingSkip);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateFunc("", string.Format(ResUI.SpeedtestingTestFailedPart, lstFailed.Count));
|
||||||
|
|
||||||
|
if (pageSizeNext > 6)
|
||||||
|
{
|
||||||
|
await RunRealPingBatchAsync(lstFailed, exitLoopKey, pageSizeNext);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await RunMixedTestAsync(lstSelected, 6, false, exitLoopKey);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -221,20 +215,7 @@ namespace ServiceLib.Services
|
||||||
}
|
}
|
||||||
tasks.Add(Task.Run(async () =>
|
tasks.Add(Task.Run(async () =>
|
||||||
{
|
{
|
||||||
try
|
await DoRealPing(downloadHandle, it);
|
||||||
{
|
|
||||||
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
|
|
||||||
var output = await GetRealPingTime(downloadHandle, webProxy);
|
|
||||||
|
|
||||||
ProfileExHandler.Instance.SetTestDelay(it.IndexId, output);
|
|
||||||
UpdateFunc(it.IndexId, output);
|
|
||||||
int.TryParse(output, out var delay);
|
|
||||||
it.Delay = delay;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logging.SaveLog(_tag, ex);
|
|
||||||
}
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
Task.WaitAll(tasks.ToArray());
|
Task.WaitAll(tasks.ToArray());
|
||||||
|
|
@ -249,25 +230,15 @@ namespace ServiceLib.Services
|
||||||
{
|
{
|
||||||
await ProcUtils.ProcessKill(pid);
|
await ProcUtils.ProcessKill(pid);
|
||||||
}
|
}
|
||||||
await ProfileExHandler.Instance.SaveTo();
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> RunSpeedTestAsync(List<ServerTestItem> selecteds, string exitLoopKey)
|
private async Task RunMixedTestAsync(List<ServerTestItem> selecteds, int concurrencyCount, bool blSpeedTest, string exitLoopKey)
|
||||||
{
|
{
|
||||||
var pid = -1;
|
using var concurrencySemaphore = new SemaphoreSlim(concurrencyCount);
|
||||||
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(selecteds);
|
var downloadHandle = new DownloadService();
|
||||||
if (pid < 0)
|
List<Task> tasks = new();
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var url = _config.SpeedTestItem.SpeedTestUrl;
|
|
||||||
var timeout = _config.SpeedTestItem.SpeedTestTimeout;
|
|
||||||
|
|
||||||
DownloadService downloadHandle = new();
|
|
||||||
|
|
||||||
foreach (var it in selecteds)
|
foreach (var it in selecteds)
|
||||||
{
|
{
|
||||||
if (_lstExitLoop.Any(p => p == exitLoopKey) == false)
|
if (_lstExitLoop.Any(p => p == exitLoopKey) == false)
|
||||||
|
|
@ -275,135 +246,74 @@ namespace ServiceLib.Services
|
||||||
UpdateFunc(it.IndexId, "", ResUI.SpeedtestingSkip);
|
UpdateFunc(it.IndexId, "", ResUI.SpeedtestingSkip);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!it.AllowTest)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (it.ConfigType == EConfigType.Custom)
|
if (it.ConfigType == EConfigType.Custom)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//if (it.delay < 0)
|
await concurrencySemaphore.WaitAsync();
|
||||||
//{
|
|
||||||
// UpdateFunc(it.indexId, "", ResUI.SpeedtestingSkip);
|
|
||||||
// continue;
|
|
||||||
//}
|
|
||||||
ProfileExHandler.Instance.SetTestSpeed(it.IndexId, "-1");
|
|
||||||
UpdateFunc(it.IndexId, "", ResUI.Speedtesting);
|
|
||||||
|
|
||||||
var item = await AppHandler.Instance.GetProfileItem(it.IndexId);
|
tasks.Add(Task.Run(async () =>
|
||||||
if (item is null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
|
|
||||||
|
|
||||||
await downloadHandle.DownloadDataAsync(url, webProxy, timeout, (success, msg) =>
|
|
||||||
{
|
{
|
||||||
decimal.TryParse(msg, out var dec);
|
var pid = -1;
|
||||||
if (dec > 0)
|
try
|
||||||
{
|
{
|
||||||
ProfileExHandler.Instance.SetTestSpeed(it.IndexId, msg);
|
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(it);
|
||||||
|
if (pid > 0)
|
||||||
|
{
|
||||||
|
await Task.Delay(500);
|
||||||
|
await DoRealPing(downloadHandle, it);
|
||||||
|
if (blSpeedTest)
|
||||||
|
{
|
||||||
|
await DoSpeedTest(downloadHandle, it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UpdateFunc(it.IndexId, "", ResUI.FailedToRunCore);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
UpdateFunc(it.IndexId, "", msg);
|
catch (Exception ex)
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pid > 0)
|
|
||||||
{
|
|
||||||
await ProcUtils.ProcessKill(pid);
|
|
||||||
}
|
|
||||||
await ProfileExHandler.Instance.SaveTo();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<bool> RunSpeedTestMultiAsync(List<ServerTestItem> selecteds, string exitLoopKey)
|
|
||||||
{
|
|
||||||
var pid = -1;
|
|
||||||
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(selecteds);
|
|
||||||
if (pid < 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var url = _config.SpeedTestItem.SpeedTestUrl;
|
|
||||||
var timeout = _config.SpeedTestItem.SpeedTestTimeout;
|
|
||||||
|
|
||||||
DownloadService downloadHandle = new();
|
|
||||||
|
|
||||||
foreach (var it in selecteds)
|
|
||||||
{
|
|
||||||
if (_lstExitLoop.Any(p => p == exitLoopKey) == false)
|
|
||||||
{
|
|
||||||
UpdateFunc(it.IndexId, "", ResUI.SpeedtestingSkip);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!it.AllowTest)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (it.ConfigType == EConfigType.Custom)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (it.Delay < 0)
|
|
||||||
{
|
|
||||||
UpdateFunc(it.IndexId, "", ResUI.SpeedtestingSkip);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ProfileExHandler.Instance.SetTestSpeed(it.IndexId, "-1");
|
|
||||||
UpdateFunc(it.IndexId, "", ResUI.Speedtesting);
|
|
||||||
|
|
||||||
var item = await AppHandler.Instance.GetProfileItem(it.IndexId);
|
|
||||||
if (item is null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
|
|
||||||
_ = downloadHandle.DownloadDataAsync(url, webProxy, timeout, (success, msg) =>
|
|
||||||
{
|
|
||||||
decimal.TryParse(msg, out var dec);
|
|
||||||
if (dec > 0)
|
|
||||||
{
|
{
|
||||||
ProfileExHandler.Instance.SetTestSpeed(it.IndexId, msg);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
UpdateFunc(it.IndexId, "", msg);
|
finally
|
||||||
});
|
{
|
||||||
await Task.Delay(2000);
|
if (pid > 0)
|
||||||
|
{
|
||||||
|
await ProcUtils.ProcessKill(pid);
|
||||||
|
}
|
||||||
|
concurrencySemaphore.Release();
|
||||||
|
}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
Task.WaitAll(tasks.ToArray());
|
||||||
await Task.Delay((timeout + 2) * 1000);
|
|
||||||
|
|
||||||
if (pid > 0)
|
|
||||||
{
|
|
||||||
await ProcUtils.ProcessKill(pid);
|
|
||||||
}
|
|
||||||
await ProfileExHandler.Instance.SaveTo();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> RunMixedTestAsync(List<ServerTestItem> selecteds, string exitLoopKey)
|
private async Task DoRealPing(DownloadService downloadHandle, ServerTestItem it)
|
||||||
{
|
|
||||||
var ret = await RunRealPingAsync(selecteds, exitLoopKey);
|
|
||||||
if (ret == false)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
await Task.Delay(1000);
|
|
||||||
|
|
||||||
var ret2 = await RunSpeedTestMultiAsync(selecteds, exitLoopKey);
|
|
||||||
if (ret2 == false)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<string> GetRealPingTime(DownloadService downloadHandle, IWebProxy webProxy)
|
|
||||||
{
|
{
|
||||||
|
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
|
||||||
var responseTime = await downloadHandle.GetRealPingTime(_config.SpeedTestItem.SpeedPingTestUrl, webProxy, 10);
|
var responseTime = await downloadHandle.GetRealPingTime(_config.SpeedTestItem.SpeedPingTestUrl, webProxy, 10);
|
||||||
return FormatOut(responseTime, Global.DelayUnit);
|
|
||||||
|
ProfileExHandler.Instance.SetTestDelay(it.IndexId, responseTime);
|
||||||
|
UpdateFunc(it.IndexId, responseTime.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DoSpeedTest(DownloadService downloadHandle, ServerTestItem it)
|
||||||
|
{
|
||||||
|
UpdateFunc(it.IndexId, "", ResUI.Speedtesting);
|
||||||
|
|
||||||
|
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
|
||||||
|
var url = _config.SpeedTestItem.SpeedTestUrl;
|
||||||
|
var timeout = _config.SpeedTestItem.SpeedTestTimeout;
|
||||||
|
await downloadHandle.DownloadDataAsync(url, webProxy, timeout, (success, msg) =>
|
||||||
|
{
|
||||||
|
decimal.TryParse(msg, out var dec);
|
||||||
|
if (dec > 0)
|
||||||
|
{
|
||||||
|
ProfileExHandler.Instance.SetTestSpeed(it.IndexId, dec);
|
||||||
|
}
|
||||||
|
UpdateFunc(it.IndexId, "", msg);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<int> GetTcpingTime(string url, int port)
|
private async Task<int> GetTcpingTime(string url, int port)
|
||||||
|
|
@ -425,7 +335,10 @@ namespace ServiceLib.Services
|
||||||
|
|
||||||
var result = clientSocket.BeginConnect(endPoint, null, null);
|
var result = clientSocket.BeginConnect(endPoint, null, null);
|
||||||
if (!result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(5)))
|
if (!result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(5)))
|
||||||
|
{
|
||||||
throw new TimeoutException("connect timeout (5s): " + url);
|
throw new TimeoutException("connect timeout (5s): " + url);
|
||||||
|
}
|
||||||
|
|
||||||
clientSocket.EndConnect(result);
|
clientSocket.EndConnect(result);
|
||||||
|
|
||||||
timer.Stop();
|
timer.Stop();
|
||||||
|
|
@ -438,14 +351,31 @@ namespace ServiceLib.Services
|
||||||
return responseTime;
|
return responseTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string FormatOut(object time, string unit)
|
private List<List<ServerTestItem>> GetTestBatchItem(List<ServerTestItem> lstSelected, int pageSize)
|
||||||
{
|
{
|
||||||
return $"{time}";
|
List<List<ServerTestItem>> lstTest = new();
|
||||||
|
var lst1 = lstSelected.Where(t => t.ConfigType is not (EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard)).ToList();
|
||||||
|
var lst2 = lstSelected.Where(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard).ToList();
|
||||||
|
|
||||||
|
for (var num = 0; num < (int)Math.Ceiling(lst1.Count * 1.0 / pageSize); num++)
|
||||||
|
{
|
||||||
|
lstTest.Add(lst1.Skip(num * pageSize).Take(pageSize).ToList());
|
||||||
|
}
|
||||||
|
for (var num = 0; num < (int)Math.Ceiling(lst2.Count * 1.0 / pageSize); num++)
|
||||||
|
{
|
||||||
|
lstTest.Add(lst2.Skip(num * pageSize).Take(pageSize).ToList());
|
||||||
|
}
|
||||||
|
|
||||||
|
return lstTest;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateFunc(string indexId, string delay, string speed = "")
|
private void UpdateFunc(string indexId, string delay, string speed = "")
|
||||||
{
|
{
|
||||||
_updateFunc?.Invoke(new() { IndexId = indexId, Delay = delay, Speed = speed });
|
_updateFunc?.Invoke(new() { IndexId = indexId, Delay = delay, Speed = speed });
|
||||||
|
if (indexId.IsNotEmpty() && speed.IsNotEmpty())
|
||||||
|
{
|
||||||
|
ProfileExHandler.Instance.SetTestMessage(indexId, speed);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -173,7 +173,7 @@ namespace ServiceLib.ViewModels
|
||||||
var configDirZipTemp = Utils.GetTempPath($"v2rayN_{DateTime.Now:yyyyMMddHHmmss}");
|
var configDirZipTemp = Utils.GetTempPath($"v2rayN_{DateTime.Now:yyyyMMddHHmmss}");
|
||||||
var configDirTemp = Path.Combine(configDirZipTemp, _guiConfigs);
|
var configDirTemp = Path.Combine(configDirZipTemp, _guiConfigs);
|
||||||
|
|
||||||
FileManager.CopyDirectory(configDir, configDirTemp, false, true, "cache.db");
|
FileManager.CopyDirectory(configDir, configDirTemp, false, true, "");
|
||||||
var ret = FileManager.CreateFromDirectory(configDirZipTemp, fileName);
|
var ret = FileManager.CreateFromDirectory(configDirZipTemp, fileName);
|
||||||
Directory.Delete(configDirZipTemp, true);
|
Directory.Delete(configDirZipTemp, true);
|
||||||
return await Task.FromResult(ret);
|
return await Task.FromResult(ret);
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,6 @@ namespace ServiceLib.ViewModels
|
||||||
[Reactive] public int SpeedTestTimeout { get; set; }
|
[Reactive] public int SpeedTestTimeout { get; set; }
|
||||||
[Reactive] public string SpeedTestUrl { get; set; }
|
[Reactive] public string SpeedTestUrl { get; set; }
|
||||||
[Reactive] public string SpeedPingTestUrl { get; set; }
|
[Reactive] public string SpeedPingTestUrl { get; set; }
|
||||||
//[Reactive] public int SpeedTestPageSize { get; set; }
|
|
||||||
[Reactive] public bool EnableHWA { get; set; }
|
[Reactive] public bool EnableHWA { get; set; }
|
||||||
[Reactive] public string SubConvertUrl { get; set; }
|
[Reactive] public string SubConvertUrl { get; set; }
|
||||||
[Reactive] public int MainGirdOrientation { get; set; }
|
[Reactive] public int MainGirdOrientation { get; set; }
|
||||||
|
|
@ -178,7 +177,6 @@ namespace ServiceLib.ViewModels
|
||||||
CurrentFontFamily = _config.UiItem.CurrentFontFamily;
|
CurrentFontFamily = _config.UiItem.CurrentFontFamily;
|
||||||
SpeedTestTimeout = _config.SpeedTestItem.SpeedTestTimeout;
|
SpeedTestTimeout = _config.SpeedTestItem.SpeedTestTimeout;
|
||||||
SpeedTestUrl = _config.SpeedTestItem.SpeedTestUrl;
|
SpeedTestUrl = _config.SpeedTestItem.SpeedTestUrl;
|
||||||
//SpeedTestPageSize = _config.SpeedTestItem.SpeedTestPageSize;
|
|
||||||
SpeedPingTestUrl = _config.SpeedTestItem.SpeedPingTestUrl;
|
SpeedPingTestUrl = _config.SpeedTestItem.SpeedPingTestUrl;
|
||||||
EnableHWA = _config.GuiItem.EnableHWA;
|
EnableHWA = _config.GuiItem.EnableHWA;
|
||||||
SubConvertUrl = _config.ConstItem.SubConvertUrl;
|
SubConvertUrl = _config.ConstItem.SubConvertUrl;
|
||||||
|
|
@ -332,7 +330,6 @@ namespace ServiceLib.ViewModels
|
||||||
_config.GuiItem.TrayMenuServersLimit = TrayMenuServersLimit;
|
_config.GuiItem.TrayMenuServersLimit = TrayMenuServersLimit;
|
||||||
_config.UiItem.CurrentFontFamily = CurrentFontFamily;
|
_config.UiItem.CurrentFontFamily = CurrentFontFamily;
|
||||||
_config.SpeedTestItem.SpeedTestTimeout = SpeedTestTimeout;
|
_config.SpeedTestItem.SpeedTestTimeout = SpeedTestTimeout;
|
||||||
//_config.SpeedTestItem.SpeedTestPageSize = SpeedTestPageSize;
|
|
||||||
_config.SpeedTestItem.SpeedTestUrl = SpeedTestUrl;
|
_config.SpeedTestItem.SpeedTestUrl = SpeedTestUrl;
|
||||||
_config.SpeedTestItem.SpeedPingTestUrl = SpeedPingTestUrl;
|
_config.SpeedTestItem.SpeedPingTestUrl = SpeedPingTestUrl;
|
||||||
_config.GuiItem.EnableHWA = EnableHWA;
|
_config.GuiItem.EnableHWA = EnableHWA;
|
||||||
|
|
|
||||||
|
|
@ -269,20 +269,22 @@ namespace ServiceLib.ViewModels
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var item = _profileItems.FirstOrDefault(it => it.IndexId == result.IndexId);
|
var item = _profileItems.FirstOrDefault(it => it.IndexId == result.IndexId);
|
||||||
if (item != null)
|
if (item == null)
|
||||||
{
|
{
|
||||||
if (Utils.IsNotEmpty(result.Delay))
|
return;
|
||||||
{
|
|
||||||
int.TryParse(result.Delay, out int temp);
|
|
||||||
item.Delay = temp;
|
|
||||||
item.DelayVal = $"{result.Delay} {Global.DelayUnit}";
|
|
||||||
}
|
|
||||||
if (Utils.IsNotEmpty(result.Speed))
|
|
||||||
{
|
|
||||||
item.SpeedVal = $"{result.Speed} {Global.SpeedUnit}";
|
|
||||||
}
|
|
||||||
_profileItems.Replace(item, JsonUtils.DeepCopy(item));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Utils.IsNotEmpty(result.Delay))
|
||||||
|
{
|
||||||
|
int.TryParse(result.Delay, out var temp);
|
||||||
|
item.Delay = temp;
|
||||||
|
item.DelayVal = result.Delay ?? string.Empty;
|
||||||
|
}
|
||||||
|
if (Utils.IsNotEmpty(result.Speed))
|
||||||
|
{
|
||||||
|
item.SpeedVal = result.Speed ?? string.Empty;
|
||||||
|
}
|
||||||
|
_profileItems.Replace(item, JsonUtils.DeepCopy(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateStatistics(ServerSpeedItem update)
|
public void UpdateStatistics(ServerSpeedItem update)
|
||||||
|
|
@ -421,10 +423,11 @@ namespace ServiceLib.ViewModels
|
||||||
Subid = t.Subid,
|
Subid = t.Subid,
|
||||||
SubRemarks = t.SubRemarks,
|
SubRemarks = t.SubRemarks,
|
||||||
IsActive = t.IndexId == _config.IndexId,
|
IsActive = t.IndexId == _config.IndexId,
|
||||||
Sort = t33 == null ? 0 : t33.Sort,
|
Sort = t33?.Sort ?? 0,
|
||||||
Delay = t33 == null ? 0 : t33.Delay,
|
Delay = t33?.Delay ?? 0,
|
||||||
DelayVal = t33?.Delay != 0 ? $"{t33?.Delay} {Global.DelayUnit}" : string.Empty,
|
Speed = t33?.Speed ?? 0,
|
||||||
SpeedVal = t33?.Speed != 0 ? $"{t33?.Speed} {Global.SpeedUnit}" : string.Empty,
|
DelayVal = t33?.Delay != 0 ? $"{t33?.Delay}" : string.Empty,
|
||||||
|
SpeedVal = t33?.Speed > 0 ? $"{t33?.Speed}" : t33?.Message ?? string.Empty,
|
||||||
TodayDown = t22 == null ? "" : Utils.HumanFy(t22.TodayDown),
|
TodayDown = t22 == null ? "" : Utils.HumanFy(t22.TodayDown),
|
||||||
TodayUp = t22 == null ? "" : Utils.HumanFy(t22.TodayUp),
|
TodayUp = t22 == null ? "" : Utils.HumanFy(t22.TodayUp),
|
||||||
TotalDown = t22 == null ? "" : Utils.HumanFy(t22.TotalDown),
|
TotalDown = t22 == null ? "" : Utils.HumanFy(t22.TotalDown),
|
||||||
|
|
|
||||||
|
|
@ -518,21 +518,7 @@
|
||||||
Classes="Margin8"
|
Classes="Margin8"
|
||||||
Text="{x:Static resx:ResUI.TbSettingsCurrentFontFamilyLinuxTip}"
|
Text="{x:Static resx:ResUI.TbSettingsCurrentFontFamilyLinuxTip}"
|
||||||
TextWrapping="Wrap" />
|
TextWrapping="Wrap" />
|
||||||
<!--
|
|
||||||
<TextBlock
|
|
||||||
Grid.Row="16"
|
|
||||||
Grid.Column="0"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Classes="Margin8"
|
|
||||||
Text="{x:Static resx:ResUI.TbSettingsSpeedTestPageSize}" />
|
|
||||||
<TextBox
|
|
||||||
x:Name="txtSpeedTestPageSize"
|
|
||||||
Grid.Row="16"
|
|
||||||
Grid.Column="1"
|
|
||||||
Width="200"
|
|
||||||
HorizontalAlignment="Left"
|
|
||||||
Classes="Margin8" />
|
|
||||||
-->
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="17"
|
Grid.Row="17"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
|
|
|
||||||
|
|
@ -139,7 +139,6 @@ namespace v2rayN.Desktop.Views
|
||||||
this.Bind(ViewModel, vm => vm.SpeedTestTimeout, v => v.cmbSpeedTestTimeout.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SpeedTestTimeout, v => v.cmbSpeedTestTimeout.SelectedValue).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SpeedTestUrl, v => v.cmbSpeedTestUrl.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SpeedTestUrl, v => v.cmbSpeedTestUrl.SelectedValue).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SpeedPingTestUrl, v => v.cmbSpeedPingTestUrl.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SpeedPingTestUrl, v => v.cmbSpeedPingTestUrl.SelectedValue).DisposeWith(disposables);
|
||||||
//this.Bind(ViewModel, vm => vm.SpeedTestPageSize, v => v.txtSpeedTestPageSize.Text).DisposeWith(disposables);
|
|
||||||
this.Bind(ViewModel, vm => vm.SubConvertUrl, v => v.cmbSubConvertUrl.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SubConvertUrl, v => v.cmbSubConvertUrl.SelectedValue).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.MainGirdOrientation, v => v.cmbMainGirdOrientation.SelectedIndex).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.MainGirdOrientation, v => v.cmbMainGirdOrientation.SelectedIndex).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.GeoFileSourceUrl, v => v.cmbGetFilesSourceUrl.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.GeoFileSourceUrl, v => v.cmbGetFilesSourceUrl.SelectedValue).DisposeWith(disposables);
|
||||||
|
|
|
||||||
|
|
@ -776,23 +776,7 @@
|
||||||
Style="{StaticResource ToolbarTextBlock}"
|
Style="{StaticResource ToolbarTextBlock}"
|
||||||
Text="{x:Static resx:ResUI.TbSettingsCurrentFontFamilyTip}"
|
Text="{x:Static resx:ResUI.TbSettingsCurrentFontFamilyTip}"
|
||||||
TextWrapping="Wrap" />
|
TextWrapping="Wrap" />
|
||||||
<!--
|
|
||||||
<TextBlock
|
|
||||||
Grid.Row="16"
|
|
||||||
Grid.Column="0"
|
|
||||||
Margin="{StaticResource Margin8}"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Style="{StaticResource ToolbarTextBlock}"
|
|
||||||
Text="{x:Static resx:ResUI.TbSettingsSpeedTestPageSize}" />
|
|
||||||
<TextBox
|
|
||||||
x:Name="txtSpeedTestPageSize"
|
|
||||||
Grid.Row="16"
|
|
||||||
Grid.Column="1"
|
|
||||||
Width="200"
|
|
||||||
Margin="{StaticResource Margin8}"
|
|
||||||
HorizontalAlignment="Left"
|
|
||||||
Style="{StaticResource DefTextBox}" />
|
|
||||||
-->
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="17"
|
Grid.Row="17"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
|
|
|
||||||
|
|
@ -150,7 +150,6 @@ namespace v2rayN.Views
|
||||||
this.Bind(ViewModel, vm => vm.SpeedTestTimeout, v => v.cmbSpeedTestTimeout.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SpeedTestTimeout, v => v.cmbSpeedTestTimeout.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SpeedTestUrl, v => v.cmbSpeedTestUrl.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SpeedTestUrl, v => v.cmbSpeedTestUrl.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SpeedPingTestUrl, v => v.cmbSpeedPingTestUrl.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SpeedPingTestUrl, v => v.cmbSpeedPingTestUrl.Text).DisposeWith(disposables);
|
||||||
//this.Bind(ViewModel, vm => vm.SpeedTestPageSize, v => v.txtSpeedTestPageSize.Text).DisposeWith(disposables);
|
|
||||||
this.Bind(ViewModel, vm => vm.EnableHWA, v => v.togEnableHWA.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.EnableHWA, v => v.togEnableHWA.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SubConvertUrl, v => v.cmbSubConvertUrl.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SubConvertUrl, v => v.cmbSubConvertUrl.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.MainGirdOrientation, v => v.cmbMainGirdOrientation.SelectedIndex).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.MainGirdOrientation, v => v.cmbMainGirdOrientation.SelectedIndex).DisposeWith(disposables);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue