using linker.libs;
using linker.messenger.relay.server.caching;
using System.Collections.Concurrent;
using System.Net;
namespace linker.messenger.relay.server
{
///
/// 中继主机操作
///
public class RelayServerMasterTransfer
{
private ulong relayFlowingId = 0;
private readonly ICrypto crypto;
private readonly ConcurrentDictionary reports = new ConcurrentDictionary();
private readonly IRelayServerCaching relayCaching;
private readonly ISerializer serializer;
public RelayServerMasterTransfer(IRelayServerCaching relayCaching, ISerializer serializer, IRelayServerMasterStore relayServerMasterStore)
{
this.relayCaching = relayCaching;
this.serializer = serializer;
crypto = CryptoFactory.CreateSymmetric(relayServerMasterStore.Master.SecretKey);
}
public ulong AddRelay(string fromid, string fromName, string toid, string toName, string groupid)
{
ulong flowingId = Interlocked.Increment(ref relayFlowingId);
RelayCacheInfo cache = new RelayCacheInfo
{
FlowId = flowingId,
FromId = fromid,
FromName = fromName,
ToId = toid,
ToName = toName,
GroupId = groupid
};
bool added = relayCaching.TryAdd($"{fromid}->{toid}->{flowingId}", cache, 15000);
if (added == false) return 0;
return flowingId;
}
public Memory TryGetRelayCache(string key)
{
if (relayCaching.TryGetValue(key, out RelayCacheInfo value))
{
byte[] bytes = crypto.Encode(serializer.Serialize(value));
return bytes;
}
return Helper.EmptyArray;
}
///
/// 设置节点
///
///
///
public void SetNodeReport(IPEndPoint ep, Memory data)
{
try
{
if (crypto == null) return;
data = crypto.Decode(data.ToArray());
RelayServerNodeReportInfo relayNodeReportInfo = serializer.Deserialize(data.Span);
if (relayNodeReportInfo.Id == RelayServerNodeInfo.MASTER_NODE_ID)
{
relayNodeReportInfo.EndPoint = new IPEndPoint(IPAddress.Any, 0);
}
else if (relayNodeReportInfo.EndPoint.Address.Equals(IPAddress.Any))
{
relayNodeReportInfo.EndPoint.Address = ep.Address;
}
relayNodeReportInfo.LastTicks = Environment.TickCount64;
reports.AddOrUpdate(relayNodeReportInfo.Id, relayNodeReportInfo, (a, b) => relayNodeReportInfo);
}
catch (Exception ex)
{
if(LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Error(ex);
}
}
}
///
/// 获取节点列表
///
/// 是否已认证
///
public List GetNodes(bool validated)
{
var result = reports.Values
.Where(c => c.Public || (c.Public == false && validated))
.Where(c => Environment.TickCount64 - c.LastTicks < 15000)
.Where(c => c.ConnectionRatio < 100 && (c.MaxGbTotal == 0 || (c.MaxGbTotal > 0 && c.MaxGbTotalLastBytes > 0)))
.OrderByDescending(c => c.LastTicks);
return result.OrderByDescending(x => x.MaxConnection == 0 ? int.MaxValue : x.MaxConnection)
.ThenBy(x => x.ConnectionRatio)
.ThenBy(x => x.BandwidthRatio)
.ThenByDescending(x => x.MaxBandwidth == 0 ? double.MaxValue : x.MaxBandwidth)
.ThenByDescending(x => x.MaxBandwidthTotal == 0 ? double.MaxValue : x.MaxBandwidthTotal)
.ThenByDescending(x => x.MaxGbTotal == 0 ? double.MaxValue : x.MaxGbTotal)
.ThenByDescending(x => x.MaxGbTotalLastBytes == 0 ? ulong.MaxValue : x.MaxGbTotalLastBytes)
.ToList();
}
///
/// 是否需要认证
///
///
///
public bool NodeValidate(string nodeId)
{
return reports.TryGetValue(nodeId, out RelayServerNodeReportInfo relayNodeReportInfo) && relayNodeReportInfo.Public == false;
}
}
}