feat: 看起来效果不错.

This commit is contained in:
2025-01-11 02:35:39 +08:00
parent 66a0a2de08
commit 9ed913b15d
6 changed files with 372 additions and 87 deletions
+109 -16
View File
@@ -15,6 +15,7 @@ namespace Proxd_man;
public class XrayCoreManager(
ILogger<XrayCoreManager> logger,
ILoggerFactory loggerFactory,
IOptionsMonitor<ProxdConfig> config)
{
private const string XrayLatestReleaseApiUrl = "https://api.github.com/repos/XTLS/Xray-core/releases/latest";
@@ -25,8 +26,6 @@ public class XrayCoreManager(
private string CoreProgramDir => config.CurrentValue.XrayCoreProgramDirectory;
private string WorkingDirectory => config.CurrentValue.XrayCoreWorkingDirectory;
// TODO: 看看注册订阅更新事件后, 需要进行哪些操作.
public string GetXrayCoreProgramPath()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
@@ -107,7 +106,7 @@ public class XrayCoreManager(
return $"{XrayLatestReleaseAssetDownloadUrlPrefix}Xray-{os}-{arch}.zip";
}
private Process CreateXrayCoreProcess(string args, bool redirectOutput = true)
private Process CreateXrayCoreProcess(List<string> args, bool redirectOutput = true, bool redirectError = true)
{
var programPath = GetXrayCoreProgramPath();
if (!File.Exists(programPath))
@@ -122,11 +121,10 @@ public class XrayCoreManager(
return new Process
{
StartInfo = new ProcessStartInfo
StartInfo = new ProcessStartInfo(programPath, args)
{
FileName = programPath,
Arguments = args,
RedirectStandardOutput = redirectOutput,
RedirectStandardError = redirectError,
UseShellExecute = false,
CreateNoWindow = true,
WorkingDirectory = WorkingDirectory
@@ -147,7 +145,7 @@ public class XrayCoreManager(
return null;
}
var process = CreateXrayCoreProcess("--version");
var process = CreateXrayCoreProcess(["--version"]);
process.Start();
await process.WaitForExitAsync();
var output = (await process.StandardOutput.ReadToEndAsync()).Trim();
@@ -284,9 +282,11 @@ public class XrayCoreManager(
public async Task<bool> VerifyXrayCoreConfigFile(string configFilePath)
{
var process = CreateXrayCoreProcess($"run -test -config {configFilePath}");
var process = CreateXrayCoreProcess(["run", "-test", "-c", configFilePath]);
process.Start();
RedirectXrayCoreProcessOutput(process);
await process.WaitForExitAsync();
return process.ExitCode == 0;
}
@@ -427,7 +427,7 @@ public class XrayCoreManager(
// ------------ Outbound 配置 ------------
// ------------ Routing 配置 -------------
var routingSettings = new JsonObject
{
{ "domainStrategy", "AsIs" }
@@ -472,7 +472,7 @@ public class XrayCoreManager(
return proxyConfig;
}
public Process CreateOutboundTestProcess(ushort inboundHttpPort, BaseOutboundSetting outboundSetting)
public async Task<Process> CreateOutboundTestProcess(ushort inboundHttpPort, BaseOutboundSetting outboundSetting)
{
var configJson = GenerateXrayCoreConfigJson([
new HttpInboundSetting
@@ -481,12 +481,105 @@ public class XrayCoreManager(
}
], outboundSetting, true);
var configFilePath = Path.Combine(Path.Combine(WorkingDirectory, "test-config"), Path.GetRandomFileName() + ".json");
using var configFileStream = File.CreateText(configFilePath);
configFileStream.Write(JsonSerializer.Serialize(configJson));
return CreateXrayCoreProcess($"run -config {configFilePath}");
var testingConfigDir = Path.Combine(WorkingDirectory, "test-config");
if (!Directory.Exists(testingConfigDir))
{
Directory.CreateDirectory(testingConfigDir);
}
var configFilePath = Path.GetFullPath(Path.Combine(testingConfigDir, Path.GetRandomFileName() + ".json"));
await using (var configFileStream = File.CreateText(configFilePath))
{
await configFileStream.WriteAsync(JsonSerializer.Serialize(configJson));
}
if (!await VerifyXrayCoreConfigFile(configFilePath))
{
throw new Exception($"测试配置验证失败: {configFilePath}");
}
logger.LogDebug("Xray-Core 测试配置文件: {configFilePath}", configFilePath);
var xrayCoreProcess = CreateXrayCoreProcess(["run", "-c", configFilePath], true, true);
xrayCoreProcess.Exited += (_, _) => File.Delete(configFilePath);
return xrayCoreProcess;
}
public Process? MainXrayCoreProcess { get; private set; }
public BaseOutboundSetting? CurrentOutboundSetting { get; private set; }
public delegate void MainXrayCoreProcessExitedHandler();
public event MainXrayCoreProcessExitedHandler? MainXrayCoreProcessExited;
public delegate void MainXrayCoreProcessStartedHandler();
public event MainXrayCoreProcessStartedHandler? MainXrayCoreProcessStarted;
public async Task StartMainXrayCoreProcess(BaseOutboundSetting outboundSetting, bool noStart = false)
{
if (MainXrayCoreProcess != null)
{
await StopMainXrayCoreProcess();
}
logger.LogInformation("正在启动主要 Xray-Core 进程...");
var configJson = GenerateXrayCoreConfigJson(config.CurrentValue.Inbounds.ToInboundSettings(), outboundSetting);
var configFilePath = Path.GetFullPath(Path.Combine(WorkingDirectory, "main-config.json"));
await File.WriteAllTextAsync(configFilePath, JsonSerializer.Serialize(configJson));
logger.LogDebug("配置文件已写入: {configPath}", configFilePath);
var process = CreateXrayCoreProcess(["run", "-c", configFilePath]);
process.Exited += async (_, _) =>
{
MainXrayCoreProcessExited?.Invoke();
await StopMainXrayCoreProcess();
};
process.Start();
RedirectXrayCoreProcessOutput(process);
logger.LogInformation("主要 Xray-Core 进程已启动.");
MainXrayCoreProcessStarted?.Invoke();
MainXrayCoreProcess = process;
CurrentOutboundSetting = outboundSetting;
}
public async Task StopMainXrayCoreProcess()
{
if (MainXrayCoreProcess == null)
{
return;
}
if (!MainXrayCoreProcess.HasExited)
{
MainXrayCoreProcess.Kill();
await MainXrayCoreProcess.WaitForExitAsync();
}
MainXrayCoreProcess = null;
CurrentOutboundSetting = null;
}
public void RedirectXrayCoreProcessOutput(Process process)
{
var processLogger = loggerFactory.CreateLogger($"Xray-Core.Process[{process.Id}]");
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.OutputDataReceived += (sender, e) =>
{
if (!string.IsNullOrEmpty(e.Data))
{
processLogger.LogInformation("{content}", e.Data);
}
};
process.ErrorDataReceived += (sender, e) =>
{
if (!string.IsNullOrEmpty(e.Data))
{
processLogger.LogError("{content}", e.Data);
}
};
}
}