using linker.messenger.relay.client.transport;
using linker.tunnel.connection;
using linker.libs;
using linker.libs.extends;
using System.Collections.Concurrent;
namespace linker.messenger.relay.client
{
///
/// 中继
///
public sealed class RelayClientTransfer
{
public List Transports { get; private set; }
private ConcurrentDictionary connectingDic = new ConcurrentDictionary();
private Dictionary>> OnConnected { get; } = new Dictionary>>();
private readonly IRelayClientStore relayClientStore;
public RelayClientTransfer(IRelayClientStore relayClientStore)
{
this.relayClientStore = relayClientStore;
}
public void LoadTransports(List list)
{
Transports = list;
}
///
/// 设置中继成功回调
///
/// 事务
///
public void SetConnectedCallback(string transactionId, Action callback)
{
if (OnConnected.TryGetValue(transactionId, out List> callbacks) == false)
{
callbacks = new List>();
OnConnected[transactionId] = callbacks;
}
callbacks.Add(callback);
}
///
/// 一处中继成功回调
///
/// 事务
///
public void RemoveConnectedCallback(string transactionId, Action callback)
{
if (OnConnected.TryGetValue(transactionId, out List> callbacks))
{
callbacks.Remove(callback);
}
}
///
/// 中继连接对方
///
/// 自己的id
/// 对方id
/// 事务
///
public async Task ConnectAsync(string fromMachineId, string remoteMachineId, string transactionId, string nodeId = "")
{
if (connectingDic.TryAdd(remoteMachineId, true) == false)
{
return null;
}
try
{
IRelayClientTransport transport = Transports.FirstOrDefault(c => c.Type == relayClientStore.RelayType && relayClientStore.Disabled == false);
if (transport == null)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Error($"relay to {remoteMachineId} fail,transport not found {relayClientStore.RelayType},{relayClientStore.Disabled}");
return null;
}
transport.RelayInfo relayInfo = new transport.RelayInfo
{
FlowingId = 0,
FromMachineId = fromMachineId,
FromMachineName = string.Empty,
RemoteMachineId = remoteMachineId,
RemoteMachineName = string.Empty,
SecretKey = relayClientStore.SecretKey,
TransactionId = transactionId,
TransportName = transport.Name,
SSL = relayClientStore.SSL,
NodeId = nodeId
};
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Info($"relay to {relayInfo.RemoteMachineId}->{relayInfo.RemoteMachineName} {relayInfo.ToJson()}");
ITunnelConnection connection = await transport.RelayAsync(relayInfo).ConfigureAwait(false);
if (connection != null)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Debug($"relay to {relayInfo.RemoteMachineId}->{relayInfo.RemoteMachineName} success,{relayInfo.ToJson()}");
ConnectedCallback(relayInfo, connection);
return connection;
}
else
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Error($"relay to {relayInfo.RemoteMachineId}->{relayInfo.RemoteMachineName} fail,{relayInfo.ToJson()}");
}
}
catch (Exception ex)
{
LoggerHelper.Instance.Error(ex);
}
finally
{
connectingDic.TryRemove(remoteMachineId, out _);
}
return null;
}
///
/// 收到对方的中继请求
///
///
///
public async Task OnBeginAsync(transport.RelayInfo relayInfo)
{
if (connectingDic.TryAdd(relayInfo.FromMachineId, true) == false)
{
return false;
}
try
{
IRelayClientTransport _transports = Transports.FirstOrDefault(c => c.Name == relayInfo.TransportName);
if (_transports == null) return false;
await _transports.OnBeginAsync(relayInfo, (connection) =>
{
if (connection != null)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Debug($"relay from {relayInfo.RemoteMachineId}->{relayInfo.RemoteMachineName} success,{relayInfo.ToJson()}");
ConnectedCallback(relayInfo, connection);
}
else
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Error($"relay from {relayInfo.RemoteMachineId}->{relayInfo.RemoteMachineName} error,{relayInfo.ToJson()}");
}
}).ConfigureAwait(false);
return true;
}
catch (Exception ex)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Error(ex);
}
}
finally
{
connectingDic.TryRemove(relayInfo.FromMachineId, out _);
}
return false;
}
///
/// 回调
///
///
///
private void ConnectedCallback(transport.RelayInfo relayInfo, ITunnelConnection connection)
{
if (OnConnected.TryGetValue(Helper.GlobalString, out List> callbacks))
{
foreach (var item in callbacks)
{
item(connection);
}
}
if (OnConnected.TryGetValue(connection.TransactionId, out callbacks))
{
foreach (var callabck in callbacks)
{
callabck(connection);
}
}
}
}
}