Skip to content

Commit 9c82df5

Browse files
authored
Refactor core config gen (2dust#8768)
* Refactor core config gen * Update tag naming * Support sing-box 1.11 DNS * Fix * Optimize ProfileItem acquisition speed * Fix * Fix
1 parent b5800f7 commit 9c82df5

29 files changed

+1256
-2179
lines changed

v2rayN/ServiceLib/Global.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ public class Global
1515
public const string CoreConfigFileName = "config.json";
1616
public const string CorePreConfigFileName = "configPre.json";
1717
public const string CoreSpeedtestConfigFileName = "configTest{0}.json";
18-
public const string CoreMultipleLoadConfigFileName = "configMultipleLoad.json";
1918
public const string ClashMixinConfigFileName = "Mixin.yaml";
2019

2120
public const string NamespaceSample = "ServiceLib.Sample.";
@@ -88,7 +87,6 @@ public class Global
8887
public const string SingboxLocalDNSTag = "local_local";
8988
public const string SingboxHostsDNSTag = "hosts_dns";
9089
public const string SingboxFakeDNSTag = "fake_dns";
91-
public const string SingboxEchDNSTag = "ech_dns";
9290

9391
public const int Hysteria2DefaultHopInt = 10;
9492

v2rayN/ServiceLib/Handler/ConfigHandler.cs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1231,26 +1231,16 @@ public static async Task<RetResult> AddGroupServer4Multiple(Config config, List<
12311231
/// <param name="node">Server node that might need pre-SOCKS</param>
12321232
/// <param name="coreType">Core type being used</param>
12331233
/// <returns>A SOCKS profile item or null if not needed</returns>
1234-
public static async Task<ProfileItem?> GetPreSocksItem(Config config, ProfileItem node, ECoreType coreType)
1234+
public static ProfileItem? GetPreSocksItem(Config config, ProfileItem node, ECoreType coreType)
12351235
{
12361236
ProfileItem? itemSocks = null;
12371237
if (node.ConfigType != EConfigType.Custom && coreType != ECoreType.sing_box && config.TunModeItem.EnableTun)
12381238
{
1239-
var tun2SocksAddress = node.Address;
1240-
if (node.ConfigType.IsGroupType())
1241-
{
1242-
var lstAddresses = (await GroupProfileManager.GetAllChildDomainAddresses(node)).ToList();
1243-
if (lstAddresses.Count > 0)
1244-
{
1245-
tun2SocksAddress = Utils.List2String(lstAddresses);
1246-
}
1247-
}
12481239
itemSocks = new ProfileItem()
12491240
{
12501241
CoreType = ECoreType.sing_box,
12511242
ConfigType = EConfigType.SOCKS,
12521243
Address = Global.Loopback,
1253-
SpiderX = tun2SocksAddress, // Tun2SocksAddress
12541244
Port = AppManager.Instance.GetLocalPort(EInboundProtocol.socks)
12551245
};
12561246
}
@@ -1265,7 +1255,6 @@ public static async Task<RetResult> AddGroupServer4Multiple(Config config, List<
12651255
Port = node.PreSocksPort.Value,
12661256
};
12671257
}
1268-
await Task.CompletedTask;
12691258
return itemSocks;
12701259
}
12711260

v2rayN/ServiceLib/Handler/CoreConfigHandler.cs

Lines changed: 141 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,27 @@ public static class CoreConfigHandler
77
{
88
private static readonly string _tag = "CoreConfigHandler";
99

10-
public static async Task<RetResult> GenerateClientConfig(ProfileItem node, string? fileName)
10+
public static async Task<RetResult> GenerateClientConfig(CoreConfigContext context, string? fileName)
1111
{
1212
var config = AppManager.Instance.Config;
1313
var result = new RetResult();
14+
var node = context.Node;
1415

1516
if (node.ConfigType == EConfigType.Custom)
1617
{
1718
result = node.CoreType switch
1819
{
1920
ECoreType.mihomo => await new CoreConfigClashService(config).GenerateClientCustomConfig(node, fileName),
20-
ECoreType.sing_box => await new CoreConfigSingboxService(config).GenerateClientCustomConfig(node, fileName),
2121
_ => await GenerateClientCustomConfig(node, fileName)
2222
};
2323
}
2424
else if (AppManager.Instance.GetCoreType(node, node.ConfigType) == ECoreType.sing_box)
2525
{
26-
result = await new CoreConfigSingboxService(config).GenerateClientConfigContent(node);
26+
result = new CoreConfigSingboxService(context).GenerateClientConfigContent();
2727
}
2828
else
2929
{
30-
result = await new CoreConfigV2rayService(config).GenerateClientConfigContent(node);
30+
result = new CoreConfigV2rayService(context).GenerateClientConfigContent();
3131
}
3232
if (result.Success != true)
3333
{
@@ -93,13 +93,21 @@ private static async Task<RetResult> GenerateClientCustomConfig(ProfileItem node
9393
public static async Task<RetResult> GenerateClientSpeedtestConfig(Config config, string fileName, List<ServerTestItem> selecteds, ECoreType coreType)
9494
{
9595
var result = new RetResult();
96+
var context = await BuildCoreConfigContext(config, new());
97+
var ids = selecteds.Where(serverTestItem => !serverTestItem.IndexId.IsNullOrEmpty())
98+
.Select(serverTestItem => serverTestItem.IndexId);
99+
var nodes = await AppManager.Instance.GetProfileItemsByIndexIds(ids);
100+
foreach (var node in nodes)
101+
{
102+
await FillNodeContext(context, node, false);
103+
}
96104
if (coreType == ECoreType.sing_box)
97105
{
98-
result = await new CoreConfigSingboxService(config).GenerateClientSpeedtestConfig(selecteds);
106+
result = new CoreConfigSingboxService(context).GenerateClientSpeedtestConfig(selecteds);
99107
}
100108
else if (coreType == ECoreType.Xray)
101109
{
102-
result = await new CoreConfigV2rayService(config).GenerateClientSpeedtestConfig(selecteds);
110+
result = new CoreConfigV2rayService(context).GenerateClientSpeedtestConfig(selecteds);
103111
}
104112
if (result.Success != true)
105113
{
@@ -109,20 +117,21 @@ public static async Task<RetResult> GenerateClientSpeedtestConfig(Config config,
109117
return result;
110118
}
111119

112-
public static async Task<RetResult> GenerateClientSpeedtestConfig(Config config, ProfileItem node, ServerTestItem testItem, string fileName)
120+
public static async Task<RetResult> GenerateClientSpeedtestConfig(Config config, CoreConfigContext context, ServerTestItem testItem, string fileName)
113121
{
114122
var result = new RetResult();
123+
var node = context.Node;
115124
var initPort = AppManager.Instance.GetLocalPort(EInboundProtocol.speedtest);
116125
var port = Utils.GetFreePort(initPort + testItem.QueueNum);
117126
testItem.Port = port;
118127

119128
if (AppManager.Instance.GetCoreType(node, node.ConfigType) == ECoreType.sing_box)
120129
{
121-
result = await new CoreConfigSingboxService(config).GenerateClientSpeedtestConfig(node, port);
130+
result = new CoreConfigSingboxService(context).GenerateClientSpeedtestConfig(port);
122131
}
123132
else
124133
{
125-
result = await new CoreConfigV2rayService(config).GenerateClientSpeedtestConfig(node, port);
134+
result = new CoreConfigV2rayService(context).GenerateClientSpeedtestConfig(port);
126135
}
127136
if (result.Success != true)
128137
{
@@ -132,4 +141,127 @@ public static async Task<RetResult> GenerateClientSpeedtestConfig(Config config,
132141
await File.WriteAllTextAsync(fileName, result.Data.ToString());
133142
return result;
134143
}
144+
145+
public static async Task<CoreConfigContext> BuildCoreConfigContext(Config config, ProfileItem node)
146+
{
147+
var coreType = AppManager.Instance.GetCoreType(node, node.ConfigType) == ECoreType.sing_box ? ECoreType.sing_box : ECoreType.Xray;
148+
var context = new CoreConfigContext()
149+
{
150+
Node = node,
151+
AllProxiesMap = [],
152+
AppConfig = config,
153+
FullConfigTemplate = await AppManager.Instance.GetFullConfigTemplateItem(coreType),
154+
IsTunEnabled = config.TunModeItem.EnableTun,
155+
SimpleDnsItem = config.SimpleDNSItem,
156+
ProtectDomainList = [],
157+
ProtectSocksPort = 0,
158+
RawDnsItem = await AppManager.Instance.GetDNSItem(coreType),
159+
RoutingItem = await ConfigHandler.GetDefaultRouting(config),
160+
};
161+
context = context with
162+
{
163+
Node = await FillNodeContext(context, node)
164+
};
165+
if (!(context.RoutingItem?.RuleSet.IsNullOrEmpty() ?? true))
166+
{
167+
var rules = JsonUtils.Deserialize<List<RulesItem>>(context.RoutingItem?.RuleSet);
168+
foreach (var ruleItem in rules.Where(ruleItem => !Global.OutboundTags.Contains(ruleItem.OutboundTag)))
169+
{
170+
var ruleOutboundNode = await AppManager.Instance.GetProfileItemViaRemarks(ruleItem.OutboundTag);
171+
if (ruleOutboundNode != null)
172+
{
173+
var ruleOutboundNodeAct = await FillNodeContext(context, ruleOutboundNode, false);
174+
context.AllProxiesMap[$"remark:{ruleItem.OutboundTag}"] = ruleOutboundNodeAct;
175+
}
176+
}
177+
}
178+
return context;
179+
}
180+
181+
private static async Task<ProfileItem> FillNodeContext(CoreConfigContext context, ProfileItem node, bool includeSubChain = true)
182+
{
183+
if (node.IndexId.IsNullOrEmpty())
184+
{
185+
return node;
186+
}
187+
var newItems = new List<ProfileItem> { node };
188+
if (node.ConfigType.IsGroupType())
189+
{
190+
var (groupChildList, _) = await GroupProfileManager.GetChildProfileItems(node);
191+
foreach (var childItem in groupChildList.Where(childItem => !context.AllProxiesMap.ContainsKey(childItem.IndexId)))
192+
{
193+
await FillNodeContext(context, childItem, false);
194+
}
195+
node.SetProtocolExtra(node.GetProtocolExtra() with
196+
{
197+
ChildItems = Utils.List2String(groupChildList.Select(n => n.IndexId).ToList()),
198+
});
199+
newItems.AddRange(groupChildList);
200+
}
201+
context.AllProxiesMap[node.IndexId] = node;
202+
203+
foreach (var item in newItems)
204+
{
205+
var address = item.Address;
206+
if (Utils.IsDomain(address))
207+
{
208+
context.ProtectDomainList.Add(address);
209+
}
210+
211+
if (item.EchConfigList.IsNullOrEmpty())
212+
{
213+
continue;
214+
}
215+
216+
var echQuerySni = item.Sni;
217+
if (item.StreamSecurity == Global.StreamSecurity
218+
&& item.EchConfigList?.Contains("://") == true)
219+
{
220+
var idx = item.EchConfigList.IndexOf('+');
221+
echQuerySni = idx > 0 ? item.EchConfigList[..idx] : item.Sni;
222+
}
223+
if (!Utils.IsDomain(echQuerySni))
224+
{
225+
continue;
226+
}
227+
context.ProtectDomainList.Add(echQuerySni);
228+
}
229+
230+
if (!includeSubChain || node.Subid.IsNullOrEmpty())
231+
{
232+
return node;
233+
}
234+
235+
var subItem = await AppManager.Instance.GetSubItem(node.Subid);
236+
if (subItem == null)
237+
{
238+
return node;
239+
}
240+
var prevNode = await AppManager.Instance.GetProfileItemViaRemarks(subItem.PrevProfile);
241+
var nextNode = await AppManager.Instance.GetProfileItemViaRemarks(subItem.NextProfile);
242+
if (prevNode is null && nextNode is null)
243+
{
244+
return node;
245+
}
246+
247+
var prevNodeAct = prevNode is null ? null : await FillNodeContext(context, prevNode, false);
248+
var nextNodeAct = nextNode is null ? null : await FillNodeContext(context, nextNode, false);
249+
250+
// Build new proxy chain node
251+
var chainNode = new ProfileItem()
252+
{
253+
IndexId = $"inner-{Utils.GetGuid(false)}",
254+
ConfigType = EConfigType.ProxyChain,
255+
CoreType = node.CoreType ?? ECoreType.Xray,
256+
};
257+
List<string?> childItems = [prevNodeAct?.IndexId, node.IndexId, nextNodeAct?.IndexId];
258+
var chainExtraItem = chainNode.GetProtocolExtra() with
259+
{
260+
GroupType = chainNode.ConfigType.ToString(),
261+
ChildItems = string.Join(",", childItems.Where(x => !x.IsNullOrEmpty())),
262+
};
263+
chainNode.SetProtocolExtra(chainExtraItem);
264+
context.AllProxiesMap[chainNode.IndexId] = chainNode;
265+
return chainNode;
266+
}
135267
}

v2rayN/ServiceLib/Manager/AppManager.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,18 @@ from ProfileItem a
230230
return await SQLiteHelper.Instance.TableAsync<ProfileItem>().FirstOrDefaultAsync(it => it.IndexId == indexId);
231231
}
232232

233+
public async Task<List<ProfileItem>> GetProfileItemsByIndexIds(IEnumerable<string> indexIds)
234+
{
235+
var ids = indexIds.Where(id => !id.IsNullOrEmpty()).Distinct().ToList();
236+
if (ids.Count == 0)
237+
{
238+
return [];
239+
}
240+
return await SQLiteHelper.Instance.TableAsync<ProfileItem>()
241+
.Where(it => ids.Contains(it.IndexId))
242+
.ToListAsync();
243+
}
244+
233245
public async Task<ProfileItem?> GetProfileItemViaRemarks(string? remarks)
234246
{
235247
if (remarks.IsNullOrEmpty())

v2rayN/ServiceLib/Manager/CoreManager.cs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@ public async Task LoadCore(ProfileItem? node)
6666
}
6767

6868
var fileName = Utils.GetBinConfigPath(Global.CoreConfigFileName);
69-
var result = await CoreConfigHandler.GenerateClientConfig(node, fileName);
69+
var context = await CoreConfigHandler.BuildCoreConfigContext(_config, node);
70+
context = context with { IsTunEnabled = _config.TunModeItem.EnableTun };
71+
var result = await CoreConfigHandler.GenerateClientConfig(context, fileName);
7072
if (result.Success != true)
7173
{
7274
await UpdateFunc(true, result.Msg);
@@ -85,8 +87,8 @@ public async Task LoadCore(ProfileItem? node)
8587
await WindowsUtils.RemoveTunDevice();
8688
}
8789

88-
await CoreStart(node);
89-
await CoreStartPreService(node);
90+
await CoreStart(context);
91+
await CoreStartPreService(context);
9092
if (_processService != null)
9193
{
9294
await UpdateFunc(true, $"{node.GetSummary()}");
@@ -122,7 +124,8 @@ public async Task LoadCore(ProfileItem? node)
122124

123125
var fileName = string.Format(Global.CoreSpeedtestConfigFileName, Utils.GetGuid(false));
124126
var configPath = Utils.GetBinConfigPath(fileName);
125-
var result = await CoreConfigHandler.GenerateClientSpeedtestConfig(_config, node, testItem, configPath);
127+
var context = await CoreConfigHandler.BuildCoreConfigContext(_config, node);
128+
var result = await CoreConfigHandler.GenerateClientSpeedtestConfig(_config, context, testItem, configPath);
126129
if (result.Success != true)
127130
{
128131
return null;
@@ -165,8 +168,9 @@ public async Task CoreStop()
165168

166169
#region Private
167170

168-
private async Task CoreStart(ProfileItem node)
171+
private async Task CoreStart(CoreConfigContext context)
169172
{
173+
var node = context.Node;
170174
var coreType = AppManager.Instance.RunningCoreType = AppManager.Instance.GetCoreType(node, node.ConfigType);
171175
var coreInfo = CoreInfoManager.Instance.GetCoreInfo(coreType);
172176

@@ -179,17 +183,20 @@ private async Task CoreStart(ProfileItem node)
179183
_processService = proc;
180184
}
181185

182-
private async Task CoreStartPreService(ProfileItem node)
186+
private async Task CoreStartPreService(CoreConfigContext context)
183187
{
188+
var node = context.Node;
184189
if (_processService != null && !_processService.HasExited)
185190
{
186191
var coreType = AppManager.Instance.GetCoreType(node, node.ConfigType);
187-
var itemSocks = await ConfigHandler.GetPreSocksItem(_config, node, coreType);
192+
var itemSocks = ConfigHandler.GetPreSocksItem(_config, node, coreType);
188193
if (itemSocks != null)
189194
{
190195
var preCoreType = itemSocks.CoreType ?? ECoreType.sing_box;
191196
var fileName = Utils.GetBinConfigPath(Global.CorePreConfigFileName);
192-
var result = await CoreConfigHandler.GenerateClientConfig(itemSocks, fileName);
197+
var itemSocksContext = await CoreConfigHandler.BuildCoreConfigContext(_config, itemSocks);
198+
itemSocksContext.ProtectDomainList.AddRangeSafe(context.ProtectDomainList);
199+
var result = await CoreConfigHandler.GenerateClientConfig(itemSocksContext, fileName);
193200
if (result.Success)
194201
{
195202
var coreInfo = CoreInfoManager.Instance.GetCoreInfo(preCoreType);

0 commit comments

Comments
 (0)