Files
linker/linker.messenger.relay/server/RelayServerMasterTransfer.cs
snltty ad3b2c7320 demo
2024-12-21 18:01:49 +08:00

126 lines
4.8 KiB
C#

using linker.libs;
using linker.messenger.relay.server.caching;
using System.Collections.Concurrent;
using System.Net;
namespace linker.messenger.relay.server
{
/// <summary>
/// 中继主机操作
/// </summary>
public class RelayServerMasterTransfer
{
private ulong relayFlowingId = 0;
private readonly ICrypto crypto;
private readonly ConcurrentDictionary<string, RelayServerNodeReportInfo> reports = new ConcurrentDictionary<string, RelayServerNodeReportInfo>();
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<byte> TryGetRelayCache(string key)
{
if (relayCaching.TryGetValue(key, out RelayCacheInfo value))
{
byte[] bytes = crypto.Encode(serializer.Serialize(value));
return bytes;
}
return Helper.EmptyArray;
}
/// <summary>
/// 设置节点
/// </summary>
/// <param name="ep"></param>
/// <param name="data"></param>
public void SetNodeReport(IPEndPoint ep, Memory<byte> data)
{
try
{
if (crypto == null) return;
data = crypto.Decode(data.ToArray());
RelayServerNodeReportInfo relayNodeReportInfo = serializer.Deserialize<RelayServerNodeReportInfo>(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);
}
}
}
/// <summary>
/// 获取节点列表
/// </summary>
/// <param name="validated">是否已认证</param>
/// <returns></returns>
public List<RelayServerNodeReportInfo> 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();
}
/// <summary>
/// 是否需要认证
/// </summary>
/// <param name="nodeId"></param>
/// <returns></returns>
public bool NodeValidate(string nodeId)
{
return reports.TryGetValue(nodeId, out RelayServerNodeReportInfo relayNodeReportInfo) && relayNodeReportInfo.Public == false;
}
}
}