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; } } }