mirror of
https://github.com/2dust/v2rayN.git
synced 2025-10-26 10:14:42 +00:00
Compare commits
1 commit
11924b545f
...
d44459eb2f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d44459eb2f |
17 changed files with 343 additions and 349 deletions
|
|
@ -1251,7 +1251,7 @@ public static class ConfigHandler
|
|||
public static async Task<ProfileItem?> GetPreSocksItem(Config config, ProfileItem node, ECoreType coreType)
|
||||
{
|
||||
ProfileItem? itemSocks = null;
|
||||
if (node.ConfigType != EConfigType.Custom && coreType != ECoreType.sing_box && config.TunModeItem.EnableTun)
|
||||
if (node.ConfigType != EConfigType.Custom && node.ConfigType < EConfigType.Group && coreType != ECoreType.sing_box && config.TunModeItem.EnableTun)
|
||||
{
|
||||
itemSocks = new ProfileItem()
|
||||
{
|
||||
|
|
@ -1262,7 +1262,7 @@ public static class ConfigHandler
|
|||
Port = AppManager.Instance.GetLocalPort(EInboundProtocol.socks)
|
||||
};
|
||||
}
|
||||
else if (node.ConfigType == EConfigType.Custom && node.PreSocksPort > 0)
|
||||
else if (node.ConfigType == EConfigType.Custom && node.ConfigType < EConfigType.Group && node.PreSocksPort > 0)
|
||||
{
|
||||
var preCoreType = config.RunningCoreType = config.TunModeItem.EnableTun ? ECoreType.sing_box : ECoreType.Xray;
|
||||
itemSocks = new ProfileItem()
|
||||
|
|
|
|||
|
|
@ -32,19 +32,19 @@ public class ProfileItem : ReactiveObject
|
|||
public string GetSummary()
|
||||
{
|
||||
var summary = $"[{(ConfigType).ToString()}] ";
|
||||
if (IsComplex())
|
||||
var arrAddr = Address.Contains(':') ? Address.Split(':') : Address.Split('.');
|
||||
var addr = arrAddr.Length switch
|
||||
{
|
||||
> 2 => $"{arrAddr.First()}***{arrAddr.Last()}",
|
||||
> 1 => $"***{arrAddr.Last()}",
|
||||
_ => Address
|
||||
};
|
||||
if (ConfigType is EConfigType.Custom or > EConfigType.Group)
|
||||
{
|
||||
summary += $"[{CoreType.ToString()}]{Remarks}";
|
||||
}
|
||||
else
|
||||
{
|
||||
var arrAddr = Address.Contains(':') ? Address.Split(':') : Address.Split('.');
|
||||
var addr = arrAddr.Length switch
|
||||
{
|
||||
> 2 => $"{arrAddr.First()}***{arrAddr.Last()}",
|
||||
> 1 => $"***{arrAddr.Last()}",
|
||||
_ => Address
|
||||
};
|
||||
summary += $"{Remarks}({addr}:{Port})";
|
||||
}
|
||||
return summary;
|
||||
|
|
@ -64,51 +64,6 @@ public class ProfileItem : ReactiveObject
|
|||
return Network.TrimEx();
|
||||
}
|
||||
|
||||
public bool IsComplex()
|
||||
{
|
||||
return ConfigType is EConfigType.Custom or > EConfigType.Group;
|
||||
}
|
||||
|
||||
public bool IsValid()
|
||||
{
|
||||
if (IsComplex())
|
||||
return true;
|
||||
|
||||
if (Address.IsNullOrEmpty() || Port is <= 0 or >= 65536)
|
||||
return false;
|
||||
|
||||
switch (ConfigType)
|
||||
{
|
||||
case EConfigType.VMess:
|
||||
if (Id.IsNullOrEmpty() || !Utils.IsGuidByParse(Id))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case EConfigType.VLESS:
|
||||
if (Id.IsNullOrEmpty() || (!Utils.IsGuidByParse(Id) && Id.Length > 30))
|
||||
return false;
|
||||
if (!Global.Flows.Contains(Flow))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case EConfigType.Shadowsocks:
|
||||
if (Id.IsNullOrEmpty())
|
||||
return false;
|
||||
if (string.IsNullOrEmpty(Security) || !Global.SsSecuritiesInSingbox.Contains(Security))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((ConfigType is EConfigType.VLESS or EConfigType.Trojan)
|
||||
&& StreamSecurity == Global.StreamSecurityReality
|
||||
&& PublicKey.IsNullOrEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion function
|
||||
|
||||
[PrimaryKey]
|
||||
|
|
|
|||
18
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
18
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
|
|
@ -303,15 +303,6 @@ namespace ServiceLib.Resx {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 The group "{0}" cannot reference itself. 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string GroupSelfReference {
|
||||
get {
|
||||
return ResourceManager.GetString("GroupSelfReference", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 This is not the correct configuration, please check 的本地化字符串。
|
||||
/// </summary>
|
||||
|
|
@ -339,15 +330,6 @@ namespace ServiceLib.Resx {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 The {0} property is invalid, please check. 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string InvalidProperty {
|
||||
get {
|
||||
return ResourceManager.GetString("InvalidProperty", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Invalid address (URL) 的本地化字符串。
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -1587,10 +1587,4 @@
|
|||
<data name="GroupEmpty" xml:space="preserve">
|
||||
<value>Group '{0}' is empty. Please add at least one node.</value>
|
||||
</data>
|
||||
<data name="InvalidProperty" xml:space="preserve">
|
||||
<value>The {0} property is invalid, please check.</value>
|
||||
</data>
|
||||
<data name="GroupSelfReference" xml:space="preserve">
|
||||
<value>The group "{0}" cannot reference itself.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -1587,10 +1587,4 @@
|
|||
<data name="GroupEmpty" xml:space="preserve">
|
||||
<value>Group '{0}' is empty. Please add at least one node.</value>
|
||||
</data>
|
||||
<data name="InvalidProperty" xml:space="preserve">
|
||||
<value>The {0} property is invalid, please check.</value>
|
||||
</data>
|
||||
<data name="GroupSelfReference" xml:space="preserve">
|
||||
<value>The group "{0}" cannot reference itself.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -1587,10 +1587,4 @@
|
|||
<data name="GroupEmpty" xml:space="preserve">
|
||||
<value>Group '{0}' is empty. Please add at least one node.</value>
|
||||
</data>
|
||||
<data name="InvalidProperty" xml:space="preserve">
|
||||
<value>The {0} property is invalid, please check.</value>
|
||||
</data>
|
||||
<data name="GroupSelfReference" xml:space="preserve">
|
||||
<value>The group "{0}" cannot reference itself.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -1587,10 +1587,4 @@
|
|||
<data name="GroupEmpty" xml:space="preserve">
|
||||
<value>Group '{0}' is empty. Please add at least one node.</value>
|
||||
</data>
|
||||
<data name="InvalidProperty" xml:space="preserve">
|
||||
<value>The {0} property is invalid, please check.</value>
|
||||
</data>
|
||||
<data name="GroupSelfReference" xml:space="preserve">
|
||||
<value>The group "{0}" cannot reference itself.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -1584,10 +1584,4 @@
|
|||
<data name="GroupEmpty" xml:space="preserve">
|
||||
<value>组“{0}”为空。请至少添加一个节点。</value>
|
||||
</data>
|
||||
<data name="InvalidProperty" xml:space="preserve">
|
||||
<value>{0}属性无效,请检查</value>
|
||||
</data>
|
||||
<data name="GroupSelfReference" xml:space="preserve">
|
||||
<value>{0} 分组不能引用自身</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -1584,10 +1584,4 @@
|
|||
<data name="GroupEmpty" xml:space="preserve">
|
||||
<value>Group '{0}' is empty. Please add at least one node.</value>
|
||||
</data>
|
||||
<data name="InvalidProperty" xml:space="preserve">
|
||||
<value>The {0} property is invalid, please check.</value>
|
||||
</data>
|
||||
<data name="GroupSelfReference" xml:space="preserve">
|
||||
<value>The group "{0}" cannot reference itself.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -65,56 +65,6 @@ public class ActionPrecheckService(Config config)
|
|||
return errors;
|
||||
}
|
||||
|
||||
if (!item.IsComplex())
|
||||
{
|
||||
if (item.Address.IsNullOrEmpty())
|
||||
{
|
||||
errors.Add(string.Format(ResUI.InvalidProperty, "Address"));
|
||||
return errors;
|
||||
}
|
||||
|
||||
if (item.Port is <= 0 or >= 65536)
|
||||
{
|
||||
errors.Add(string.Format(ResUI.InvalidProperty, "Port"));
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
||||
switch (item.ConfigType)
|
||||
{
|
||||
case EConfigType.VMess:
|
||||
if (item.Id.IsNullOrEmpty() || !Utils.IsGuidByParse(item.Id))
|
||||
errors.Add(string.Format(ResUI.InvalidProperty, "Id"));
|
||||
break;
|
||||
|
||||
case EConfigType.VLESS:
|
||||
if (item.Id.IsNullOrEmpty() || (!Utils.IsGuidByParse(item.Id) && item.Id.Length > 30))
|
||||
errors.Add(string.Format(ResUI.InvalidProperty, "Id"));
|
||||
if (!Global.Flows.Contains(item.Flow))
|
||||
errors.Add(string.Format(ResUI.InvalidProperty, "Flow"));
|
||||
break;
|
||||
|
||||
case EConfigType.Shadowsocks:
|
||||
if (item.Id.IsNullOrEmpty())
|
||||
errors.Add(string.Format(ResUI.InvalidProperty, "Id"));
|
||||
if (string.IsNullOrEmpty(item.Security) || !Global.SsSecuritiesInSingbox.Contains(item.Security))
|
||||
errors.Add(string.Format(ResUI.InvalidProperty, "Security"));
|
||||
break;
|
||||
}
|
||||
|
||||
if ((item.ConfigType is EConfigType.VLESS or EConfigType.Trojan)
|
||||
&& item.StreamSecurity == Global.StreamSecurityReality
|
||||
&& item.PublicKey.IsNullOrEmpty())
|
||||
{
|
||||
errors.Add(string.Format(ResUI.InvalidProperty, "PublicKey"));
|
||||
}
|
||||
|
||||
if (errors.Count > 0)
|
||||
{
|
||||
return errors;
|
||||
}
|
||||
}
|
||||
|
||||
if (item.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain)
|
||||
{
|
||||
ProfileGroupItemManager.Instance.TryGet(item.IndexId, out var group);
|
||||
|
|
@ -126,7 +76,6 @@ public class ActionPrecheckService(Config config)
|
|||
|
||||
foreach (var child in Utils.String2List(group.ChildItems))
|
||||
{
|
||||
var childErrors = new List<string>();
|
||||
if (child.IsNullOrEmpty())
|
||||
{
|
||||
continue;
|
||||
|
|
@ -135,24 +84,11 @@ public class ActionPrecheckService(Config config)
|
|||
var childItem = await AppManager.Instance.GetProfileItem(child);
|
||||
if (childItem is null)
|
||||
{
|
||||
childErrors.Add(string.Format(ResUI.NodeTagNotExist, child));
|
||||
errors.Add(string.Format(ResUI.NodeTagNotExist, child));
|
||||
continue;
|
||||
}
|
||||
|
||||
// self-reference check
|
||||
if (childItem.IndexId == item.IndexId)
|
||||
{
|
||||
childErrors.Add(string.Format(ResUI.GroupSelfReference, childItem.Remarks));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (childItem.ConfigType is EConfigType.Custom or EConfigType.ProxyChain)
|
||||
{
|
||||
childErrors.Add(string.Format(ResUI.InvalidProperty, childItem.Remarks));
|
||||
continue;
|
||||
}
|
||||
|
||||
childErrors.AddRange(await ValidateNodeAndCoreSupport(childItem, coreType));
|
||||
|
||||
var childErrors = await ValidateNodeAndCoreSupport(childItem, coreType);
|
||||
errors.AddRange(childErrors);
|
||||
}
|
||||
return errors;
|
||||
|
|
@ -187,7 +123,7 @@ public class ActionPrecheckService(Config config)
|
|||
}
|
||||
}
|
||||
|
||||
return errors.Select(s => $"{item.Remarks}: {s}").ToList();
|
||||
return errors;
|
||||
}
|
||||
|
||||
private async Task<List<string>> ValidateRelatedNodesExistAndValid(ProfileItem? item)
|
||||
|
|
|
|||
|
|
@ -15,8 +15,35 @@ public partial class CoreConfigSingboxService(Config config)
|
|||
var ret = new RetResult();
|
||||
try
|
||||
{
|
||||
if (node?.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain)
|
||||
{
|
||||
ProfileGroupItemManager.Instance.TryGet(node.IndexId, out var profileGroupItem);
|
||||
if (profileGroupItem == null || profileGroupItem.ChildItems.IsNullOrEmpty())
|
||||
{
|
||||
ret.Msg = ResUI.CheckServerSettings;
|
||||
return ret;
|
||||
}
|
||||
var childProfiles = (await Task.WhenAll(
|
||||
Utils.String2List(profileGroupItem.ChildItems)
|
||||
.Where(p => !p.IsNullOrEmpty())
|
||||
.Select(AppManager.Instance.GetProfileItem)
|
||||
)).Where(p => p != null).ToList();
|
||||
if (childProfiles.Count <= 0)
|
||||
{
|
||||
ret.Msg = ResUI.CheckServerSettings;
|
||||
return ret;
|
||||
}
|
||||
switch (node.ConfigType)
|
||||
{
|
||||
case EConfigType.PolicyGroup:
|
||||
return await GenerateClientMultipleLoadConfig(childProfiles, profileGroupItem.MultipleLoad);
|
||||
case EConfigType.ProxyChain:
|
||||
return await GenerateClientChainConfig(childProfiles);
|
||||
}
|
||||
}
|
||||
|
||||
if (node == null
|
||||
|| !node.IsValid())
|
||||
|| node.Port <= 0)
|
||||
{
|
||||
ret.Msg = ResUI.CheckServerSettings;
|
||||
return ret;
|
||||
|
|
@ -28,17 +55,6 @@ public partial class CoreConfigSingboxService(Config config)
|
|||
}
|
||||
|
||||
ret.Msg = ResUI.InitialConfiguration;
|
||||
|
||||
if (node?.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain)
|
||||
{
|
||||
switch (node.ConfigType)
|
||||
{
|
||||
case EConfigType.PolicyGroup:
|
||||
return await GenerateClientMultipleLoadConfig(node);
|
||||
case EConfigType.ProxyChain:
|
||||
return await GenerateClientChainConfig(node);
|
||||
}
|
||||
}
|
||||
|
||||
var result = EmbedUtils.GetEmbedText(Global.SingboxSampleClient);
|
||||
if (result.IsNullOrEmpty())
|
||||
|
|
@ -153,9 +169,12 @@ public partial class CoreConfigSingboxService(Config config)
|
|||
continue;
|
||||
}
|
||||
var item = await AppManager.Instance.GetProfileItem(it.IndexId);
|
||||
if (item is null || item.IsComplex() || !item.IsValid())
|
||||
if (it.ConfigType is EConfigType.VMess or EConfigType.VLESS)
|
||||
{
|
||||
continue;
|
||||
if (item is null || item.Id.IsNullOrEmpty() || !Utils.IsGuidByParse(item.Id))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
//find unused port
|
||||
|
|
@ -195,6 +214,27 @@ public partial class CoreConfigSingboxService(Config config)
|
|||
singboxConfig.inbounds.Add(inbound);
|
||||
|
||||
//outbound
|
||||
if (item is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (item.ConfigType == EConfigType.Shadowsocks
|
||||
&& !Global.SsSecuritiesInSingbox.Contains(item.Security))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (item.ConfigType == EConfigType.VLESS
|
||||
&& !Global.Flows.Contains(item.Flow))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (it.ConfigType is EConfigType.VLESS or EConfigType.Trojan
|
||||
&& item.StreamSecurity == Global.StreamSecurityReality
|
||||
&& item.PublicKey.IsNullOrEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var server = await GenServer(item);
|
||||
if (server is null)
|
||||
{
|
||||
|
|
@ -253,8 +293,7 @@ public partial class CoreConfigSingboxService(Config config)
|
|||
var ret = new RetResult();
|
||||
try
|
||||
{
|
||||
if (node == null
|
||||
|| !node.IsValid())
|
||||
if (node is not { Port: > 0 })
|
||||
{
|
||||
ret.Msg = ResUI.CheckServerSettings;
|
||||
return ret;
|
||||
|
|
@ -332,7 +371,7 @@ public partial class CoreConfigSingboxService(Config config)
|
|||
}
|
||||
}
|
||||
|
||||
public async Task<RetResult> GenerateClientMultipleLoadConfig(ProfileItem parentNode)
|
||||
public async Task<RetResult> GenerateClientMultipleLoadConfig(List<ProfileItem> selecteds, EMultipleLoad multipleLoad)
|
||||
{
|
||||
var ret = new RetResult();
|
||||
try
|
||||
|
|
@ -366,12 +405,53 @@ public partial class CoreConfigSingboxService(Config config)
|
|||
await GenRouting(singboxConfig);
|
||||
await GenExperimental(singboxConfig);
|
||||
|
||||
var groupRet = await GenGroupOutbound(parentNode, singboxConfig);
|
||||
if (groupRet != 0)
|
||||
var proxyProfiles = new List<ProfileItem>();
|
||||
foreach (var it in selecteds)
|
||||
{
|
||||
if (it.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain)
|
||||
{
|
||||
var itemGroup = await AppManager.Instance.GetProfileItem(it.IndexId);
|
||||
proxyProfiles.Add(itemGroup);
|
||||
}
|
||||
if (!Global.SingboxSupportConfigType.Contains(it.ConfigType))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (it.Port <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var item = await AppManager.Instance.GetProfileItem(it.IndexId);
|
||||
if (item is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (it.ConfigType is EConfigType.VMess or EConfigType.VLESS)
|
||||
{
|
||||
if (item.Id.IsNullOrEmpty() || !Utils.IsGuidByParse(item.Id))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (item.ConfigType == EConfigType.Shadowsocks
|
||||
&& !Global.SsSecuritiesInSingbox.Contains(item.Security))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (item.ConfigType == EConfigType.VLESS && !Global.Flows.Contains(item.Flow))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//outbound
|
||||
proxyProfiles.Add(item);
|
||||
}
|
||||
if (proxyProfiles.Count <= 0)
|
||||
{
|
||||
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
||||
return ret;
|
||||
}
|
||||
await GenOutboundsListWithChain(proxyProfiles, singboxConfig, multipleLoad);
|
||||
|
||||
await GenDns(null, singboxConfig);
|
||||
await ConvertGeo2Ruleset(singboxConfig);
|
||||
|
|
@ -389,7 +469,7 @@ public partial class CoreConfigSingboxService(Config config)
|
|||
}
|
||||
}
|
||||
|
||||
public async Task<RetResult> GenerateClientChainConfig(ProfileItem parentNode)
|
||||
public async Task<RetResult> GenerateClientChainConfig(List<ProfileItem> selecteds)
|
||||
{
|
||||
var ret = new RetResult();
|
||||
try
|
||||
|
|
@ -423,12 +503,48 @@ public partial class CoreConfigSingboxService(Config config)
|
|||
await GenExperimental(singboxConfig);
|
||||
singboxConfig.outbounds.RemoveAt(0);
|
||||
|
||||
var groupRet = await GenGroupOutbound(parentNode, singboxConfig);
|
||||
if (groupRet != 0)
|
||||
var proxyProfiles = new List<ProfileItem>();
|
||||
foreach (var it in selecteds)
|
||||
{
|
||||
if (!Global.SingboxSupportConfigType.Contains(it.ConfigType))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (it.Port <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var item = await AppManager.Instance.GetProfileItem(it.IndexId);
|
||||
if (item is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (it.ConfigType is EConfigType.VMess or EConfigType.VLESS)
|
||||
{
|
||||
if (item.Id.IsNullOrEmpty() || !Utils.IsGuidByParse(item.Id))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (item.ConfigType == EConfigType.Shadowsocks
|
||||
&& !Global.SsSecuritiesInSingbox.Contains(item.Security))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (item.ConfigType == EConfigType.VLESS && !Global.Flows.Contains(item.Flow))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//outbound
|
||||
proxyProfiles.Add(item);
|
||||
}
|
||||
if (proxyProfiles.Count <= 0)
|
||||
{
|
||||
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
||||
return ret;
|
||||
}
|
||||
await GenChainOutboundsList(proxyProfiles, singboxConfig);
|
||||
|
||||
await GenDns(null, singboxConfig);
|
||||
await ConvertGeo2Ruleset(singboxConfig);
|
||||
|
|
|
|||
|
|
@ -204,67 +204,6 @@ public partial class CoreConfigSingboxService
|
|||
return await Task.FromResult<BaseServer4Sbox?>(null);
|
||||
}
|
||||
|
||||
private async Task<int> GenGroupOutbound(ProfileItem node, SingboxConfig singboxConfig, string baseTagName = Global.ProxyTag, bool ignoreOriginChain = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (node.ConfigType is not (EConfigType.PolicyGroup or EConfigType.ProxyChain))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
ProfileGroupItemManager.Instance.TryGet(node.IndexId, out var profileGroupItem);
|
||||
if (profileGroupItem is null || profileGroupItem.ChildItems.IsNullOrEmpty())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
// remove custom nodes
|
||||
// remove group nodes for proxy chain
|
||||
// avoid self-reference
|
||||
var childProfiles = (await Task.WhenAll(
|
||||
Utils.String2List(profileGroupItem.ChildItems)
|
||||
.Where(p => !p.IsNullOrEmpty())
|
||||
.Select(AppManager.Instance.GetProfileItem)
|
||||
))
|
||||
.Where(p =>
|
||||
p != null
|
||||
&& p.IsValid()
|
||||
&& p.ConfigType != EConfigType.Custom
|
||||
&& (node.ConfigType == EConfigType.PolicyGroup || p.ConfigType < EConfigType.Group)
|
||||
&& p.IndexId != node.IndexId
|
||||
)
|
||||
.ToList();
|
||||
|
||||
if (childProfiles.Count <= 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
switch (node.ConfigType)
|
||||
{
|
||||
case EConfigType.PolicyGroup:
|
||||
if (ignoreOriginChain)
|
||||
{
|
||||
await GenOutboundsList(childProfiles, singboxConfig, profileGroupItem.MultipleLoad, baseTagName);
|
||||
}
|
||||
else
|
||||
{
|
||||
await GenOutboundsListWithChain(childProfiles, singboxConfig, profileGroupItem.MultipleLoad, baseTagName);
|
||||
}
|
||||
|
||||
break;
|
||||
case EConfigType.ProxyChain:
|
||||
await GenChainOutboundsList(childProfiles, singboxConfig, baseTagName);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.SaveLog(_tag, ex);
|
||||
}
|
||||
return await Task.FromResult(0);
|
||||
}
|
||||
|
||||
private async Task<int> GenOutboundMux(ProfileItem node, Outbound4Sbox outbound)
|
||||
{
|
||||
try
|
||||
|
|
|
|||
|
|
@ -385,8 +385,29 @@ public partial class CoreConfigSingboxService
|
|||
|
||||
if (node.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain)
|
||||
{
|
||||
ProfileGroupItemManager.Instance.TryGet(node.IndexId, out var profileGroupItem);
|
||||
if (profileGroupItem == null || profileGroupItem.ChildItems.IsNullOrEmpty())
|
||||
{
|
||||
return Global.ProxyTag;
|
||||
}
|
||||
var childProfiles = (await Task.WhenAll(
|
||||
Utils.String2List(profileGroupItem.ChildItems)
|
||||
.Where(p => !p.IsNullOrEmpty())
|
||||
.Select(AppManager.Instance.GetProfileItem)
|
||||
)).Where(p => p != null).ToList();
|
||||
if (childProfiles.Count <= 0)
|
||||
{
|
||||
return Global.ProxyTag;
|
||||
}
|
||||
var childBaseTagName = $"{Global.ProxyTag}-{node.IndexId}";
|
||||
var ret = await GenGroupOutbound(node, singboxConfig, childBaseTagName);
|
||||
var ret = node.ConfigType switch
|
||||
{
|
||||
EConfigType.PolicyGroup =>
|
||||
await GenOutboundsListWithChain(childProfiles, singboxConfig, profileGroupItem.MultipleLoad, childBaseTagName),
|
||||
EConfigType.ProxyChain =>
|
||||
await GenChainOutboundsList(childProfiles, singboxConfig, childBaseTagName),
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
if (ret == 0)
|
||||
{
|
||||
return childBaseTagName;
|
||||
|
|
|
|||
|
|
@ -15,8 +15,35 @@ public partial class CoreConfigV2rayService(Config config)
|
|||
var ret = new RetResult();
|
||||
try
|
||||
{
|
||||
if (node?.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain)
|
||||
{
|
||||
ProfileGroupItemManager.Instance.TryGet(node.IndexId, out var profileGroupItem);
|
||||
if (profileGroupItem == null || profileGroupItem.ChildItems.IsNullOrEmpty())
|
||||
{
|
||||
ret.Msg = ResUI.CheckServerSettings;
|
||||
return ret;
|
||||
}
|
||||
var childProfiles = (await Task.WhenAll(
|
||||
Utils.String2List(profileGroupItem.ChildItems)
|
||||
.Where(p => !p.IsNullOrEmpty())
|
||||
.Select(AppManager.Instance.GetProfileItem)
|
||||
)).Where(p => p != null).ToList();
|
||||
if (childProfiles.Count <= 0)
|
||||
{
|
||||
ret.Msg = ResUI.CheckServerSettings;
|
||||
return ret;
|
||||
}
|
||||
switch (node.ConfigType)
|
||||
{
|
||||
case EConfigType.PolicyGroup:
|
||||
return await GenerateClientMultipleLoadConfig(childProfiles, profileGroupItem.MultipleLoad);
|
||||
case EConfigType.ProxyChain:
|
||||
return await GenerateClientChainConfig(childProfiles);
|
||||
}
|
||||
}
|
||||
|
||||
if (node == null
|
||||
|| !node.IsValid())
|
||||
|| node.Port <= 0)
|
||||
{
|
||||
ret.Msg = ResUI.CheckServerSettings;
|
||||
return ret;
|
||||
|
|
@ -30,17 +57,6 @@ public partial class CoreConfigV2rayService(Config config)
|
|||
|
||||
ret.Msg = ResUI.InitialConfiguration;
|
||||
|
||||
if (node?.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain)
|
||||
{
|
||||
switch (node.ConfigType)
|
||||
{
|
||||
case EConfigType.PolicyGroup:
|
||||
return await GenerateClientMultipleLoadConfig(node);
|
||||
case EConfigType.ProxyChain:
|
||||
return await GenerateClientChainConfig(node);
|
||||
}
|
||||
}
|
||||
|
||||
var result = EmbedUtils.GetEmbedText(Global.V2raySampleClient);
|
||||
if (result.IsNullOrEmpty())
|
||||
{
|
||||
|
|
@ -82,7 +98,7 @@ public partial class CoreConfigV2rayService(Config config)
|
|||
}
|
||||
}
|
||||
|
||||
public async Task<RetResult> GenerateClientMultipleLoadConfig(ProfileItem parentNode)
|
||||
public async Task<RetResult> GenerateClientMultipleLoadConfig(List<ProfileItem> selecteds, EMultipleLoad multipleLoad)
|
||||
{
|
||||
var ret = new RetResult();
|
||||
|
||||
|
|
@ -118,12 +134,57 @@ public partial class CoreConfigV2rayService(Config config)
|
|||
await GenDns(null, v2rayConfig);
|
||||
await GenStatistic(v2rayConfig);
|
||||
|
||||
var groupRet = await GenGroupOutbound(parentNode, v2rayConfig);
|
||||
if (groupRet != 0)
|
||||
var proxyProfiles = new List<ProfileItem>();
|
||||
foreach (var it in selecteds)
|
||||
{
|
||||
if (it.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain)
|
||||
{
|
||||
var itemGroup = await AppManager.Instance.GetProfileItem(it.IndexId);
|
||||
proxyProfiles.Add(itemGroup);
|
||||
}
|
||||
if (!Global.XraySupportConfigType.Contains(it.ConfigType))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (it.Port <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var item = await AppManager.Instance.GetProfileItem(it.IndexId);
|
||||
if (item is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (it.ConfigType is EConfigType.VMess or EConfigType.VLESS)
|
||||
{
|
||||
if (item.Id.IsNullOrEmpty() || !Utils.IsGuidByParse(item.Id))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (item.ConfigType == EConfigType.Shadowsocks
|
||||
&& !Global.SsSecuritiesInSingbox.Contains(item.Security))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (item.ConfigType == EConfigType.VLESS && !Global.Flows.Contains(item.Flow))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//outbound
|
||||
proxyProfiles.Add(item);
|
||||
}
|
||||
if (proxyProfiles.Count <= 0)
|
||||
{
|
||||
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
||||
return ret;
|
||||
}
|
||||
await GenOutboundsListWithChain(proxyProfiles, v2rayConfig);
|
||||
|
||||
//add balancers
|
||||
await GenObservatory(v2rayConfig, multipleLoad);
|
||||
await GenBalancer(v2rayConfig, multipleLoad);
|
||||
|
||||
var defaultBalancerTag = $"{Global.ProxyTag}{Global.BalancerTagSuffix}";
|
||||
|
||||
|
|
@ -187,7 +248,7 @@ public partial class CoreConfigV2rayService(Config config)
|
|||
}
|
||||
}
|
||||
|
||||
public async Task<RetResult> GenerateClientChainConfig(ProfileItem parentNode)
|
||||
public async Task<RetResult> GenerateClientChainConfig(List<ProfileItem> selecteds)
|
||||
{
|
||||
var ret = new RetResult();
|
||||
|
||||
|
|
@ -223,12 +284,48 @@ public partial class CoreConfigV2rayService(Config config)
|
|||
await GenStatistic(v2rayConfig);
|
||||
v2rayConfig.outbounds.RemoveAt(0);
|
||||
|
||||
var groupRet = await GenGroupOutbound(parentNode, v2rayConfig);
|
||||
if (groupRet != 0)
|
||||
var proxyProfiles = new List<ProfileItem>();
|
||||
foreach (var it in selecteds)
|
||||
{
|
||||
if (!Global.XraySupportConfigType.Contains(it.ConfigType))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (it.Port <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var item = await AppManager.Instance.GetProfileItem(it.IndexId);
|
||||
if (item is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (it.ConfigType is EConfigType.VMess or EConfigType.VLESS)
|
||||
{
|
||||
if (item.Id.IsNullOrEmpty() || !Utils.IsGuidByParse(item.Id))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (item.ConfigType == EConfigType.Shadowsocks
|
||||
&& !Global.SsSecuritiesInSingbox.Contains(item.Security))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (item.ConfigType == EConfigType.VLESS && !Global.Flows.Contains(item.Flow))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//outbound
|
||||
proxyProfiles.Add(item);
|
||||
}
|
||||
if (proxyProfiles.Count <= 0)
|
||||
{
|
||||
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
||||
return ret;
|
||||
}
|
||||
await GenChainOutboundsList(proxyProfiles, v2rayConfig);
|
||||
|
||||
ret.Success = true;
|
||||
|
||||
|
|
@ -301,9 +398,12 @@ public partial class CoreConfigV2rayService(Config config)
|
|||
continue;
|
||||
}
|
||||
var item = await AppManager.Instance.GetProfileItem(it.IndexId);
|
||||
if (item is null || item.IsComplex() || !item.IsValid())
|
||||
if (it.ConfigType is EConfigType.VMess or EConfigType.VLESS)
|
||||
{
|
||||
continue;
|
||||
if (item is null || item.Id.IsNullOrEmpty() || !Utils.IsGuidByParse(item.Id))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
//find unused port
|
||||
|
|
@ -332,6 +432,28 @@ public partial class CoreConfigV2rayService(Config config)
|
|||
it.Port = port;
|
||||
it.AllowTest = true;
|
||||
|
||||
//outbound
|
||||
if (item is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (item.ConfigType == EConfigType.Shadowsocks
|
||||
&& !Global.SsSecuritiesInXray.Contains(item.Security))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (item.ConfigType == EConfigType.VLESS
|
||||
&& !Global.Flows.Contains(item.Flow))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (it.ConfigType is EConfigType.VLESS or EConfigType.Trojan
|
||||
&& item.StreamSecurity == Global.StreamSecurityReality
|
||||
&& item.PublicKey.IsNullOrEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//inbound
|
||||
Inbounds4Ray inbound = new()
|
||||
{
|
||||
|
|
@ -342,7 +464,6 @@ public partial class CoreConfigV2rayService(Config config)
|
|||
inbound.tag = inbound.protocol + inbound.port.ToString();
|
||||
v2rayConfig.inbounds.Add(inbound);
|
||||
|
||||
//outbound
|
||||
var outbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound);
|
||||
await GenOutbound(item, outbound);
|
||||
outbound.tag = Global.ProxyTag + inbound.port.ToString();
|
||||
|
|
@ -376,8 +497,7 @@ public partial class CoreConfigV2rayService(Config config)
|
|||
var ret = new RetResult();
|
||||
try
|
||||
{
|
||||
if (node == null
|
||||
|| !node.IsValid())
|
||||
if (node is not { Port: > 0 })
|
||||
{
|
||||
ret.Msg = ResUI.CheckServerSettings;
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -480,69 +480,6 @@ public partial class CoreConfigV2rayService
|
|||
return 0;
|
||||
}
|
||||
|
||||
private async Task<int> GenGroupOutbound(ProfileItem node, V2rayConfig v2rayConfig, string baseTagName = Global.ProxyTag, bool ignoreOriginChain = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (node.ConfigType is not (EConfigType.PolicyGroup or EConfigType.ProxyChain))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
ProfileGroupItemManager.Instance.TryGet(node.IndexId, out var profileGroupItem);
|
||||
if (profileGroupItem is null || profileGroupItem.ChildItems.IsNullOrEmpty())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
// remove custom nodes
|
||||
// remove group nodes for proxy chain
|
||||
var childProfiles = (await Task.WhenAll(
|
||||
Utils.String2List(profileGroupItem.ChildItems)
|
||||
.Where(p => !p.IsNullOrEmpty())
|
||||
.Select(AppManager.Instance.GetProfileItem)
|
||||
))
|
||||
.Where(p =>
|
||||
p != null &&
|
||||
p.IsValid() &&
|
||||
p.ConfigType != EConfigType.Custom &&
|
||||
(node.ConfigType == EConfigType.PolicyGroup || p.ConfigType < EConfigType.Group)
|
||||
)
|
||||
.ToList();
|
||||
|
||||
if (childProfiles.Count <= 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
switch (node.ConfigType)
|
||||
{
|
||||
case EConfigType.PolicyGroup:
|
||||
if (ignoreOriginChain)
|
||||
{
|
||||
await GenOutboundsList(childProfiles, v2rayConfig, baseTagName);
|
||||
}
|
||||
else
|
||||
{
|
||||
await GenOutboundsListWithChain(childProfiles, v2rayConfig, baseTagName);
|
||||
}
|
||||
break;
|
||||
case EConfigType.ProxyChain:
|
||||
await GenChainOutboundsList(childProfiles, v2rayConfig, baseTagName);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//add balancers
|
||||
await GenObservatory(v2rayConfig, profileGroupItem.MultipleLoad, baseTagName);
|
||||
await GenBalancer(v2rayConfig, profileGroupItem.MultipleLoad, baseTagName);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.SaveLog(_tag, ex);
|
||||
}
|
||||
return await Task.FromResult(0);
|
||||
}
|
||||
|
||||
private async Task<int> GenMoreOutbounds(ProfileItem node, V2rayConfig v2rayConfig)
|
||||
{
|
||||
//fragment proxy
|
||||
|
|
|
|||
|
|
@ -141,8 +141,33 @@ public partial class CoreConfigV2rayService
|
|||
|
||||
if (node.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain)
|
||||
{
|
||||
ProfileGroupItemManager.Instance.TryGet(node.IndexId, out var profileGroupItem);
|
||||
if (profileGroupItem == null || profileGroupItem.ChildItems.IsNullOrEmpty())
|
||||
{
|
||||
return Global.ProxyTag;
|
||||
}
|
||||
var childProfiles = (await Task.WhenAll(
|
||||
Utils.String2List(profileGroupItem.ChildItems)
|
||||
.Where(p => !p.IsNullOrEmpty())
|
||||
.Select(AppManager.Instance.GetProfileItem)
|
||||
)).Where(p => p != null).ToList();
|
||||
if (childProfiles.Count <= 0)
|
||||
{
|
||||
return Global.ProxyTag;
|
||||
}
|
||||
var childBaseTagName = $"{Global.ProxyTag}-{node.IndexId}";
|
||||
var ret = await GenGroupOutbound(node, v2rayConfig, childBaseTagName);
|
||||
var ret = node.ConfigType switch
|
||||
{
|
||||
EConfigType.PolicyGroup =>
|
||||
await GenOutboundsListWithChain(childProfiles, v2rayConfig, childBaseTagName),
|
||||
EConfigType.ProxyChain =>
|
||||
await GenChainOutboundsList(childProfiles, v2rayConfig, childBaseTagName),
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
if (node.ConfigType == EConfigType.PolicyGroup)
|
||||
{
|
||||
await GenBalancer(v2rayConfig, profileGroupItem.MultipleLoad, childBaseTagName);
|
||||
}
|
||||
if (ret == 0)
|
||||
{
|
||||
return childBaseTagName;
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@ public partial class AddGroupServerWindow
|
|||
|
||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||
});
|
||||
WindowsUtils.SetDarkBorder(this, AppManager.Instance.Config.UiItem.CurrentTheme);
|
||||
}
|
||||
|
||||
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
||||
|
|
|
|||
Loading…
Reference in a new issue