Config Handler

This commit is contained in:
DHR60 2025-07-24 12:48:52 +08:00
parent c899d534af
commit b8dbe61db3
2 changed files with 149 additions and 78 deletions

View file

@ -1197,43 +1197,6 @@ public class ConfigHandler
return result; return result;
} }
/// <summary>
/// Get a SOCKS server profile for pre-SOCKS functionality
/// Used when TUN mode is enabled or when a custom config has a pre-SOCKS port
/// </summary>
/// <param name="config">Current configuration</param>
/// <param name="node">Server node that might need pre-SOCKS</param>
/// <param name="coreType">Core type being used</param>
/// <returns>A SOCKS profile item or null if not needed</returns>
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)
{
itemSocks = new ProfileItem()
{
CoreType = ECoreType.sing_box,
ConfigType = EConfigType.SOCKS,
Address = Global.Loopback,
Sni = node.Address, //Tun2SocksAddress
Port = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks)
};
}
else if ((node.ConfigType == EConfigType.Custom && node.PreSocksPort > 0))
{
var preCoreType = config.RunningCoreType = config.TunModeItem.EnableTun ? ECoreType.sing_box : ECoreType.Xray;
itemSocks = new ProfileItem()
{
CoreType = preCoreType,
ConfigType = EConfigType.SOCKS,
Address = Global.Loopback,
Port = node.PreSocksPort.Value,
};
}
await Task.CompletedTask;
return itemSocks;
}
/// <summary> /// <summary>
/// Remove servers with invalid test results (timeout) /// Remove servers with invalid test results (timeout)
/// Useful for cleaning up subscription lists /// Useful for cleaning up subscription lists

View file

@ -1,5 +1,7 @@
using System.Diagnostics; using System.Diagnostics;
using System.Text; using System.Text;
using ServiceLib.Enums;
using ServiceLib.Models;
namespace ServiceLib.Handler; namespace ServiceLib.Handler;
@ -71,28 +73,24 @@ public class CoreHandler
return; return;
} }
var fileName = Utils.GetBinConfigPath(Global.CoreConfigFileName); // Create launch context and configure parameters
var result = await CoreConfigHandler.GenerateClientConfig(node, fileName); var context = new CoreLaunchContext(node, _config);
if (result.Success != true) context.AdjustForConfigType();
context.AdjustForSplitCore();
// Start main core
if (!await CoreStart(context))
{ {
UpdateFunc(true, result.Msg);
return; return;
} }
UpdateFunc(false, $"{node.GetSummary()}"); // Start pre-core if needed
UpdateFunc(false, $"{Utils.GetRuntimeInfo()}"); if (!await CoreStartPreService(context))
UpdateFunc(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
await CoreStop();
await Task.Delay(100);
if (Utils.IsWindows() && _config.TunModeItem.EnableTun)
{ {
await Task.Delay(100); await CoreStop(); // Clean up main core if pre-core fails
await WindowsUtils.RemoveTunDevice(); return;
} }
await CoreStart(node);
await CoreStartPreService(node);
if (_process != null) if (_process != null)
{ {
UpdateFunc(true, $"{node.GetSummary()}"); UpdateFunc(true, $"{node.GetSummary()}");
@ -181,43 +179,153 @@ public class CoreHandler
#region Private #region Private
private async Task CoreStart(ProfileItem node) /// <summary>
/// Core launch context that encapsulates all parameters required for launching
/// </summary>
private class CoreLaunchContext
{ {
var coreType = _config.RunningCoreType = AppHandler.Instance.GetCoreType(node, node.ConfigType); public ProfileItem Node { get; set; }
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType); public bool SplitCore { get; set; }
public ECoreType CoreType { get; set; }
public ECoreType? PreCoreType { get; set; }
public ECoreType PureEndpointCore { get; set; }
public ECoreType SplitRouteCore { get; set; }
public bool EnableTun { get; set; }
public int PreSocksPort { get; set; }
var displayLog = node.ConfigType != EConfigType.Custom || node.DisplayLog; public CoreLaunchContext(ProfileItem node, Config config)
var proc = await RunProcess(coreInfo, Global.CoreConfigFileName, displayLog, true);
if (proc is null)
{ {
return; Node = node;
SplitCore = config.SplitCoreItem.EnableSplitCore;
CoreType = AppHandler.Instance.GetCoreType(node, node.ConfigType);
PureEndpointCore = AppHandler.Instance.GetSplitCoreType(node, node.ConfigType);
SplitRouteCore = config.SplitCoreItem.RouteCoreType;
EnableTun = config.TunModeItem.EnableTun;
PreSocksPort = 0;
PreCoreType = null;
} }
_process = proc;
}
private async Task CoreStartPreService(ProfileItem node) /// <summary>
{ /// Adjust context parameters based on configuration type
if (_process != null && !_process.HasExited) /// </summary>
public void AdjustForConfigType()
{ {
var coreType = AppHandler.Instance.GetCoreType(node, node.ConfigType); if (Node.ConfigType == EConfigType.Custom)
var itemSocks = await ConfigHandler.GetPreSocksItem(_config, node, coreType);
if (itemSocks != null)
{ {
var preCoreType = itemSocks.CoreType ?? ECoreType.sing_box; SplitCore = false;
var fileName = Utils.GetBinConfigPath(Global.CorePreConfigFileName); CoreType = Node.CoreType ?? ECoreType.Xray;
var result = await CoreConfigHandler.GenerateClientConfig(itemSocks, fileName); if (Node.PreSocksPort > 0)
if (result.Success)
{ {
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(preCoreType); PreCoreType = EnableTun ? ECoreType.sing_box : AppHandler.Instance.GetCoreType(Node, Node.ConfigType);
var proc = await RunProcess(coreInfo, Global.CorePreConfigFileName, true, true); PreSocksPort = Node.PreSocksPort.Value;
if (proc is null) }
{ else
return; {
} EnableTun = false;
_processPre = proc; PreCoreType = null;
} }
} }
} }
/// <summary>
/// Adjust split core configuration
/// </summary>
public void AdjustForSplitCore()
{
if (SplitCore)
{
PreCoreType = EnableTun ? ECoreType.sing_box : SplitRouteCore;
CoreType = PureEndpointCore;
if (PreCoreType == CoreType)
{
PreCoreType = null;
SplitCore = false;
}
else
{
PreSocksPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.split);
}
}
}
}
private async Task<bool> CoreStart(CoreLaunchContext context)
{
var fileName = Utils.GetBinConfigPath(Global.CoreConfigFileName);
var result = context.SplitCore
? await CoreConfigHandler.GeneratePureEndpointConfig(context.Node, fileName)
: await CoreConfigHandler.GenerateClientConfig(context.Node, fileName);
if (result.Success != true)
{
UpdateFunc(true, result.Msg);
return false;
}
UpdateFunc(false, $"{context.Node.GetSummary()}");
UpdateFunc(false, $"{Utils.GetRuntimeInfo()}");
UpdateFunc(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
await CoreStop();
await Task.Delay(100);
if (Utils.IsWindows() && _config.TunModeItem.EnableTun)
{
await Task.Delay(100);
await WindowsUtils.RemoveTunDevice();
}
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(context.CoreType);
var displayLog = context.Node.ConfigType != EConfigType.Custom || context.Node.DisplayLog;
var proc = await RunProcess(coreInfo, Global.CoreConfigFileName, displayLog, true);
if (proc is null)
{
UpdateFunc(true, ResUI.FailedToRunCore);
return false;
}
_process = proc;
_config.RunningCoreType = AppHandler.Instance.GetCoreType(context.Node, context.Node.ConfigType);
return true;
}
private async Task<bool> CoreStartPreService(CoreLaunchContext context)
{
if (context.PreCoreType == null)
{
return true; // No pre-core needed, consider successful
}
var fileName = Utils.GetBinConfigPath(Global.CorePreConfigFileName);
var itemSocks = new ProfileItem()
{
CoreType = context.PreCoreType,
ConfigType = EConfigType.SOCKS,
Address = Global.Loopback,
Sni = context.EnableTun && Utils.IsDomain(context.Node.Address) ? context.Node.Address : string.Empty, //Tun2SocksAddress
Port = context.PreSocksPort
};
var result = await CoreConfigHandler.GenerateClientConfig(itemSocks, fileName);
if (!result.Success)
{
UpdateFunc(true, result.Msg);
return false;
}
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo((ECoreType)context.PreCoreType);
var proc = await RunProcess(coreInfo, Global.CorePreConfigFileName, true, true);
if (proc is null || (_process?.HasExited == true))
{
UpdateFunc(true, ResUI.FailedToRunCore);
return false;
}
_processPre = proc;
return true;
} }
private void UpdateFunc(bool notify, string msg) private void UpdateFunc(bool notify, string msg)