mirror of
https://github.com/2dust/v2rayN.git
synced 2025-12-16 03:42:42 +00:00
Refactor Node Precheck (#8464)
This commit is contained in:
parent
3885ff8b31
commit
7cee98887b
1 changed files with 153 additions and 116 deletions
|
|
@ -3,13 +3,11 @@ namespace ServiceLib.Manager;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Centralized pre-checks before sensitive actions (set active profile, generate config, etc.).
|
/// Centralized pre-checks before sensitive actions (set active profile, generate config, etc.).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ActionPrecheckManager(Config config)
|
public class ActionPrecheckManager
|
||||||
{
|
{
|
||||||
private static readonly Lazy<ActionPrecheckManager> _instance = new(() => new ActionPrecheckManager(AppManager.Instance.Config));
|
private static readonly Lazy<ActionPrecheckManager> _instance = new();
|
||||||
public static ActionPrecheckManager Instance => _instance.Value;
|
public static ActionPrecheckManager Instance => _instance.Value;
|
||||||
|
|
||||||
private readonly Config _config = config;
|
|
||||||
|
|
||||||
// sing-box supported transports for different protocol types
|
// sing-box supported transports for different protocol types
|
||||||
private static readonly HashSet<string> SingboxUnsupportedTransports = [nameof(ETransport.kcp), nameof(ETransport.xhttp)];
|
private static readonly HashSet<string> SingboxUnsupportedTransports = [nameof(ETransport.kcp), nameof(ETransport.xhttp)];
|
||||||
|
|
||||||
|
|
@ -56,6 +54,7 @@ public class ActionPrecheckManager(Config config)
|
||||||
{
|
{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
var coreType = AppManager.Instance.GetCoreType(item, item.ConfigType);
|
var coreType = AppManager.Instance.GetCoreType(item, item.ConfigType);
|
||||||
return await ValidateNodeAndCoreSupport(item, coreType);
|
return await ValidateNodeAndCoreSupport(item, coreType);
|
||||||
}
|
}
|
||||||
|
|
@ -71,21 +70,64 @@ public class ActionPrecheckManager(Config config)
|
||||||
errors.Add(string.Format(ResUI.NotSupportProtocol, item.ConfigType.ToString()));
|
errors.Add(string.Format(ResUI.NotSupportProtocol, item.ConfigType.ToString()));
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
else if (item.ConfigType.IsGroupType())
|
||||||
if (!item.IsComplex())
|
|
||||||
{
|
{
|
||||||
|
var groupErrors = await ValidateGroupNode(item, coreType);
|
||||||
|
errors.AddRange(groupErrors);
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
else if (!item.IsComplex())
|
||||||
|
{
|
||||||
|
var normalErrors = await ValidateNormalNode(item, coreType);
|
||||||
|
errors.AddRange(normalErrors);
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<List<string>> ValidateNormalNode(ProfileItem item, ECoreType? coreType = null)
|
||||||
|
{
|
||||||
|
var errors = new List<string>();
|
||||||
|
|
||||||
if (item.Address.IsNullOrEmpty())
|
if (item.Address.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
errors.Add(string.Format(ResUI.InvalidProperty, "Address"));
|
errors.Add(string.Format(ResUI.InvalidProperty, "Address"));
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.Port is <= 0 or >= 65536)
|
if (item.Port is <= 0 or > 65535)
|
||||||
{
|
{
|
||||||
errors.Add(string.Format(ResUI.InvalidProperty, "Port"));
|
errors.Add(string.Format(ResUI.InvalidProperty, "Port"));
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var net = item.GetNetwork();
|
||||||
|
|
||||||
|
if (coreType == ECoreType.sing_box)
|
||||||
|
{
|
||||||
|
var transportError = ValidateSingboxTransport(item.ConfigType, net);
|
||||||
|
if (transportError != null)
|
||||||
|
{
|
||||||
|
errors.Add(transportError);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Global.SingboxSupportConfigType.Contains(item.ConfigType))
|
||||||
|
{
|
||||||
|
errors.Add(string.Format(ResUI.CoreNotSupportProtocol,
|
||||||
|
nameof(ECoreType.sing_box), item.ConfigType.ToString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (coreType is ECoreType.Xray)
|
||||||
|
{
|
||||||
|
// Xray core does not support these protocols
|
||||||
|
if (!Global.XraySupportConfigType.Contains(item.ConfigType))
|
||||||
|
{
|
||||||
|
errors.Add(string.Format(ResUI.CoreNotSupportProtocol,
|
||||||
|
nameof(ECoreType.Xray), item.ConfigType.ToString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (item.ConfigType)
|
switch (item.ConfigType)
|
||||||
{
|
{
|
||||||
case EConfigType.VMess:
|
case EConfigType.VMess:
|
||||||
|
|
@ -123,21 +165,41 @@ public class ActionPrecheckManager(Config config)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.ConfigType is EConfigType.VLESS or EConfigType.Trojan
|
if (item.StreamSecurity == Global.StreamSecurity)
|
||||||
&& item.StreamSecurity == Global.StreamSecurityReality
|
{
|
||||||
&& item.PublicKey.IsNullOrEmpty())
|
// check certificate validity
|
||||||
|
if ((!item.Cert.IsNullOrEmpty()) && (CertPemManager.ParsePemChain(item.Cert).Count == 0))
|
||||||
|
{
|
||||||
|
errors.Add(string.Format(ResUI.InvalidProperty, "TLS Certificate"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.StreamSecurity == Global.StreamSecurityReality)
|
||||||
|
{
|
||||||
|
if (item.PublicKey.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
errors.Add(string.Format(ResUI.InvalidProperty, "PublicKey"));
|
errors.Add(string.Format(ResUI.InvalidProperty, "PublicKey"));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (errors.Count > 0)
|
if (item.Network == nameof(ETransport.xhttp)
|
||||||
|
&& !item.Extra.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
|
// check xhttp extra json validity
|
||||||
|
var xhttpExtra = JsonUtils.ParseJson(item.Extra);
|
||||||
|
if (xhttpExtra is null)
|
||||||
|
{
|
||||||
|
errors.Add(string.Format(ResUI.InvalidProperty, "XHTTP Extra"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (item.ConfigType.IsGroupType())
|
private async Task<List<string>> ValidateGroupNode(ProfileItem item, ECoreType? coreType = null)
|
||||||
{
|
{
|
||||||
|
var errors = new List<string>();
|
||||||
|
|
||||||
ProfileGroupItemManager.Instance.TryGet(item.IndexId, out var group);
|
ProfileGroupItemManager.Instance.TryGet(item.IndexId, out var group);
|
||||||
if (group is null || group.NotHasChild())
|
if (group is null || group.NotHasChild())
|
||||||
{
|
{
|
||||||
|
|
@ -178,36 +240,11 @@ public class ActionPrecheckManager(Config config)
|
||||||
}
|
}
|
||||||
|
|
||||||
childErrors.AddRange(await ValidateNodeAndCoreSupport(childItem, coreType));
|
childErrors.AddRange(await ValidateNodeAndCoreSupport(childItem, coreType));
|
||||||
errors.AddRange(childErrors);
|
errors.AddRange(childErrors.Select(s => s.Insert(0, $"{childItem.Remarks}: ")));
|
||||||
}
|
}
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
var net = item.GetNetwork();
|
|
||||||
|
|
||||||
if (coreType == ECoreType.sing_box)
|
|
||||||
{
|
|
||||||
var transportError = ValidateSingboxTransport(item.ConfigType, net);
|
|
||||||
if (transportError != null)
|
|
||||||
{
|
|
||||||
errors.Add(transportError);
|
|
||||||
return errors;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (coreType is ECoreType.Xray)
|
|
||||||
{
|
|
||||||
// Xray core does not support these protocols
|
|
||||||
if (!Global.XraySupportConfigType.Contains(item.ConfigType)
|
|
||||||
&& !item.IsComplex())
|
|
||||||
{
|
|
||||||
errors.Add(string.Format(ResUI.CoreNotSupportProtocol, nameof(ECoreType.Xray), item.ConfigType.ToString()));
|
|
||||||
return errors;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string? ValidateSingboxTransport(EConfigType configType, string net)
|
private static string? ValidateSingboxTransport(EConfigType configType, string net)
|
||||||
{
|
{
|
||||||
// sing-box does not support xhttp / kcp transports
|
// sing-box does not support xhttp / kcp transports
|
||||||
|
|
@ -271,7 +308,7 @@ public class ActionPrecheckManager(Config config)
|
||||||
if (node is not null)
|
if (node is not null)
|
||||||
{
|
{
|
||||||
var nodeErrors = await ValidateNodeAndCoreSupport(node, coreType);
|
var nodeErrors = await ValidateNodeAndCoreSupport(node, coreType);
|
||||||
errors.AddRange(nodeErrors.Select(s => ResUI.ProxyChainedPrefix + s));
|
errors.AddRange(nodeErrors.Select(s => ResUI.ProxyChainedPrefix + $"{node.Remarks}: " + s));
|
||||||
}
|
}
|
||||||
else if (tag.IsNotEmpty())
|
else if (tag.IsNotEmpty())
|
||||||
{
|
{
|
||||||
|
|
@ -289,7 +326,7 @@ public class ActionPrecheckManager(Config config)
|
||||||
}
|
}
|
||||||
|
|
||||||
var coreType = AppManager.Instance.GetCoreType(item, item.ConfigType);
|
var coreType = AppManager.Instance.GetCoreType(item, item.ConfigType);
|
||||||
var routing = await ConfigHandler.GetDefaultRouting(_config);
|
var routing = await ConfigHandler.GetDefaultRouting(AppManager.Instance.Config);
|
||||||
if (routing == null)
|
if (routing == null)
|
||||||
{
|
{
|
||||||
return errors;
|
return errors;
|
||||||
|
|
@ -317,7 +354,7 @@ public class ActionPrecheckManager(Config config)
|
||||||
}
|
}
|
||||||
|
|
||||||
var tagErrors = await ValidateNodeAndCoreSupport(tagItem, coreType);
|
var tagErrors = await ValidateNodeAndCoreSupport(tagItem, coreType);
|
||||||
errors.AddRange(tagErrors.Select(s => ResUI.RoutingRuleOutboundPrefix + s));
|
errors.AddRange(tagErrors.Select(s => ResUI.RoutingRuleOutboundPrefix + $"{tagItem.Remarks}: " + s));
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors;
|
return errors;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue