Avoids duplicate proxy chain generation

This commit is contained in:
DHR60 2025-06-30 14:30:58 +08:00
parent c6757ec122
commit fa7acd575a
2 changed files with 41 additions and 16 deletions

View file

@ -959,6 +959,7 @@ public class CoreConfigSingboxService
var proxyTags = new List<string>(); // For selector and urltest outbounds var proxyTags = new List<string>(); // For selector and urltest outbounds
// Cache for chain proxies to avoid duplicate generation // Cache for chain proxies to avoid duplicate generation
var nextProxyCache = new Dictionary<string, Outbound4Sbox?>();
var prevProxyTags = new Dictionary<string, string?>(); // Map from profile name to tag var prevProxyTags = new Dictionary<string, string?>(); // Map from profile name to tag
int prevIndex = 0; // Index for prev outbounds int prevIndex = 0; // Index for prev outbounds
@ -971,19 +972,24 @@ public class CoreConfigSingboxService
// Handle proxy chain // Handle proxy chain
string? prevTag = null; string? prevTag = null;
var currentOutbound = JsonUtils.Deserialize<Outbound4Sbox>(txtOutbound); var currentOutbound = JsonUtils.Deserialize<Outbound4Sbox>(txtOutbound);
Outbound4Sbox? nextOutbound = null; var nextOutbound = nextProxyCache.GetValueOrDefault(node.Subid, null);
if (nextOutbound != null)
{
nextOutbound = JsonUtils.DeepCopy(nextOutbound);
}
var subItem = await AppHandler.Instance.GetSubItem(node.Subid); var subItem = await AppHandler.Instance.GetSubItem(node.Subid);
// current proxy // current proxy
await GenOutbound(node, currentOutbound); await GenOutbound(node, currentOutbound);
currentOutbound.tag = $"{Global.ProxyTag}-{index}"; currentOutbound.tag = $"{Global.ProxyTag}-{index}";
proxyTags.Add(currentOutbound.tag);
if (!node.Subid.IsNullOrEmpty()) if (!node.Subid.IsNullOrEmpty())
{ {
if (prevProxyTags.ContainsKey(node.Subid)) if (prevProxyTags.TryGetValue(node.Subid, out var value))
{ {
prevTag = prevProxyTags[node.Subid]; // maybe null prevTag = value; // maybe null
} }
else else
{ {
@ -1000,7 +1006,11 @@ public class CoreConfigSingboxService
prevProxyTags[node.Subid] = prevTag; prevProxyTags[node.Subid] = prevTag;
} }
nextOutbound = await GenChainOutbounds(subItem, currentOutbound, prevTag); nextOutbound = await GenChainOutbounds(subItem, currentOutbound, prevTag, nextOutbound);
if (!nextProxyCache.ContainsKey(node.Subid))
{
nextProxyCache[node.Subid] = nextOutbound;
}
} }
if (nextOutbound is not null) if (nextOutbound is not null)
@ -1057,10 +1067,11 @@ public class CoreConfigSingboxService
/// <param name="subItem">The subscription item containing proxy chain information.</param> /// <param name="subItem">The subscription item containing proxy chain information.</param>
/// <param name="outbound">The current outbound configuration. Its tag must be set before calling this method.</param> /// <param name="outbound">The current outbound configuration. Its tag must be set before calling this method.</param>
/// <param name="prevOutboundTag">The tag of the previous outbound in the chain, if any.</param> /// <param name="prevOutboundTag">The tag of the previous outbound in the chain, if any.</param>
/// <param name="nextOutbound">The outbound for the next proxy in the chain, if already created. If null, will be created inside.</param>
/// <returns> /// <returns>
/// The outbound configuration for the next proxy in the chain, or null if no next proxy exists. /// The outbound configuration for the next proxy in the chain, or null if no next proxy exists.
/// </returns> /// </returns>
private async Task<Outbound4Sbox?> GenChainOutbounds(SubItem subItem, Outbound4Sbox outbound, string? prevOutboundTag) private async Task<Outbound4Sbox?> GenChainOutbounds(SubItem subItem, Outbound4Sbox outbound, string? prevOutboundTag, Outbound4Sbox? nextOutbound = null)
{ {
try try
{ {
@ -1073,12 +1084,14 @@ public class CoreConfigSingboxService
// Next proxy // Next proxy
var nextNode = await AppHandler.Instance.GetProfileItemViaRemarks(subItem.NextProfile); var nextNode = await AppHandler.Instance.GetProfileItemViaRemarks(subItem.NextProfile);
Outbound4Sbox? nextOutbound = null;
if (nextNode is not null if (nextNode is not null
&& nextNode.ConfigType != EConfigType.Custom) && nextNode.ConfigType != EConfigType.Custom)
{
if (nextOutbound == null)
{ {
nextOutbound = JsonUtils.Deserialize<Outbound4Sbox>(txtOutbound); nextOutbound = JsonUtils.Deserialize<Outbound4Sbox>(txtOutbound);
await GenOutbound(nextNode, nextOutbound); await GenOutbound(nextNode, nextOutbound);
}
nextOutbound.tag = outbound.tag; nextOutbound.tag = outbound.tag;
outbound.tag = $"mid-{outbound.tag}"; outbound.tag = $"mid-{outbound.tag}";

View file

@ -1360,6 +1360,7 @@ public class CoreConfigV2rayService
var prevOutbounds = new List<Outbounds4Ray>(); // Separate list for prev outbounds and fragment var prevOutbounds = new List<Outbounds4Ray>(); // Separate list for prev outbounds and fragment
// Cache for chain proxies to avoid duplicate generation // Cache for chain proxies to avoid duplicate generation
var nextProxyCache = new Dictionary<string, Outbounds4Ray?>();
var prevProxyTags = new Dictionary<string, string?>(); // Map from profile name to tag var prevProxyTags = new Dictionary<string, string?>(); // Map from profile name to tag
int prevIndex = 0; // Index for prev outbounds int prevIndex = 0; // Index for prev outbounds
@ -1372,7 +1373,11 @@ public class CoreConfigV2rayService
// Handle proxy chain // Handle proxy chain
string? prevTag = null; string? prevTag = null;
var currentOutbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound); var currentOutbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound);
Outbounds4Ray? nextOutbound = null; var nextOutbound = nextProxyCache.GetValueOrDefault(node.Subid, null);
if (nextOutbound != null)
{
nextOutbound = JsonUtils.DeepCopy(nextOutbound);
}
var subItem = await AppHandler.Instance.GetSubItem(node.Subid); var subItem = await AppHandler.Instance.GetSubItem(node.Subid);
@ -1382,9 +1387,9 @@ public class CoreConfigV2rayService
if (!node.Subid.IsNullOrEmpty()) if (!node.Subid.IsNullOrEmpty())
{ {
if (prevProxyTags.ContainsKey(node.Subid)) if (prevProxyTags.TryGetValue(node.Subid, out var value))
{ {
prevTag = prevProxyTags[node.Subid]; // maybe null prevTag = value; // maybe null
} }
else else
{ {
@ -1403,7 +1408,11 @@ public class CoreConfigV2rayService
prevProxyTags[node.Subid] = prevTag; prevProxyTags[node.Subid] = prevTag;
} }
nextOutbound = await GenChainOutbounds(subItem, currentOutbound, prevTag); nextOutbound = await GenChainOutbounds(subItem, currentOutbound, prevTag, nextOutbound);
if (!nextProxyCache.ContainsKey(node.Subid))
{
nextProxyCache[node.Subid] = nextOutbound;
}
} }
if (nextOutbound is not null) if (nextOutbound is not null)
@ -1434,10 +1443,11 @@ public class CoreConfigV2rayService
/// <param name="subItem">The subscription item containing proxy chain information.</param> /// <param name="subItem">The subscription item containing proxy chain information.</param>
/// <param name="outbound">The current outbound configuration. Its tag must be set before calling this method.</param> /// <param name="outbound">The current outbound configuration. Its tag must be set before calling this method.</param>
/// <param name="prevOutboundTag">The tag of the previous outbound in the chain, if any.</param> /// <param name="prevOutboundTag">The tag of the previous outbound in the chain, if any.</param>
/// <param name="nextOutbound">The outbound for the next proxy in the chain, if already created. If null, will be created inside.</param>
/// <returns> /// <returns>
/// The outbound configuration for the next proxy in the chain, or null if no next proxy exists. /// The outbound configuration for the next proxy in the chain, or null if no next proxy exists.
/// </returns> /// </returns>
private async Task<Outbounds4Ray?> GenChainOutbounds(SubItem subItem, Outbounds4Ray outbound, string? prevOutboundTag) private async Task<Outbounds4Ray?> GenChainOutbounds(SubItem subItem, Outbounds4Ray outbound, string? prevOutboundTag, Outbounds4Ray? nextOutbound = null)
{ {
try try
{ {
@ -1453,14 +1463,16 @@ public class CoreConfigV2rayService
// Next proxy // Next proxy
var nextNode = await AppHandler.Instance.GetProfileItemViaRemarks(subItem.NextProfile); var nextNode = await AppHandler.Instance.GetProfileItemViaRemarks(subItem.NextProfile);
Outbounds4Ray? nextOutbound = null;
if (nextNode is not null if (nextNode is not null
&& nextNode.ConfigType != EConfigType.Custom && nextNode.ConfigType != EConfigType.Custom
&& nextNode.ConfigType != EConfigType.Hysteria2 && nextNode.ConfigType != EConfigType.Hysteria2
&& nextNode.ConfigType != EConfigType.TUIC) && nextNode.ConfigType != EConfigType.TUIC)
{
if (nextOutbound == null)
{ {
nextOutbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound); nextOutbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound);
await GenOutbound(nextNode, nextOutbound); await GenOutbound(nextNode, nextOutbound);
}
nextOutbound.tag = outbound.tag; nextOutbound.tag = outbound.tag;
outbound.tag = $"mid-{outbound.tag}"; outbound.tag = $"mid-{outbound.tag}";