mirror of
https://github.com/netchx/netch.git
synced 2026-03-20 18:19:44 +08:00
Refactor Guard.cs
This commit is contained in:
@@ -1,6 +1,3 @@
|
||||
using Netch.Models;
|
||||
using Netch.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
@@ -9,83 +6,157 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Netch.Models;
|
||||
using Netch.Utils;
|
||||
using Serilog;
|
||||
using Timer = System.Timers.Timer;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
public abstract class Guard
|
||||
{
|
||||
private readonly Timer _flushFileStreamTimer = new(300) { AutoReset = true };
|
||||
|
||||
private FileStream? _logFileStream;
|
||||
|
||||
private StreamWriter? _logStreamWriter;
|
||||
private bool _redirectToFile = true;
|
||||
|
||||
/// <summary>
|
||||
/// 日志文件(重定向输出文件)
|
||||
/// </summary>
|
||||
/// <param name="mainFile">application path relative of Netch\bin</param>
|
||||
/// <param name="redirectOutput"></param>
|
||||
/// <param name="encoding">application output encode</param>
|
||||
protected Guard(string mainFile, bool redirectOutput = true, Encoding? encoding = null)
|
||||
{
|
||||
RedirectOutput = redirectOutput;
|
||||
|
||||
var fileName = Path.GetFullPath($"bin\\{mainFile}");
|
||||
|
||||
if (!File.Exists(fileName))
|
||||
throw new MessageException(i18N.Translate($"bin\\{mainFile} file not found!"));
|
||||
|
||||
Instance = new Process
|
||||
{
|
||||
StartInfo =
|
||||
{
|
||||
FileName = fileName,
|
||||
WorkingDirectory = $"{Global.NetchDir}\\bin",
|
||||
CreateNoWindow = true,
|
||||
UseShellExecute = !RedirectOutput,
|
||||
RedirectStandardOutput = RedirectOutput,
|
||||
StandardOutputEncoding = RedirectOutput ? encoding : null,
|
||||
RedirectStandardError = RedirectOutput,
|
||||
StandardErrorEncoding = RedirectOutput ? encoding : null,
|
||||
WindowStyle = ProcessWindowStyle.Hidden
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected string LogPath => Path.Combine(Global.NetchDir, $"logging\\{Name}.log");
|
||||
|
||||
/// <summary>
|
||||
/// 成功启动关键词
|
||||
/// </summary>
|
||||
protected virtual IEnumerable<string> StartedKeywords { get; set; } = new List<string>();
|
||||
protected virtual IEnumerable<string> StartedKeywords { get; } = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// 启动失败关键词
|
||||
/// </summary>
|
||||
protected virtual IEnumerable<string> StoppedKeywords { get; set; } = new List<string>();
|
||||
protected virtual IEnumerable<string> FailedKeywords { get; } = new List<string>();
|
||||
|
||||
public abstract string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 主程序名
|
||||
/// </summary>
|
||||
public abstract string MainFile { get; protected set; }
|
||||
private State State { get; set; } = State.Waiting;
|
||||
|
||||
protected State State { get; set; } = State.Waiting;
|
||||
private bool RedirectOutput { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 进程是否可以重定向输出
|
||||
/// </summary>
|
||||
protected bool RedirectStd { get; set; } = true;
|
||||
public Process Instance { get; }
|
||||
|
||||
protected bool RedirectToFile
|
||||
~Guard()
|
||||
{
|
||||
get => RedirectStd && _redirectToFile;
|
||||
set => _redirectToFile = value;
|
||||
_logFileStream?.Dispose();
|
||||
_logStreamWriter?.Dispose();
|
||||
Instance.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 进程实例
|
||||
/// </summary>
|
||||
public Process? Instance { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 程序输出的编码,
|
||||
/// </summary>
|
||||
protected virtual Encoding? InstanceOutputEncoding { get; } = null;
|
||||
|
||||
public abstract void Stop();
|
||||
|
||||
/// <summary>
|
||||
/// 停止进程
|
||||
/// </summary>
|
||||
protected void StopInstance()
|
||||
protected void StartGuard(string argument, ProcessPriorityClass priority = ProcessPriorityClass.Normal)
|
||||
{
|
||||
State = State.Starting;
|
||||
|
||||
_logFileStream = File.Open(LogPath, FileMode.Create, FileAccess.ReadWrite, FileShare.Read);
|
||||
_logStreamWriter = new StreamWriter(_logFileStream) { AutoFlush = true };
|
||||
|
||||
Instance.StartInfo.Arguments = argument;
|
||||
Instance.Start();
|
||||
|
||||
if (priority != ProcessPriorityClass.Normal)
|
||||
Instance.PriorityClass = priority;
|
||||
|
||||
if (RedirectOutput)
|
||||
{
|
||||
Task.Run(() => ReadOutput(Instance.StandardOutput));
|
||||
Task.Run(() => ReadOutput(Instance.StandardError));
|
||||
|
||||
if (!StartedKeywords.Any())
|
||||
{
|
||||
// Skip, No started keyword
|
||||
State = State.Started;
|
||||
return;
|
||||
}
|
||||
|
||||
// wait ReadOutput change State
|
||||
for (var i = 0; i < 1000; i++)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
switch (State)
|
||||
{
|
||||
case State.Started:
|
||||
OnStarted();
|
||||
return;
|
||||
case State.Stopped:
|
||||
StopGuard();
|
||||
OnStartFailed();
|
||||
throw new MessageException($"{Name} 控制器启动失败");
|
||||
}
|
||||
}
|
||||
|
||||
StopGuard();
|
||||
throw new MessageException($"{Name} 控制器启动超时");
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadOutput(TextReader reader)
|
||||
{
|
||||
string? line;
|
||||
while ((line = reader.ReadLine()) != null)
|
||||
{
|
||||
_logStreamWriter!.WriteLine(line);
|
||||
OnReadNewLine(line);
|
||||
|
||||
if (State == State.Starting)
|
||||
{
|
||||
if (StartedKeywords.Any(s => line.Contains(s)))
|
||||
State = State.Started;
|
||||
else if (FailedKeywords.Any(s => line.Contains(s)))
|
||||
{
|
||||
OnStartFailed();
|
||||
State = State.Stopped;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
State = State.Stopped;
|
||||
}
|
||||
|
||||
public virtual void Stop()
|
||||
{
|
||||
StopGuard();
|
||||
}
|
||||
|
||||
protected void StopGuard()
|
||||
{
|
||||
_logStreamWriter?.Close();
|
||||
_logFileStream?.Close();
|
||||
|
||||
try
|
||||
{
|
||||
if (Instance == null || Instance.HasExited)
|
||||
return;
|
||||
|
||||
Instance.Kill();
|
||||
Instance.WaitForExit();
|
||||
if (Instance is { HasExited: false })
|
||||
{
|
||||
Instance.Kill();
|
||||
Instance.WaitForExit();
|
||||
}
|
||||
}
|
||||
catch (Win32Exception e)
|
||||
{
|
||||
Log.Error(e, "停止 {MainFile} 异常", MainFile);
|
||||
Log.Error(e, "停止 {Name} 异常", Instance.ProcessName);
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -93,191 +164,17 @@ namespace Netch.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 仅初始化 <see cref="Instance" />,不设定事件处理方法
|
||||
/// </summary>
|
||||
/// <param name="argument"></param>
|
||||
protected virtual void InitInstance(string argument)
|
||||
protected virtual void OnStarted()
|
||||
{
|
||||
Instance = new Process
|
||||
{
|
||||
StartInfo =
|
||||
{
|
||||
FileName = Path.GetFullPath($"bin\\{MainFile}"),
|
||||
WorkingDirectory = $"{Global.NetchDir}\\bin",
|
||||
Arguments = argument,
|
||||
CreateNoWindow = true,
|
||||
UseShellExecute = !RedirectStd,
|
||||
RedirectStandardOutput = RedirectStd,
|
||||
StandardOutputEncoding = RedirectStd ? InstanceOutputEncoding : null,
|
||||
RedirectStandardError = RedirectStd,
|
||||
StandardErrorEncoding = RedirectStd ? InstanceOutputEncoding : null,
|
||||
WindowStyle = ProcessWindowStyle.Hidden
|
||||
}
|
||||
};
|
||||
|
||||
if (!File.Exists(Instance.StartInfo.FileName))
|
||||
throw new MessageException(i18N.Translate($"bin\\{MainFile} file not found!"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 默认行为启动主程序
|
||||
/// </summary>
|
||||
/// <param name="argument">主程序启动参数</param>
|
||||
/// <param name="priority">进程优先级</param>
|
||||
/// <returns>是否成功启动</returns>
|
||||
protected void StartInstanceAuto(string argument, ProcessPriorityClass priority = ProcessPriorityClass.Normal)
|
||||
{
|
||||
State = State.Starting;
|
||||
// 初始化程序
|
||||
InitInstance(argument);
|
||||
|
||||
if (RedirectToFile)
|
||||
OpenLogFile();
|
||||
|
||||
// 启动程序
|
||||
Instance!.Start();
|
||||
if (priority != ProcessPriorityClass.Normal)
|
||||
Instance.PriorityClass = priority;
|
||||
|
||||
if (RedirectStd)
|
||||
{
|
||||
Task.Run(() => ReadOutput(Instance.StandardOutput));
|
||||
Task.Run(() => ReadOutput(Instance.StandardError));
|
||||
|
||||
if (!StartedKeywords.Any())
|
||||
{
|
||||
State = State.Started;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 等待启动
|
||||
for (var i = 0; i < 1000; i++)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
switch (State)
|
||||
{
|
||||
case State.Started:
|
||||
Task.Run(OnKeywordStarted);
|
||||
return;
|
||||
case State.Stopped:
|
||||
Stop();
|
||||
CloseLogFile();
|
||||
OnKeywordStopped();
|
||||
throw new MessageException($"{Name} 控制器启动失败");
|
||||
}
|
||||
}
|
||||
|
||||
Stop();
|
||||
OnKeywordTimeout();
|
||||
throw new MessageException($"{Name} 控制器启动超时");
|
||||
}
|
||||
|
||||
#region FileStream
|
||||
|
||||
private void OpenLogFile()
|
||||
{
|
||||
if (!RedirectToFile)
|
||||
return;
|
||||
|
||||
_logFileStream = File.Open(LogPath, FileMode.Create, FileAccess.ReadWrite, FileShare.Read);
|
||||
_logStreamWriter = new StreamWriter(_logFileStream);
|
||||
|
||||
_flushFileStreamTimer.Elapsed += FlushFileStreamTimerEvent;
|
||||
_flushFileStreamTimer.Enabled = true;
|
||||
}
|
||||
|
||||
private void WriteLog(string line)
|
||||
{
|
||||
if (!RedirectToFile)
|
||||
return;
|
||||
|
||||
_logStreamWriter!.WriteLine(line);
|
||||
}
|
||||
|
||||
private readonly object _logStreamLock = new();
|
||||
private void CloseLogFile()
|
||||
{
|
||||
if (!RedirectToFile)
|
||||
return;
|
||||
|
||||
lock (_logStreamLock)
|
||||
{
|
||||
if (_logFileStream == null)
|
||||
return;
|
||||
|
||||
_flushFileStreamTimer.Enabled = false;
|
||||
_logStreamWriter?.Close();
|
||||
_logFileStream?.Close();
|
||||
_logStreamWriter = _logStreamWriter = null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region virtual
|
||||
|
||||
protected virtual void OnReadNewLine(string line)
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void OnKeywordStarted()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void OnKeywordStopped()
|
||||
protected virtual void OnStartFailed()
|
||||
{
|
||||
Utils.Utils.Open(LogPath);
|
||||
}
|
||||
|
||||
protected virtual void OnKeywordTimeout()
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected void ReadOutput(TextReader reader)
|
||||
{
|
||||
string? line;
|
||||
while ((line = reader.ReadLine()) != null)
|
||||
{
|
||||
WriteLog(line);
|
||||
OnReadNewLine(line);
|
||||
|
||||
// State == State.Started if !StartedKeywords.Any()
|
||||
if (State == State.Starting)
|
||||
{
|
||||
if (StartedKeywords.Any(s => line.Contains(s)))
|
||||
State = State.Started;
|
||||
else if (StoppedKeywords.Any(s => line.Contains(s)))
|
||||
State = State.Stopped;
|
||||
}
|
||||
}
|
||||
|
||||
CloseLogFile();
|
||||
State = State.Stopped;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计时器存储日志
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void FlushFileStreamTimerEvent(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logStreamWriter!.Flush();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warning(ex, "写入 {Name} 日志异常", Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,15 +10,12 @@ namespace Netch.Controllers
|
||||
{
|
||||
public class NTTController : Guard, IController
|
||||
{
|
||||
public override string MainFile { get; protected set; } = "NTT.exe";
|
||||
|
||||
public override string Name { get; } = "NTT";
|
||||
|
||||
public override void Stop()
|
||||
public NTTController() : base("NTT.exe")
|
||||
{
|
||||
StopInstance();
|
||||
}
|
||||
|
||||
public override string Name => "NTT";
|
||||
|
||||
/// <summary>
|
||||
/// 启动 NatTypeTester
|
||||
/// </summary>
|
||||
@@ -29,8 +26,8 @@ namespace Netch.Controllers
|
||||
|
||||
try
|
||||
{
|
||||
InitInstance($" {Global.Settings.STUN_Server} {Global.Settings.STUN_Server_Port}");
|
||||
Instance!.Start();
|
||||
Instance.StartInfo.Arguments = $" {Global.Settings.STUN_Server} {Global.Settings.STUN_Server_Port}";
|
||||
Instance.Start();
|
||||
|
||||
var output = await Instance.StandardOutput.ReadToEndAsync();
|
||||
var error = await Instance.StandardError.ReadToEndAsync();
|
||||
@@ -47,8 +44,7 @@ namespace Netch.Controllers
|
||||
if (output.IsNullOrWhiteSpace())
|
||||
if (!error.IsNullOrWhiteSpace())
|
||||
{
|
||||
error = error.Trim();
|
||||
var errorFirst = error.Substring(0, error.IndexOf('\n')).Trim();
|
||||
var errorFirst = error.GetLines().First();
|
||||
return (errorFirst.SplitTrimEntries(':').Last(), null, null);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,23 +15,27 @@ namespace Netch.Controllers
|
||||
{
|
||||
public class PcapController : Guard, IModeController
|
||||
{
|
||||
public override string Name { get; } = "pcap2socks";
|
||||
public PcapController() : base("pcap2socks.exe", encoding: Encoding.UTF8)
|
||||
{
|
||||
_form = new LogForm(Global.MainForm);
|
||||
_form.CreateControl();
|
||||
}
|
||||
|
||||
public override string MainFile { get; protected set; } = "pcap2socks.exe";
|
||||
~PcapController()
|
||||
{
|
||||
_form.Dispose();
|
||||
}
|
||||
|
||||
protected override IEnumerable<string> StartedKeywords { get; set; } = new[] { "└" };
|
||||
public override string Name => "pcap2socks";
|
||||
|
||||
protected override Encoding? InstanceOutputEncoding { get; } = Encoding.UTF8;
|
||||
protected override IEnumerable<string> StartedKeywords { get; } = new[] { "└" };
|
||||
|
||||
private LogForm? _form;
|
||||
private readonly LogForm _form;
|
||||
|
||||
public void Start(in Mode mode)
|
||||
{
|
||||
var server = MainController.Server!;
|
||||
|
||||
_form = new LogForm(Global.MainForm);
|
||||
_form.CreateControl();
|
||||
|
||||
var outboundNetworkInterface = NetworkInterfaceUtils.GetBest();
|
||||
|
||||
var argument = new StringBuilder($@"-i \Device\NPF_{outboundNetworkInterface.Id}");
|
||||
@@ -41,26 +45,22 @@ namespace Netch.Controllers
|
||||
argument.Append($" --destination 127.0.0.1:{Global.Settings.Socks5LocalPort}");
|
||||
|
||||
argument.Append($" {mode.GetRules().FirstOrDefault() ?? "-P n"}");
|
||||
StartInstanceAuto(argument.ToString());
|
||||
StartGuard(argument.ToString());
|
||||
}
|
||||
|
||||
protected override void OnReadNewLine(string line)
|
||||
{
|
||||
Global.MainForm.BeginInvoke(new Action(() =>
|
||||
{
|
||||
if (!_form!.IsDisposed)
|
||||
_form.richTextBox1.AppendText(line + "\n");
|
||||
}));
|
||||
Global.MainForm.BeginInvoke(new Action(() => _form.richTextBox1.AppendText(line + "\n")));
|
||||
}
|
||||
|
||||
protected override void OnKeywordStarted()
|
||||
protected override void OnStarted()
|
||||
{
|
||||
Global.MainForm.BeginInvoke(new Action(() => { _form!.Show(); }));
|
||||
Global.MainForm.BeginInvoke(new Action(() => _form.Show()));
|
||||
}
|
||||
|
||||
protected override void OnKeywordStopped()
|
||||
protected override void OnStartFailed()
|
||||
{
|
||||
if (File.ReadAllText(LogPath).Length == 0)
|
||||
if (new FileInfo(LogPath).Length == 0)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
@@ -76,8 +76,8 @@ namespace Netch.Controllers
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
_form!.Close();
|
||||
StopInstance();
|
||||
_form.Close();
|
||||
StopGuard();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,14 +2,8 @@
|
||||
{
|
||||
public interface IController
|
||||
{
|
||||
/// <summary>
|
||||
/// 控制器名
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 停止
|
||||
/// </summary>
|
||||
public void Stop();
|
||||
}
|
||||
}
|
||||
@@ -4,11 +4,6 @@ namespace Netch.Interfaces
|
||||
{
|
||||
public interface IModeController : IController
|
||||
{
|
||||
/// <summary>
|
||||
/// 启动
|
||||
/// </summary>
|
||||
/// <param name="mode">模式</param>
|
||||
/// <returns>是否成功</returns>
|
||||
public abstract void Start(in Mode mode);
|
||||
public void Start(in Mode mode);
|
||||
}
|
||||
}
|
||||
@@ -7,13 +7,15 @@ namespace Netch.Servers.Shadowsocks
|
||||
{
|
||||
public class SSController : Guard, IServerController
|
||||
{
|
||||
public override string MainFile { get; protected set; } = "Shadowsocks.exe";
|
||||
public SSController() : base("Shadowsocks.exe")
|
||||
{
|
||||
}
|
||||
|
||||
protected override IEnumerable<string> StartedKeywords { get; set; } = new[] { "listening at" };
|
||||
protected override IEnumerable<string> StartedKeywords => new[] { "listening at" };
|
||||
|
||||
protected override IEnumerable<string> StoppedKeywords { get; set; } = new[] { "Invalid config path", "usage", "plugin service exit unexpectedly" };
|
||||
protected override IEnumerable<string> FailedKeywords => new[] { "Invalid config path", "usage", "plugin service exit unexpectedly" };
|
||||
|
||||
public override string Name { get; } = "Shadowsocks";
|
||||
public override string Name => "Shadowsocks";
|
||||
|
||||
public ushort? Socks5LocalPort { get; set; }
|
||||
|
||||
@@ -36,7 +38,7 @@ namespace Netch.Servers.Shadowsocks
|
||||
plugin_opts = server.PluginOption
|
||||
};
|
||||
|
||||
StartInstanceAuto(command.ToString());
|
||||
StartGuard(command.ToString());
|
||||
}
|
||||
|
||||
[Verb]
|
||||
@@ -70,10 +72,5 @@ namespace Netch.Servers.Shadowsocks
|
||||
[Optional]
|
||||
public string? acl { get; set; }
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
StopInstance();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,13 +7,15 @@ namespace Netch.Servers.ShadowsocksR
|
||||
{
|
||||
public class SSRController : Guard, IServerController
|
||||
{
|
||||
public override string MainFile { get; protected set; } = "ShadowsocksR.exe";
|
||||
public SSRController() : base("ShadowsocksR.exe")
|
||||
{
|
||||
}
|
||||
|
||||
protected override IEnumerable<string> StartedKeywords { get; set; } = new[] { "listening at" };
|
||||
protected override IEnumerable<string> StartedKeywords => new[] { "listening at" };
|
||||
|
||||
protected override IEnumerable<string> StoppedKeywords { get; set; } = new[] { "Invalid config path", "usage" };
|
||||
protected override IEnumerable<string> FailedKeywords => new[] { "Invalid config path", "usage" };
|
||||
|
||||
public override string Name { get; } = "ShadowsocksR";
|
||||
public override string Name => "ShadowsocksR";
|
||||
|
||||
public ushort? Socks5LocalPort { get; set; }
|
||||
|
||||
@@ -39,7 +41,7 @@ namespace Netch.Servers.ShadowsocksR
|
||||
u = true
|
||||
};
|
||||
|
||||
StartInstanceAuto(command.ToString());
|
||||
StartGuard(command.ToString());
|
||||
}
|
||||
|
||||
[Verb]
|
||||
@@ -79,10 +81,5 @@ namespace Netch.Servers.ShadowsocksR
|
||||
[Optional]
|
||||
public string? acl { get; set; }
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
StopInstance();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,13 +10,15 @@ namespace Netch.Servers.Trojan
|
||||
{
|
||||
public class TrojanController : Guard, IServerController
|
||||
{
|
||||
public override string MainFile { get; protected set; } = "Trojan.exe";
|
||||
public TrojanController() : base("Trojan.exe")
|
||||
{
|
||||
}
|
||||
|
||||
protected override IEnumerable<string> StartedKeywords { get; set; } = new[] { "started" };
|
||||
protected override IEnumerable<string> StartedKeywords => new[] { "started" };
|
||||
|
||||
protected override IEnumerable<string> StoppedKeywords { get; set; } = new[] { "exiting" };
|
||||
protected override IEnumerable<string> FailedKeywords => new[] { "exiting" };
|
||||
|
||||
public override string Name { get; } = "Trojan";
|
||||
public override string Name => "Trojan";
|
||||
|
||||
public ushort? Socks5LocalPort { get; set; }
|
||||
|
||||
@@ -45,12 +47,7 @@ namespace Netch.Servers.Trojan
|
||||
|
||||
File.WriteAllBytes(Constants.TempConfig, JsonSerializer.SerializeToUtf8Bytes(trojanConfig, Global.NewDefaultJsonSerializerOptions));
|
||||
|
||||
StartInstanceAuto("-c ..\\data\\last.json");
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
StopInstance();
|
||||
StartGuard("-c ..\\data\\last.json");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,13 +9,17 @@ namespace Netch.Servers.V2ray
|
||||
{
|
||||
public class V2rayController : Guard, IServerController
|
||||
{
|
||||
public override string MainFile { get; protected set; } = "xray.exe";
|
||||
public V2rayController() : base("xray.exe")
|
||||
{
|
||||
if (!Global.Settings.V2RayConfig.XrayCone)
|
||||
Instance.StartInfo.Environment["XRAY_CONE_DISABLED"] = "true";
|
||||
}
|
||||
|
||||
protected override IEnumerable<string> StartedKeywords { get; set; } = new[] { "started" };
|
||||
protected override IEnumerable<string> StartedKeywords => new[] { "started" };
|
||||
|
||||
protected override IEnumerable<string> StoppedKeywords { get; set; } = new[] { "config file not readable", "failed to" };
|
||||
protected override IEnumerable<string> FailedKeywords => new[] { "config file not readable", "failed to" };
|
||||
|
||||
public override string Name { get; } = "Xray";
|
||||
public override string Name => "Xray";
|
||||
|
||||
public ushort? Socks5LocalPort { get; set; }
|
||||
|
||||
@@ -24,19 +28,7 @@ namespace Netch.Servers.V2ray
|
||||
public virtual void Start(in Server s, in Mode mode)
|
||||
{
|
||||
File.WriteAllText(Constants.TempConfig, V2rayConfigUtils.GenerateClientConfig(s, mode));
|
||||
StartInstanceAuto("-config ..\\data\\last.json");
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
StopInstance();
|
||||
}
|
||||
|
||||
protected override void InitInstance(string argument)
|
||||
{
|
||||
base.InitInstance(argument);
|
||||
if (!Global.Settings.V2RayConfig.XrayCone)
|
||||
Instance!.StartInfo.Environment["XRAY_CONE_DISABLED"] = "true";
|
||||
StartGuard("-config ..\\data\\last.json");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
using Microsoft.Diagnostics.Tracing.Parsers;
|
||||
using Microsoft.Diagnostics.Tracing.Session;
|
||||
using Netch.Controllers;
|
||||
using Netch.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Diagnostics.Tracing.Parsers;
|
||||
using Microsoft.Diagnostics.Tracing.Session;
|
||||
using Netch.Controllers;
|
||||
using Netch.Models;
|
||||
using Serilog;
|
||||
|
||||
namespace Netch.Utils
|
||||
@@ -58,9 +58,8 @@ namespace Netch.Utils
|
||||
{
|
||||
case null:
|
||||
break;
|
||||
case Guard instanceController:
|
||||
if (instanceController.Instance != null)
|
||||
instances.Add(instanceController.Instance);
|
||||
case Guard guard:
|
||||
instances.Add(guard.Instance);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -70,18 +69,17 @@ namespace Netch.Utils
|
||||
{
|
||||
case null:
|
||||
break;
|
||||
case NFController _:
|
||||
case NFController:
|
||||
instances.Add(Process.GetCurrentProcess());
|
||||
break;
|
||||
case Guard instanceController:
|
||||
instances.Add(instanceController.Instance!);
|
||||
case Guard guard:
|
||||
instances.Add(guard.Instance);
|
||||
break;
|
||||
}
|
||||
|
||||
var processList = instances.Select(instance => instance.Id).ToList();
|
||||
var processList = instances.Select(instance => instance.Id).ToHashSet();
|
||||
|
||||
Log.Information("流量统计进程: {Processes}",
|
||||
$"{string.Join(",", instances.Select(instance => $"({instance.Id})" + instance.ProcessName).ToArray())}");
|
||||
Log.Information("流量统计进程: {Processes}", string.Join(',', instances.Select(v => $"({v.Id}){v.ProcessName}")));
|
||||
|
||||
received = 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user