Fix repository

This commit is contained in:
AmazingDM
2022-03-22 14:20:23 +08:00
parent 17b9640c95
commit b53d4a6d28
340 changed files with 142377 additions and 3241 deletions

View File

@@ -1,92 +1,196 @@
namespace Netch.Controllers
{
public class MainController : Interface.IController
{
/// <summary>
/// 节点控制器
/// </summary>
private Interface.IController NodeController;
/// <summary>
/// 模式控制器
/// </summary>
private Interface.IController ModeController;
public bool Create(Models.Server.Server s, Models.Mode.Mode m)
{
switch (s.Type)
{
case Models.Server.ServerType.Socks:
break;
case Models.Server.ServerType.Shadowsocks:
this.NodeController = new Server.ShadowsocksController();
break;
case Models.Server.ServerType.ShadowsocksR:
this.NodeController = new Server.ShadowsocksRController();
break;
case Models.Server.ServerType.WireGuard:
this.NodeController = new Server.WireGuardController();
break;
case Models.Server.ServerType.Trojan:
this.NodeController = new Server.TrojanController();
break;
case Models.Server.ServerType.VMess:
this.NodeController = new Server.VMessController();
break;
case Models.Server.ServerType.VLess:
this.NodeController = new Server.VLessController();
break;
default:
Global.Logger.Error($"未知的节点类型:{s.Type}");
return false;
}
{
var status = this.NodeController?.Create(s, m);
if (status.HasValue && !status.Value)
{
return false;
}
}
switch (m.Type)
{
case Models.Mode.ModeType.ProcessMode:
this.ModeController = new Mode.ProcessController();
break;
case Models.Mode.ModeType.ShareMode:
this.ModeController = new Mode.ShareController();
break;
case Models.Mode.ModeType.TunMode:
this.ModeController = new Mode.TunController();
break;
case Models.Mode.ModeType.WebMode:
this.ModeController = new Mode.WebController();
break;
default:
Global.Logger.Error($"未知的模式类型:{s.Type}");
return false;
}
{
var status = this.ModeController?.Create(s, m);
if (status.HasValue && !status.Value)
{
return false;
}
}
return true;
}
public bool Delete()
{
this.NodeController?.Delete();
this.ModeController?.Delete();
return true;
}
}
}
using System.Diagnostics;
using Microsoft.VisualStudio.Threading;
using Netch.Interfaces;
using Netch.Models;
using Netch.Models.Modes;
using Netch.Servers;
using Netch.Services;
using Netch.Utils;
namespace Netch.Controllers;
public static class MainController
{
public static Socks5Server? Socks5Server { get; private set; }
public static Server? Server { get; private set; }
public static Mode? Mode { get; private set; }
public static IServerController? ServerController { get; private set; }
public static IModeController? ModeController { get; private set; }
private static readonly AsyncSemaphore Lock = new(1);
public static async Task StartAsync(Server server, Mode mode)
{
using var releaser = await Lock.EnterAsync();
Log.Information("Start MainController: {Server} {Mode}", $"{server.Type}", $"[{(int)mode.Type}]{mode.i18NRemark}");
if (await DnsUtils.LookupAsync(server.Hostname) == null)
throw new MessageException(i18N.Translate("Lookup Server hostname failed"));
// TODO Disable NAT Type Test setting
// cache STUN Server ip to prevent "Wrong STUN Server"
DnsUtils.LookupAsync(Global.Settings.STUN_Server).Forget();
Server = server;
Mode = mode;
await Task.WhenAll(Task.Run(NativeMethods.RefreshDNSCache), Task.Run(Firewall.AddNetchFwRules));
try
{
ModeController = ModeService.GetModeControllerByType(mode.Type, out var modePort, out var portName);
if (modePort != null)
TryReleaseTcpPort((ushort)modePort, portName);
if (Server is Socks5Server socks5 && (!socks5.Auth() || ModeController.Features.HasFlag(ModeFeature.SupportSocks5Auth)))
{
Socks5Server = socks5;
}
else
{
// Start Server Controller to get a local socks5 server
Log.Debug("Server Information: {Data}", $"{server.Type} {server.MaskedData()}");
ServerController = ServerHelper.GetUtilByTypeName(server.Type).GetController();
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ServerController.Name));
TryReleaseTcpPort(ServerController.Socks5LocalPort(), "Socks5");
Socks5Server = await ServerController.StartAsync(server);
StatusPortInfoText.Socks5Port = Socks5Server.Port;
StatusPortInfoText.UpdateShareLan();
}
// Start Mode Controller
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ModeController.Name));
await ModeController.StartAsync(Socks5Server, mode);
}
catch (Exception e)
{
releaser.Dispose();
await StopAsync();
switch (e)
{
case DllNotFoundException:
case FileNotFoundException:
throw new Exception(e.Message + "\n\n" + i18N.Translate("Missing File or runtime components"));
case MessageException:
throw;
default:
Log.Error(e, "Unhandled Exception When Start MainController");
Utils.Utils.Open(Constants.LogFile);
throw new MessageException($"{i18N.Translate("Unhandled Exception")}\n{e.Message}");
}
}
}
public static async Task StopAsync()
{
if (Lock.CurrentCount == 0)
{
(await Lock.EnterAsync()).Dispose();
if (ServerController == null && ModeController == null)
// stopped
return;
// else begin stop
}
using var _ = await Lock.EnterAsync();
if (ServerController == null && ModeController == null)
return;
Log.Information("Stop Main Controller");
StatusPortInfoText.Reset();
var tasks = new[]
{
ServerController?.StopAsync() ?? Task.CompletedTask,
ModeController?.StopAsync() ?? Task.CompletedTask
};
try
{
await Task.WhenAll(tasks);
}
catch (Exception e)
{
Log.Error(e, "MainController Stop Error");
}
ServerController = null;
ModeController = null;
}
public static void PortCheck(ushort port, string portName, PortType portType = PortType.Both)
{
try
{
PortHelper.CheckPort(port, portType);
}
catch (PortInUseException)
{
throw new MessageException(i18N.TranslateFormat("The {0} port is in use.", $"{portName} ({port})"));
}
catch (PortReservedException)
{
throw new MessageException(i18N.TranslateFormat("The {0} port is reserved by system.", $"{portName} ({port})"));
}
}
public static void TryReleaseTcpPort(ushort port, string portName)
{
foreach (var p in PortHelper.GetProcessByUsedTcpPort(port))
{
var fileName = p.MainModule?.FileName;
if (fileName == null)
continue;
if (fileName.StartsWith(Global.NetchDir))
{
p.Kill();
p.WaitForExit();
}
else
{
throw new MessageException(i18N.TranslateFormat("The {0} port is used by {1}.", $"{portName} ({port})", $"({p.Id}){fileName}"));
}
}
PortCheck(port, portName, PortType.TCP);
}
public static Task<NatTypeTestResult> DiscoveryNatTypeAsync(CancellationToken ctx = default)
{
Debug.Assert(Socks5Server != null, nameof(Socks5Server) + " != null");
return Socks5ServerTestUtils.DiscoveryNatTypeAsync(Socks5Server, ctx);
}
public static Task<int?> HttpConnectAsync(CancellationToken ctx = default)
{
Debug.Assert(Socks5Server != null, nameof(Socks5Server) + " != null");
try
{
return Socks5ServerTestUtils.HttpConnectAsync(Socks5Server, ctx);
}
catch (OperationCanceledException)
{
// ignored
}
catch (Exception e)
{
Log.Warning(e, "Unhandled Socks5ServerTestUtils.HttpConnectAsync Exception");
}
return Task.FromResult<int?>(null);
}
}