feat: 看起来效果不错.
This commit is contained in:
+109
-16
@@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user