Compare commits

..

25 commits

Author SHA1 Message Date
DHR60
c9ed6c1ea8
Merge 4bf86665b7 into 5d6c5da9d9 2025-09-29 09:22:00 +00:00
DHR60
4bf86665b7 Avoids circular dependency in profile groups
Adds cycle detection to prevent infinite loops when evaluating profile groups.

This ensures that profile group configurations don't result in stack overflow errors when groups reference each other, directly or indirectly.
2025-09-29 17:19:35 +08:00
DHR60
ae46b39110 Improves Tun2Socks address handling 2025-09-29 16:43:57 +08:00
DHR60
836217266e Fix 2025-09-29 16:43:56 +08:00
DHR60
4e3c2991f9 Avoid self-reference 2025-09-29 16:43:56 +08:00
DHR60
cdab7a097f Add chain selection control to group outbounds 2025-09-29 16:43:56 +08:00
DHR60
1d8b8491ea Refactor 2025-09-29 16:43:56 +08:00
DHR60
04dae54654 Add helper function 2025-09-29 16:43:56 +08:00
DHR60
63bf68376f Adjust chained proxy, actual outbound is at the top
Based on actual network flow instead of data packets
2025-09-29 16:43:56 +08:00
DHR60
826f9f833a Refactor 2025-09-29 16:43:56 +08:00
DHR60
9317c73084 Avoid duplicate tags 2025-09-29 16:43:56 +08:00
DHR60
2d5a5465df Add group in traffic splitting support 2025-09-29 16:43:56 +08:00
DHR60
af62d9e0f4 Add PolicyGroup include other Group support 2025-09-29 16:43:56 +08:00
DHR60
2ab044b4fc Add fallback support 2025-09-29 16:43:56 +08:00
DHR60
c76d125ce1 Fix 2025-09-29 16:43:56 +08:00
DHR60
183be53153 Add Proxy Chain support 2025-09-29 16:43:56 +08:00
DHR60
52d1eb1e2b Adjust UI 2025-09-29 16:43:56 +08:00
DHR60
521dca33d5 Add generate policy group 2025-09-29 16:43:56 +08:00
DHR60
a323484ee3 Add Policy Group support 2025-09-29 16:43:55 +08:00
DHR60
9a43003c47 Rename 2025-09-29 16:43:55 +08:00
DHR60
e97b98f4bf Exclude specific profile types from selection 2025-09-29 16:43:55 +08:00
DHR60
bd3a733057 Fix right click not working 2025-09-29 16:43:55 +08:00
DHR60
0cde086448 avalonia 2025-09-29 16:43:55 +08:00
DHR60
8561311a45 VM and wpf 2025-09-29 16:43:55 +08:00
DHR60
57fd56fc05 Multi Profile 2025-09-29 16:43:55 +08:00
3 changed files with 50 additions and 2 deletions

View file

@ -109,6 +109,42 @@ public class ProfileItem : ReactiveObject
return true; return true;
} }
public async Task<bool> HasCycle(HashSet<string> visited, HashSet<string> stack)
{
if (ConfigType < EConfigType.Group)
return false;
if (stack.Contains(IndexId))
return true;
if (visited.Contains(IndexId))
return false;
visited.Add(IndexId);
stack.Add(IndexId);
if (ProfileGroupItemManager.Instance.TryGet(IndexId, out var group)
&& !group.ChildItems.IsNullOrEmpty())
{
var childProfiles = (await Task.WhenAll(
Utils.String2List(group.ChildItems)
.Where(p => !p.IsNullOrEmpty())
.Select(AppManager.Instance.GetProfileItem)
))
.Where(p => p != null)
.ToList();
foreach (var child in childProfiles)
{
if (await child.HasCycle(visited, stack))
return true;
}
}
stack.Remove(IndexId);
return false;
}
#endregion function #endregion function
[PrimaryKey] [PrimaryKey]

View file

@ -217,9 +217,15 @@ public partial class CoreConfigSingboxService
{ {
return -1; return -1;
} }
var hasCycle = await node.HasCycle(new HashSet<string>(), new HashSet<string>());
if (hasCycle)
{
return -1;
}
// remove custom nodes // remove custom nodes
// remove group nodes for proxy chain // remove group nodes for proxy chain
// avoid self-reference
var childProfiles = (await Task.WhenAll( var childProfiles = (await Task.WhenAll(
Utils.String2List(profileGroupItem.ChildItems) Utils.String2List(profileGroupItem.ChildItems)
.Where(p => !p.IsNullOrEmpty()) .Where(p => !p.IsNullOrEmpty())
@ -230,7 +236,6 @@ public partial class CoreConfigSingboxService
&& p.IsValid() && p.IsValid()
&& p.ConfigType != EConfigType.Custom && p.ConfigType != EConfigType.Custom
&& (node.ConfigType == EConfigType.PolicyGroup || p.ConfigType < EConfigType.Group) && (node.ConfigType == EConfigType.PolicyGroup || p.ConfigType < EConfigType.Group)
&& p.IndexId != node.IndexId
) )
.ToList(); .ToList();

View file

@ -493,6 +493,13 @@ public partial class CoreConfigV2rayService
{ {
return -1; return -1;
} }
var hasCycle = await node.HasCycle(new HashSet<string>(), new HashSet<string>());
if (hasCycle)
{
return -1;
}
// remove custom nodes // remove custom nodes
// remove group nodes for proxy chain // remove group nodes for proxy chain
var childProfiles = (await Task.WhenAll( var childProfiles = (await Task.WhenAll(