增加管理接口秘钥

This commit is contained in:
snltty
2024-04-29 14:18:38 +08:00
parent c6a1712f07
commit df2ed24dfe
195 changed files with 21135 additions and 515 deletions

View File

@@ -0,0 +1,246 @@
using cmonitor.client;
using cmonitor.config;
using cmonitor.plugins.tunnel.compact;
using cmonitor.plugins.tunnel.messenger;
using cmonitor.plugins.tunnel.transport;
using cmonitor.server;
using common.libs;
using MemoryPack;
using Microsoft.Extensions.DependencyInjection;
using System.Net.Sockets;
using System.Reflection;
using System.Transactions;
namespace cmonitor.plugins.tunnel
{
public sealed class TunnelTransfer
{
private List<ITransport> transports;
private readonly Config config;
private readonly ServiceProvider serviceProvider;
private readonly ClientSignInState clientSignInState;
private readonly MessengerSender messengerSender;
private readonly CompactTransfer compactTransfer;
public Action<TunnelTransportState> OnConnected { get; set; } = (state) => { };
public TunnelTransfer(Config config, ServiceProvider serviceProvider, ClientSignInState clientSignInState, MessengerSender messengerSender, CompactTransfer compactTransfer)
{
this.config = config;
this.serviceProvider = serviceProvider;
this.clientSignInState = clientSignInState;
this.messengerSender = messengerSender;
this.compactTransfer = compactTransfer;
}
public void Load(Assembly[] assembs)
{
IEnumerable<Type> types = ReflectionHelper.GetInterfaceSchieves(assembs, typeof(ITransport));
types = config.Data.Common.PluginContains(types);
transports = types.Select(c => (ITransport)serviceProvider.GetService(c)).Where(c => c != null).Where(c => string.IsNullOrWhiteSpace(c.Name) == false).ToList();
foreach (var item in transports)
{
item.OnSendConnectBegin = OnSendConnectBegin;
item.OnSendConnectFail = OnSendConnectFail;
item.OnConnectBegin = OnConnectBegin;
item.OnConnecting = OnConnecting;
item.OnConnected = _OnConnected;
item.OnConnected += OnConnected;
item.OnDisConnected = OnDisConnected;
item.OnConnectFail = OnConnectFail;
}
Logger.Instance.Warning($"load tunnel transport:{string.Join(",", transports.Select(c => c.Name))}");
}
public async Task<TunnelTransportState> ConnectAsync(string remoteMachineName, string transactionId)
{
IEnumerable<ITransport> _transports = transports.OrderBy(c => c.Type);
foreach (ITransport transport in _transports)
{
//获取自己的外网ip
TunnelTransportExternalIPInfo localInfo = await GetLocalInfo(transport.Type);
if (localInfo == null)
{
continue;
}
//获取对方的外网ip
TunnelTransportExternalIPInfo remoteInfo = await GetRemoteInfo(remoteMachineName, transport.Type);
if (remoteInfo == null)
{
continue;
}
TunnelTransportInfo tunnelTransportInfo = new TunnelTransportInfo
{
Direction = TunnelTransportDirection.Forward,
TransactionId = transactionId,
TransportName = transport.Name,
TransportType = transport.Type,
Local = localInfo,
Remote = remoteInfo,
};
TunnelTransportState state = await transport.ConnectAsync(tunnelTransportInfo);
if (state != null)
{
_OnConnected(state);
return state;
}
}
return null;
}
public void OnBegin(TunnelTransportInfo tunnelTransportInfo)
{
ITransport _transports = transports.FirstOrDefault(c => c.Name == tunnelTransportInfo.TransportName && c.Type == tunnelTransportInfo.TransportType);
if (_transports != null)
{
_transports.OnBegin(tunnelTransportInfo);
}
}
public void OnFail(TunnelTransportInfo tunnelTransportInfo)
{
ITransport _transports = transports.FirstOrDefault(c => c.Name == tunnelTransportInfo.TransportName && c.Type == tunnelTransportInfo.TransportType);
if (_transports != null)
{
_transports.OnFail(tunnelTransportInfo);
OnConnectFail(tunnelTransportInfo.FromMachineName);
}
}
public async Task<TunnelTransportExternalIPInfo> Info(TunnelTransportExternalIPRequestInfo request)
{
return await GetLocalInfo(request.TransportType);
}
private async Task<TunnelTransportExternalIPInfo> GetLocalInfo(ProtocolType transportType)
{
TunnelCompactIPEndPoint[] ips = await compactTransfer.GetExternalIPAsync(transportType);
if (ips != null && ips.Length > 0)
{
return new TunnelTransportExternalIPInfo
{
Local = ips[0].Local,
Remote = ips[0].Remote,
RouteLevel = config.Data.Client.Tunnel.RouteLevel,
MachineName = config.Data.Client.Name
};
}
return null;
}
private async Task<TunnelTransportExternalIPInfo> GetRemoteInfo(string remoteMachineName, ProtocolType transportType)
{
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
{
Connection = clientSignInState.Connection,
MessengerId = (ushort)TunnelMessengerIds.InfoForward,
Timeout = 3000,
Payload = MemoryPackSerializer.Serialize(new TunnelTransportExternalIPRequestInfo
{
RemoteMachineName = remoteMachineName,
TransportType = transportType,
})
});
if (resp.Code == MessageResponeCodes.OK && resp.Data.Length > 0)
{
return MemoryPackSerializer.Deserialize<TunnelTransportExternalIPInfo>(resp.Data.Span);
}
return null;
}
private async Task OnSendConnectBegin(TunnelTransportInfo tunnelTransportInfo)
{
await messengerSender.SendReply(new MessageRequestWrap
{
Connection = clientSignInState.Connection,
MessengerId = (ushort)TunnelMessengerIds.BeginForward,
Payload = MemoryPackSerializer.Serialize(tunnelTransportInfo)
});
}
private async Task OnSendConnectFail(TunnelTransportInfo tunnelTransportInfo)
{
await messengerSender.SendReply(new MessageRequestWrap
{
Connection = clientSignInState.Connection,
MessengerId = (ushort)TunnelMessengerIds.FailForward,
Payload = MemoryPackSerializer.Serialize(tunnelTransportInfo)
});
}
public Dictionary<string, TunnelConnectInfo> Connections { get; } = new Dictionary<string, TunnelConnectInfo>();
private int connectionsChangeFlag = 1;
public bool ConnectionChanged => Interlocked.CompareExchange(ref connectionsChangeFlag, 0, 1) == 1;
private void OnConnecting(TunnelTransportInfo tunnelTransportInfo)
{
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
Logger.Instance.Debug($"tunnel connect [{tunnelTransportInfo.TransactionId}]->{tunnelTransportInfo.Remote.MachineName}");
}
CheckDic(tunnelTransportInfo.Remote.MachineName, out TunnelConnectInfo info);
info.Status = TunnelConnectStatus.Connecting;
Interlocked.Exchange(ref connectionsChangeFlag, 1);
}
private void OnConnectBegin(TunnelTransportInfo tunnelTransportInfo)
{
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
Logger.Instance.Debug($"tunnel connect from {tunnelTransportInfo.Local.MachineName}");
}
CheckDic(tunnelTransportInfo.Local.MachineName, out TunnelConnectInfo info);
info.Status = TunnelConnectStatus.Connecting;
Interlocked.Exchange(ref connectionsChangeFlag, 1);
}
private void _OnConnected(TunnelTransportState state)
{
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
Logger.Instance.Debug($"tunnel connect [{state.TransactionId}]->{state.RemoteMachineName} success");
}
CheckDic(state.RemoteMachineName, out TunnelConnectInfo info);
info.Status = TunnelConnectStatus.Connected;
info.State = state;
Interlocked.Exchange(ref connectionsChangeFlag, 1);
}
private void OnDisConnected(TunnelTransportState state)
{
CheckDic(state.RemoteMachineName, out TunnelConnectInfo info);
info.Status = TunnelConnectStatus.None;
info.State = null;
Interlocked.Exchange(ref connectionsChangeFlag, 1);
}
private void OnConnectFail(string machineName)
{
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
Logger.Instance.Error($"tunnel connect {machineName} fail");
}
CheckDic(machineName, out TunnelConnectInfo info);
info.Status = TunnelConnectStatus.None;
info.State = null;
Interlocked.Exchange(ref connectionsChangeFlag, 1);
}
private void CheckDic(string name, out TunnelConnectInfo info)
{
if (Connections.TryGetValue(name, out info) == false)
{
info = new TunnelConnectInfo();
Connections[name] = info;
}
}
public sealed class TunnelConnectInfo
{
public TunnelConnectStatus Status { get; set; }
public TunnelTransportState State { get; set; }
}
public enum TunnelConnectStatus
{
None = 0,
Connecting = 1,
Connected = 2,
}
}
}