mirror of
				https://github.com/snltty/linker.git
				synced 2025-10-31 20:43:00 +08:00 
			
		
		
		
	增加管理接口秘钥
This commit is contained in:
		
							
								
								
									
										246
									
								
								cmonitor/plugins/tunnel/TunnelTransfer.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										246
									
								
								cmonitor/plugins/tunnel/TunnelTransfer.cs
									
									
									
									
									
										Normal 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, | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 snltty
					snltty