合并中继和穿透的多节点公共代码,公用多节点逻辑

This commit is contained in:
snltty
2025-12-10 17:13:39 +08:00
parent b38c91ebe3
commit 3f9dfe019c
60 changed files with 1471 additions and 1908 deletions

View File

@@ -34,6 +34,7 @@ jobs:
dotnet build ./src/linker.messenger.forward -c release
dotnet build ./src/linker.messenger.listen -c release
dotnet build ./src/linker.messenger.logger -c release
dotnet build ./src/linker.messenger.node -c release
dotnet build ./src/linker.messenger.pcp -c release
dotnet build ./src/linker.messenger.plan -c release
dotnet build ./src/linker.messenger.relay -c release
@@ -67,6 +68,7 @@ jobs:
dotnet pack ./src/linker.messenger.forward -c release
dotnet pack ./src/linker.messenger.listen -c release
dotnet pack ./src/linker.messenger.logger -c release
dotnet pack ./src/linker.messenger.node -c release
dotnet pack ./src/linker.messenger.pcp -c release
dotnet pack ./src/linker.messenger.plan -c release
dotnet pack ./src/linker.messenger.relay -c release
@@ -101,6 +103,7 @@ jobs:
dotnet nuget push ./src/linker.messenger.forward/bin/release/linker.messenger.forward.1.9.7.nupkg --source https://api.nuget.org/v3/index.json --skip-duplicate --api-key ${{ secrets.NUGET_KEY }} --no-symbols
dotnet nuget push ./src/linker.messenger.listen/bin/release/linker.messenger.listen.1.9.7.nupkg --source https://api.nuget.org/v3/index.json --skip-duplicate --api-key ${{ secrets.NUGET_KEY }} --no-symbols
dotnet nuget push ./src/linker.messenger.logger/bin/release/linker.messenger.logger.1.9.7.nupkg --source https://api.nuget.org/v3/index.json --skip-duplicate --api-key ${{ secrets.NUGET_KEY }} --no-symbols
dotnet nuget push ./src/linker.messenger.node/bin/release/linker.messenger.node.1.9.7.nupkg --source https://api.nuget.org/v3/index.json --skip-duplicate --api-key ${{ secrets.NUGET_KEY }} --no-symbols
dotnet nuget push ./src/linker.messenger.pcp/bin/release/linker.messenger.pcp.1.9.7.nupkg --source https://api.nuget.org/v3/index.json --skip-duplicate --api-key ${{ secrets.NUGET_KEY }} --no-symbols
dotnet nuget push ./src/linker.messenger.plan/bin/release/linker.messenger.plan.1.9.7.nupkg --source https://api.nuget.org/v3/index.json --skip-duplicate --api-key ${{ secrets.NUGET_KEY }} --no-symbols
dotnet nuget push ./src/linker.messenger.relay/bin/release/linker.messenger.relay.1.9.7.nupkg --source https://api.nuget.org/v3/index.json --skip-duplicate --api-key ${{ secrets.NUGET_KEY }} --no-symbols

View File

@@ -0,0 +1,59 @@
namespace linker.messenger.node
{
public interface INodeConfigBase
{
public string NodeId { get; set; }
public string MasterKey { get; set; }
public string ShareKey { get; set; }
public string Host { get; set; }
public string Name { get; set; }
public int Connections { get; set; }
public int Bandwidth { get; set; }
public int DataEachMonth { get; set; }
public long DataRemain { get; set; }
public int DataMonth { get; set; }
public string Url { get; set; }
public string Logo { get; set; }
}
public interface INodeConfigStore<T> where T : class, INodeConfigBase, new()
{
public int ServicePort { get; }
/// <summary>
/// 节点信息
/// </summary>
public T Config { get; }
/// <summary>
/// 设置月份
/// </summary>
/// <param name="month"></param>
public void SetDataMonth(int month);
/// <summary>
/// 设置剩余流量
/// </summary>
/// <param name="value"></param>
public void SetDataRemain(long value);
public void SetShareKey(string shareKey);
public void SetMasterKey(string masterKey);
/// <summary>
/// 提交保存
/// </summary>
public void Confirm();
}
public sealed class NodeShareInfo
{
public string NodeId { get; set; } = string.Empty;
public string Host { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public string SystemId { get; set; } = string.Empty;
}
}

View File

@@ -0,0 +1,32 @@
namespace linker.messenger.node
{
public interface INodeMasterDenyStore
{
public Task<MasterDenyStoreResponseInfo> Get(MasterDenyStoreRequestInfo request);
public Task<bool> Get(uint ip);
public Task<bool> Add(string str);
public Task<bool> Delete(int id);
}
public sealed class MasterDenyStoreRequestInfo
{
public int Page { get; set; }
public int Sise { get; set; }
public string Str { get; set; }
}
public sealed class MasterDenyStoreResponseInfo
{
public int Page { get; set; }
public int Sise { get; set; }
public int Count { get; set; }
public List<MasterDenyStoreInfo> List { get; set; } = new List<MasterDenyStoreInfo>();
}
public sealed class MasterDenyStoreInfo
{
public int Id { get; set; }
public uint Ip { get; set; }
public uint Plus { get; set; }
public string Str { get; set; }
}
}

View File

@@ -0,0 +1,52 @@
using linker.libs.extends;
namespace linker.messenger.node
{
public interface INodeStoreBase
{
public string NodeId { get; set; }
public string Name { get; set; }
public string Host { get; set; }
public bool Manageable { get; set; }
public string MasterKey { get; set; }
public string ShareKey { get; set; }
public long LastTicks { get; set; }
}
public interface INodeReportBase
{
public string NodeId { get; set; }
public string Name { get; set; }
public int Connections { get; set; }
public int Bandwidth { get; set; }
public int DataEachMonth { get; set; }
public long DataRemain { get; set; }
public string Url { get; set; }
public string Logo { get; set; }
public string MasterKey { get; set; }
public string Version { get; set; }
public int ConnectionsRatio { get; set; }
public double BandwidthRatio { get; set; }
public int MasterCount { get; set; }
public string Host { get; set; }
}
public interface INodeStore<TStore, TReport>
where TStore : class, INodeStoreBase, new()
where TReport : class, INodeReportBase, new()
{
public string StoreName { get; }
public Task<List<TStore>> GetAll();
public Task<TStore> GetByNodeId(string nodeId);
public Task<bool> Add(TStore info);
public Task<bool> Report(TReport info);
public Task<bool> Delete(string nodeId);
public Task<bool> Update(TStore info);
}
}

View File

@@ -0,0 +1,48 @@
namespace linker.messenger.node
{
/// <summary>
/// 白名单接口
/// </summary>
public interface INodeWhiteListStore
{
public string TypeName { get; }
/// <summary>
/// 获取白名单
/// </summary>
/// <param name="userid"></param>
/// <param name="machineid"></param>
/// <returns></returns>
public Task<List<NodeWhiteListInfo>> GetNodes(string userid, string machineid);
/// <summary>
/// 获取白名单
/// </summary>
/// <param name="userid"></param>
/// <param name="fromMachineId"></param>
/// <param name="toMachineId"></param>
/// <param name="nodeid"></param>
/// <returns></returns>
public Task<List<double>> GetBandwidth(string userid, string fromMachineId, string toMachineId, string nodeid);
}
public sealed class NodeWhiteListStore : INodeWhiteListStore
{
public string TypeName => string.Empty;
public async Task<List<NodeWhiteListInfo>> GetNodes(string userid, string machineid)
{
return await Task.FromResult(new List<NodeWhiteListInfo>());
}
public async Task<List<double>> GetBandwidth(string userid, string fromMachineId, string toMachineId, string nodeid)
{
return await Task.FromResult(new List<double>());
}
}
public sealed class NodeWhiteListInfo
{
public string[] Nodes { get; set; } = [];
public double Bandwidth { get; set; } = 0;
}
}

View File

@@ -3,15 +3,15 @@ using linker.libs.extends;
using System.Net;
using System.Net.Sockets;
namespace linker.messenger.sforward.server
namespace linker.messenger.node
{
public class SForwardServerConnectionResolver : IResolver
public class NodeConnectionResolver : IResolver
{
public byte Type => (byte)ResolverType.SForwardConnection;
public virtual byte Type => (byte)ResolverType.NodeConnection;
private readonly IMessengerResolver messengerResolver;
public SForwardServerConnectionResolver(IMessengerResolver messengerResolver)
public NodeConnectionResolver(IMessengerResolver messengerResolver)
{
this.messengerResolver = messengerResolver;
}

View File

@@ -0,0 +1,41 @@
using System.Collections.Concurrent;
namespace linker.messenger.node
{
public class NodeConnectionTransfer
{
private readonly ConcurrentDictionary<string, IConnection>[] connections = [
new ConcurrentDictionary<string, IConnection>()
,new ConcurrentDictionary<string, IConnection>()
];
public NodeConnectionTransfer()
{
}
public List<IConnection> Get(ConnectionSideType type)
{
return connections[(byte)type].Values.Where(c => c.Connected).ToList();
}
public bool TryGet(ConnectionSideType type, string id, out IConnection connection)
{
return connections[(byte)type].TryGetValue(id, out connection);
}
public bool TryAdd(ConnectionSideType type, string id, IConnection connection)
{
if (connections[(byte)type].TryRemove(id, out IConnection _connection) && _connection.GetHashCode() != connection.GetHashCode())
{
_connection.Disponse();
}
return connections[(byte)type].TryAdd(id, connection);
}
}
public enum ConnectionSideType : byte
{
Node = 0,
Master = 1
}
}

View File

@@ -0,0 +1,407 @@
using linker.libs;
using linker.libs.extends;
using linker.libs.timer;
using System.Net;
using System.Net.Sockets;
namespace linker.messenger.node
{
public class NodeReportTransfer<TConfig, TStore, TReport>
where TConfig : class, INodeConfigBase, new()
where TStore : class, INodeStoreBase, new()
where TReport : class, INodeReportBase, new()
{
public TConfig Config => nodeConfigStore.Config;
public int ConnectionNum => connectionNum;
public virtual ushort MessengerIdSahre { get; }
public virtual ushort MessengerIdUpdateForward { get; }
public virtual ushort MessengerIdUpgradeForward { get; }
public virtual ushort MessengerIdExitForward { get; }
public virtual ushort MessengerIdReport { get; }
public virtual ushort MessengerIdSignIn { get; }
private int connectionNum = 0;
private ulong bytes = 0;
private ulong lastBytes = 0;
private readonly string md5 = string.Empty;
private readonly ICrypto crypto = CryptoFactory.CreateSymmetric(Helper.GlobalString);
private readonly NodeConnectionTransfer nodeConnectionTransfer;
private readonly INodeConfigStore<TConfig> nodeConfigStore;
private readonly ISerializer serializer;
private readonly IMessengerSender messengerSender;
private readonly INodeStore<TStore, TReport> nodeStore;
private readonly IMessengerResolver messengerResolver;
public NodeReportTransfer(NodeConnectionTransfer nodeConnectionTransfer, INodeConfigStore<TConfig> nodeConfigStore,
ISerializer serializer, IMessengerSender messengerSender, INodeStore<TStore, TReport> nodeStore,
IMessengerResolver messengerResolver, ICommonStore commonStore)
{
this.nodeConnectionTransfer = nodeConnectionTransfer;
this.nodeConfigStore = nodeConfigStore;
this.serializer = serializer;
this.messengerSender = messengerSender;
this.nodeStore = nodeStore;
this.messengerResolver = messengerResolver;
md5 = Config.NodeId.Md5();
if (commonStore.Modes.HasFlag(CommonModes.Server))
{
_ = ReportTask();
SignInTask();
}
}
public void IncrementConnectionNum()
{
Interlocked.Increment(ref connectionNum);
}
public void DecrementConnectionNum()
{
Interlocked.Decrement(ref connectionNum);
}
public void AddBytes(long length)
{
Interlocked.Add(ref bytes, (ulong)length);
}
public async Task<bool> Report(string id, string name, string host)
{
return await nodeStore.Add(new TStore
{
NodeId = id,
Name = name,
Host = host
}).ConfigureAwait(false);
}
public async Task<bool> Report(TReport info)
{
if (nodeConnectionTransfer.TryGet(ConnectionSideType.Node, info.NodeId, out _) == false) return false;
return await nodeStore.Report(info).ConfigureAwait(false);
}
public async Task<bool> SignIn(string serverId, string shareKey, IConnection connection)
{
//未被配置,或默认配置的,设它为管理端
if (string.IsNullOrWhiteSpace(Config.MasterKey) || md5 == Config.MasterKey)
{
nodeConfigStore.SetMasterKey(serverId.Md5());
nodeConfigStore.Confirm();
}
if (shareKey != Config.ShareKey && serverId.Md5() != Config.MasterKey)
{
return false;
}
connection.Id = serverId;
nodeConnectionTransfer.TryAdd(ConnectionSideType.Master, connection.Id, connection);
return true;
}
public async Task<string> GetShareKeyForward(string nodeId)
{
TStore store = await nodeStore.GetByNodeId(nodeId);
if (store != null && store.Manageable && nodeConnectionTransfer.TryGet(ConnectionSideType.Node, nodeId, out var connection))
{
var resp = await messengerSender.SendReply(new MessageRequestWrap
{
Connection = connection,
MessengerId = MessengerIdSahre,
Payload = serializer.Serialize(store.MasterKey)
});
if (resp.Code == MessageResponeCodes.OK)
{
return serializer.Deserialize<string>(resp.Data.Span);
}
}
return string.Empty;
}
public async Task<string> GetShareKey(string masterKey)
{
if (masterKey != Config.MasterKey) return string.Empty;
return Config.ShareKey;
}
public async Task<string> Import(string shareKey)
{
try
{
NodeShareInfo info = serializer.Deserialize<NodeShareInfo>(crypto.Decode(Convert.FromBase64String(shareKey)).Span);
bool result = await nodeStore.Add(new TStore
{
NodeId = info.NodeId,
Host = info.Host,
Name = info.Name,
LastTicks = Environment.TickCount64,
ShareKey = shareKey
}).ConfigureAwait(false);
if (result == false)
{
return "node already exists";
}
}
catch (Exception ex)
{
return ex.Message;
}
return string.Empty;
}
public async Task<bool> Remove(string nodeId)
{
if (nodeId == Config.NodeId) return false;
return await nodeStore.Delete(nodeId).ConfigureAwait(false);
}
public async Task<bool> UpdateForward(TStore info)
{
TStore store = await nodeStore.GetByNodeId(info.NodeId);
if (store != null && store.Manageable && nodeConnectionTransfer.TryGet(ConnectionSideType.Node, info.NodeId, out var connection))
{
info.MasterKey = store.MasterKey;
await messengerSender.SendOnly(new MessageRequestWrap
{
Connection = connection,
MessengerId = MessengerIdUpdateForward,
Payload = serializer.Serialize(info)
});
}
return await nodeStore.Update(info).ConfigureAwait(false);
}
public virtual async Task<bool> Update(TStore info)
{
return false;
}
public async Task<bool> UpgradeForward(string nodeId, string version)
{
TStore store = await nodeStore.GetByNodeId(nodeId);
if (store != null && store.Manageable && nodeConnectionTransfer.TryGet(ConnectionSideType.Node, nodeId, out var connection))
{
await messengerSender.SendOnly(new MessageRequestWrap
{
Connection = connection,
MessengerId = MessengerIdUpgradeForward,
Payload = serializer.Serialize(new KeyValuePair<string, string>(store.MasterKey, version))
});
return true;
}
return false;
}
public async Task<bool> Upgrade(string masterKey, string version)
{
if (masterKey != Config.MasterKey) return false;
Helper.AppUpdate(version);
return true;
}
public async Task<bool> ExitForward(string nodeId)
{
TStore store = await nodeStore.GetByNodeId(nodeId);
if (store != null && store.Manageable && nodeConnectionTransfer.TryGet(ConnectionSideType.Node, nodeId, out var connection))
{
await messengerSender.SendOnly(new MessageRequestWrap
{
Connection = connection,
MessengerId = MessengerIdExitForward,
Payload = serializer.Serialize(new KeyValuePair<string, string>(store.MasterKey, nodeId))
});
return true;
}
return false;
}
public async Task<bool> Exit(string masterKey)
{
if (masterKey != Config.MasterKey) return false;
Helper.AppExit(-1);
return true;
}
/// <summary>
/// 获取节点列表
/// </summary>
/// <param name="super">是否已认证</param>
/// <returns></returns>
public virtual async Task<List<TStore>> GetNodes(bool super, string userid, string machineId)
{
return [];
}
public async Task<TStore> GetNode(string nodeId)
{
TStore node = await nodeStore.GetByNodeId(nodeId).ConfigureAwait(false);
if (node == null || Environment.TickCount64 - node.LastTicks > 15000)
{
return null;
}
return node;
}
protected virtual void BuildReport(TReport info)
{
}
private async Task BuildShareKey()
{
try
{
string host = Config.Host;
if (string.IsNullOrWhiteSpace(host))
{
using HttpClient httpClient = new HttpClient();
host = await httpClient.GetStringAsync($"https://ifconfig.me/ip").WaitAsync(TimeSpan.FromMilliseconds(5000)).ConfigureAwait(false);
}
NodeShareInfo shareKeyInfo = new NodeShareInfo
{
NodeId = Config.NodeId,
Host = $"{host}:{nodeConfigStore.ServicePort}",
Name = Config.Name,
SystemId = SystemIdHelper.GetSystemId().Md5()
};
string shareKey = Convert.ToBase64String(crypto.Encode(serializer.Serialize(shareKeyInfo)));
nodeConfigStore.SetShareKey(shareKey);
nodeConfigStore.Confirm();
host = $"{IPAddress.Loopback}:{nodeConfigStore.ServicePort}";
var node = await nodeStore.GetByNodeId(nodeConfigStore.Config.NodeId);
if (node == null || node.ShareKey != shareKey || node.Name != Config.Name || node.Host != host)
{
await nodeStore.Delete(nodeConfigStore.Config.NodeId);
await nodeStore.Add(new TStore
{
NodeId = nodeConfigStore.Config.NodeId,
Name = "default",
Host = $"{IPAddress.Loopback}:{nodeConfigStore.ServicePort}",
ShareKey = shareKey
}).ConfigureAwait(false);
}
LoggerHelper.Instance.Warning($"build SForward share key : {shareKey}");
}
catch (Exception ex)
{
LoggerHelper.Instance.Error($"build SForward share key error : {ex}");
}
}
private async Task ReportTask()
{
await BuildShareKey().ConfigureAwait(false);
TimerHelper.SetIntervalLong(async () =>
{
try
{
var connections = nodeConnectionTransfer.Get(ConnectionSideType.Master);
if (connections.Count != 0)
{
double diff = (bytes - lastBytes) * 8 / 1024.0 / 1024.0;
lastBytes = bytes;
var config = nodeConfigStore.Config;
TReport info = new TReport
{
Bandwidth = config.Bandwidth,
Connections = config.Connections,
DataEachMonth = config.DataEachMonth,
DataRemain = config.DataRemain,
Logo = config.Logo,
Name = config.Name,
NodeId = config.NodeId,
Url = config.Url,
ConnectionsRatio = connectionNum,
BandwidthRatio = Math.Round(diff / 5, 2),
Version = VersionHelper.Version,
MasterCount = connections.Count,
MasterKey = config.MasterKey
};
BuildReport(info);
byte[] memory = serializer.Serialize(info);
var tasks = connections.Select(c => messengerSender.SendOnly(new MessageRequestWrap
{
Connection = c,
MessengerId = MessengerIdReport,
Payload = memory,
Timeout = 5000
})).ToList();
await Task.WhenAll(tasks).ConfigureAwait(false);
}
}
catch (Exception ex)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Error($"SForward report : {ex}");
}
}
}, 5000);
}
private void SignInTask()
{
TimerHelper.SetIntervalLong(async () =>
{
try
{
var nodes = (await nodeStore.GetAll()).Where(c =>
{
return nodeConnectionTransfer.TryGet(ConnectionSideType.Node, c.NodeId, out IConnection connection) == false || connection == null || connection.Connected == false;
}).ToList();
if (nodes.Count != 0)
{
var tasks = nodes.Select(async c =>
{
IPEndPoint remote = await NetworkHelper.GetEndPointAsync(c.Host, 1802).ConfigureAwait(false);
Socket socket = new Socket(remote.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.KeepAlive();
await socket.ConnectAsync(remote).WaitAsync(TimeSpan.FromMilliseconds(5000)).ConfigureAwait(false);
var connection = await messengerResolver.BeginReceiveClient(socket, true, (byte)ResolverType.NodeConnection, Helper.EmptyArray).ConfigureAwait(false);
var resp = await messengerSender.SendReply(new MessageRequestWrap
{
Connection = connection,
MessengerId = MessengerIdSignIn,
Payload = serializer.Serialize(new KeyValuePair<string, string>(Config.NodeId, c.ShareKey)),
Timeout = 5000
}).ConfigureAwait(false);
if (resp.Code == MessageResponeCodes.OK && resp.Data.Span.SequenceEqual(Helper.TrueArray))
{
LoggerHelper.Instance.Debug($"SForward sign in to node {c.NodeId} success");
nodeConnectionTransfer.TryAdd(ConnectionSideType.Node, c.NodeId, connection);
}
else
{
connection?.Disponse();
}
});
await Task.WhenAll(tasks).ConfigureAwait(false);
}
}
catch (Exception ex)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Error($"SForward sign in : {ex}");
}
}
}, 10000);
}
}
}

View File

@@ -0,0 +1,269 @@
using linker.libs;
using linker.libs.timer;
using System.Collections.Concurrent;
namespace linker.messenger.node
{
/// <summary>
/// 节点操作
/// </summary>
public class NodeTransfer<TConfig, TStore, TReport>
where TConfig : class, INodeConfigBase, new()
where TStore : class, INodeStoreBase, new()
where TReport : class, INodeReportBase, new()
{
public TConfig Config => nodeConfigStore.Config;
private readonly NumberSpace ns = new(65537);
private readonly SpeedLimit limitTotal = new();
private readonly ConcurrentDictionary<ulong, TrafficCacheInfo> trafficDict = new();
private readonly INodeConfigStore<TConfig> nodeConfigStore;
private readonly NodeReportTransfer<TConfig, TStore, TReport> nodeReportTransfer;
public NodeTransfer(ICommonStore commonStore, INodeConfigStore<TConfig> nodeConfigStore, NodeReportTransfer<TConfig, TStore, TReport> nodeReportTransfer)
{
this.nodeConfigStore = nodeConfigStore;
this.nodeReportTransfer = nodeReportTransfer;
if ((commonStore.Modes & CommonModes.Server) == CommonModes.Server)
{
limitTotal.SetLimit((uint)Math.Ceiling((Config.Bandwidth * 1024 * 1024) / 8.0));
TrafficTask();
}
}
/// <summary>
/// 增加连接数
/// </summary>
public void IncrementConnectionNum()
{
nodeReportTransfer.IncrementConnectionNum();
}
/// <summary>
/// 减少连接数
/// </summary>
public void DecrementConnectionNum()
{
nodeReportTransfer.DecrementConnectionNum();
}
/// <summary>
/// 是否需要总限速
/// </summary>
/// <returns></returns>
public bool NeedLimit(TrafficCacheInfo cache)
{
return limitTotal.NeedLimit();
}
/// <summary>
/// 总限速
/// </summary>
/// <param name="length"></param>
/// <returns></returns>
public bool TryLimit(ref int length)
{
return limitTotal.TryLimit(ref length);
}
/// <summary>
/// 总限速
/// </summary>
/// <param name="length"></param>
/// <returns></returns>
public bool TryLimitPacket(int length)
{
return limitTotal.TryLimitPacket(length);
}
/// <summary>
/// 开始计算流量
/// </summary>
/// <param name="super"></param>
/// <returns></returns>
public TrafficCacheInfo AddTrafficCache(bool super, double bandwidth)
{
TrafficCacheInfo cache = new TrafficCacheInfo { Cache = new CacheInfo { FlowId = ns.Increment(), Super = super, Bandwidth = bandwidth }, Limit = new SpeedLimit(), Sendt = 0, SendtCache = 0 };
if (cache.Cache.Bandwidth < 0)
{
cache.Cache.Bandwidth = Config.Bandwidth;
}
SetLimit(cache);
trafficDict.TryAdd(cache.Cache.FlowId, cache);
return cache;
}
public void RemoveTrafficCache(ulong id)
{
trafficDict.TryRemove(id, out _);
}
/// <summary>
/// 开始计算流量
/// </summary>
/// <param name="cache"></param>
public void AddTrafficCache(TrafficCacheInfo cache)
{
SetLimit(cache);
trafficDict.TryAdd(cache.Cache.FlowId, cache);
}
/// <summary>
/// 取消计算流量
/// </summary>
/// <param name="cache"></param>
public void RemoveTrafficCache(TrafficCacheInfo cache)
{
trafficDict.TryRemove(cache.Cache.FlowId, out _);
}
/// <summary>
/// 消耗流量
/// </summary>
/// <param name="length"></param>
/// <returns></returns>
public bool AddBytes(TrafficCacheInfo cache, long length)
{
nodeReportTransfer.AddBytes(length);
if (Config.DataEachMonth == 0) return true;
Interlocked.Add(ref cache.Sendt, length);
return Config.DataRemain > 0;
}
/// <summary>
/// 设置限速
/// </summary>
/// <param name="cache"></param>
private void SetLimit(TrafficCacheInfo cache)
{
if (cache.Cache.Bandwidth >= 0)
{
cache.Limit.SetLimit((uint)Math.Ceiling(cache.Cache.Bandwidth * 1024 * 1024 / 8.0));
return;
}
cache.Limit.SetLimit((uint)Math.Ceiling(Config.Bandwidth * 1024 * 1024 / 8.0));
}
private void ResetNodeBytes()
{
if (Config.DataEachMonth == 0) return;
foreach (var cache in trafficDict.Values)
{
long length = Interlocked.Exchange(ref cache.Sendt, 0);
if (Config.DataRemain >= length)
nodeConfigStore.SetDataRemain(Config.DataRemain - length);
else nodeConfigStore.SetDataRemain(0);
}
if (Config.DataMonth != DateTime.Now.Month)
{
nodeConfigStore.SetDataMonth(DateTime.Now.Month);
nodeConfigStore.SetDataRemain((long)(Config.DataEachMonth * 1024 * 1024 * 1024));
}
nodeConfigStore.Confirm();
}
private void TrafficTask()
{
TimerHelper.SetIntervalLong(() =>
{
try
{
ResetNodeBytes();
}
catch (Exception ex)
{
LoggerHelper.Instance.Error(ex);
}
}, 3000);
}
}
public class CacheInfo
{
public ulong FlowId { get; set; }
public bool Super { get; set; }
public double Bandwidth { get; set; } = double.MinValue;
}
public class SpeedLimit
{
private uint limit = 0;
private double limitToken = 0;
private double limitBucket = 0;
private long limitTicks = Environment.TickCount64;
public bool NeedLimit()
{
return limit > 0;
}
public void SetLimit(uint bytes)
{
//每s多少字节
limit = bytes;
//每ms多少字节
limitToken = limit / 1000.0;
//桶里有多少字节
limitBucket = limit;
}
public bool TryLimit(ref int length)
{
//0不限速
if (limit == 0) return true;
lock (this)
{
long _limitTicks = Environment.TickCount64;
//距离上次经过了多少ms
long limitTicksTemp = _limitTicks - limitTicks;
limitTicks = _limitTicks;
//桶里增加多少字节
limitBucket += limitTicksTemp * limitToken;
//桶溢出了
if (limitBucket > limit) limitBucket = limit;
//能全部消耗调
if (limitBucket >= length)
{
limitBucket -= length;
length = 0;
}
else
{
//只能消耗一部分
length -= (int)limitBucket;
limitBucket = 0;
}
}
return true;
}
public bool TryLimitPacket(int length)
{
if (limit == 0) return true;
lock (this)
{
long _limitTicks = Environment.TickCount64;
long limitTicksTemp = _limitTicks - limitTicks;
limitTicks = _limitTicks;
limitBucket += limitTicksTemp * limitToken;
if (limitBucket > limit) limitBucket = limit;
if (limitBucket >= length)
{
limitBucket -= length;
return true;
}
}
return false;
}
}
public class TrafficCacheInfo
{
public long Sendt;
public long SendtCache;
public SpeedLimit Limit { get; set; }
public CacheInfo Cache { get; set; }
public string Key { get; set; }
}
}

View File

@@ -0,0 +1,43 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>disable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PublishAot>false</PublishAot>
<JsonSerializerIsReflectionEnabledByDefault>true</JsonSerializerIsReflectionEnabledByDefault>
<Title>linker messenger node</Title>
<Authors>snltty</Authors>
<Company>snltty</Company>
<Description>linker messenger node</Description>
<Copyright>snltty</Copyright>
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
<PackageReleaseNotes>linker messenger node</PackageReleaseNotes>
<Version>1.9.7</Version>
<AssemblyVersion>1.9.7</AssemblyVersion>
<FileVersion>1.9.7</FileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>full</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DebugType>full</DebugType>
<DebugSymbols>true</DebugSymbols>
<Optimize>True</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net8.0|AnyCPU'">
<DebugType>embedded</DebugType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net8.0|AnyCPU'">
<DebugType>embedded</DebugType>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\src\linker.libs\linker.libs.csproj" />
<ProjectReference Include="..\src\linker.messenger\linker.messenger.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.10.35027.167
# Visual Studio Version 18
VisualStudioVersion = 18.0.11222.15 d18.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "linker", "src\linker\linker.csproj", "{267DE8BE-F91C-4CCB-9D58-D33FDA661126}"
EndProject
@@ -71,6 +71,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "linker.messenger.rapp", "sr
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "linker.messenger.wlist", "src\linker.messenger.wlist\linker.messenger.wlist.csproj", "{26550C65-0960-4BA3-9F83-BAC90DE9AA57}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "linker.messenger.node", "linker.messenger.node\linker.messenger.node.csproj", "{1A14DE99-3939-4E37-9FD5-9C467DF015EC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -495,6 +497,18 @@ Global
{26550C65-0960-4BA3-9F83-BAC90DE9AA57}.Release|x64.Build.0 = Release|Any CPU
{26550C65-0960-4BA3-9F83-BAC90DE9AA57}.Release|x86.ActiveCfg = Release|Any CPU
{26550C65-0960-4BA3-9F83-BAC90DE9AA57}.Release|x86.Build.0 = Release|Any CPU
{1A14DE99-3939-4E37-9FD5-9C467DF015EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1A14DE99-3939-4E37-9FD5-9C467DF015EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1A14DE99-3939-4E37-9FD5-9C467DF015EC}.Debug|x64.ActiveCfg = Debug|Any CPU
{1A14DE99-3939-4E37-9FD5-9C467DF015EC}.Debug|x64.Build.0 = Debug|Any CPU
{1A14DE99-3939-4E37-9FD5-9C467DF015EC}.Debug|x86.ActiveCfg = Debug|Any CPU
{1A14DE99-3939-4E37-9FD5-9C467DF015EC}.Debug|x86.Build.0 = Debug|Any CPU
{1A14DE99-3939-4E37-9FD5-9C467DF015EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1A14DE99-3939-4E37-9FD5-9C467DF015EC}.Release|Any CPU.Build.0 = Release|Any CPU
{1A14DE99-3939-4E37-9FD5-9C467DF015EC}.Release|x64.ActiveCfg = Release|Any CPU
{1A14DE99-3939-4E37-9FD5-9C467DF015EC}.Release|x64.Build.0 = Release|Any CPU
{1A14DE99-3939-4E37-9FD5-9C467DF015EC}.Release|x86.ActiveCfg = Release|Any CPU
{1A14DE99-3939-4E37-9FD5-9C467DF015EC}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -1,5 +1,5 @@
v1.9.7
2025-12-09 16:23:22
2025-12-10 17:13:38
1. 一些累计更新一些BUG修复
2. 重构中继和穿透的多节点模式
3. 中继连接合并到隧道协议中

View File

@@ -34,6 +34,7 @@ jobs:
dotnet build ./src/linker.messenger.forward -c release
dotnet build ./src/linker.messenger.listen -c release
dotnet build ./src/linker.messenger.logger -c release
dotnet build ./src/linker.messenger.node -c release
dotnet build ./src/linker.messenger.pcp -c release
dotnet build ./src/linker.messenger.plan -c release
dotnet build ./src/linker.messenger.relay -c release
@@ -67,6 +68,7 @@ jobs:
dotnet pack ./src/linker.messenger.forward -c release
dotnet pack ./src/linker.messenger.listen -c release
dotnet pack ./src/linker.messenger.logger -c release
dotnet pack ./src/linker.messenger.node -c release
dotnet pack ./src/linker.messenger.pcp -c release
dotnet pack ./src/linker.messenger.plan -c release
dotnet pack ./src/linker.messenger.relay -c release
@@ -101,6 +103,7 @@ jobs:
dotnet nuget push ./src/linker.messenger.forward/bin/release/linker.messenger.forward.{{version}}.nupkg --source https://api.nuget.org/v3/index.json --skip-duplicate --api-key ${{ secrets.NUGET_KEY }} --no-symbols
dotnet nuget push ./src/linker.messenger.listen/bin/release/linker.messenger.listen.{{version}}.nupkg --source https://api.nuget.org/v3/index.json --skip-duplicate --api-key ${{ secrets.NUGET_KEY }} --no-symbols
dotnet nuget push ./src/linker.messenger.logger/bin/release/linker.messenger.logger.{{version}}.nupkg --source https://api.nuget.org/v3/index.json --skip-duplicate --api-key ${{ secrets.NUGET_KEY }} --no-symbols
dotnet nuget push ./src/linker.messenger.node/bin/release/linker.messenger.node.{{version}}.nupkg --source https://api.nuget.org/v3/index.json --skip-duplicate --api-key ${{ secrets.NUGET_KEY }} --no-symbols
dotnet nuget push ./src/linker.messenger.pcp/bin/release/linker.messenger.pcp.{{version}}.nupkg --source https://api.nuget.org/v3/index.json --skip-duplicate --api-key ${{ secrets.NUGET_KEY }} --no-symbols
dotnet nuget push ./src/linker.messenger.plan/bin/release/linker.messenger.plan.{{version}}.nupkg --source https://api.nuget.org/v3/index.json --skip-duplicate --api-key ${{ secrets.NUGET_KEY }} --no-symbols
dotnet nuget push ./src/linker.messenger.relay/bin/release/linker.messenger.relay.{{version}}.nupkg --source https://api.nuget.org/v3/index.json --skip-duplicate --api-key ${{ secrets.NUGET_KEY }} --no-symbols

View File

@@ -18,4 +18,9 @@ slug: /question
3. `Windows 无法验证此文件的数字签名`大概率出现再win7/8可以尝试安装<a href="https://www.microsoft.com/zh-cn/download/details.aspx?id=46148" target="_blank">KB3033929 全球化补丁</a>
4. `group id are empty` 客户端尚未初始化
5. `rtsp`关于rtsp默认使用UDP协议传输音视频在rtsp握手的SETUP阶段报告客户端UDP端口所以在经过NAT后服务端无法正确向客户端发送数据请使用TCP
6. 在windows如果1802-1804端口被占用但是`netstat -ano` 又查不到那可能是hyper-v占用的可以尝试重启winnat服务解决
```
net stop winnat
net start winnat
```
:::

View File

@@ -1,4 +1,5 @@
using linker.libs.web;
using linker.messenger.node;
using linker.messenger.relay.client;
using linker.messenger.relay.messenger;
using linker.messenger.relay.server;
@@ -61,7 +62,7 @@ namespace linker.messenger.relay
serviceCollection.AddSingleton<RelayServerReportResolver>();
serviceCollection.AddSingleton<RelayServerResolver>();
serviceCollection.AddSingleton<RelayServerConnectionResolver>();
serviceCollection.AddSingleton<NodeConnectionResolver>();
serviceCollection.AddSingleton<RelayServerConnectionTransfer>();
serviceCollection.AddSingleton<IRelayServerCaching, RelayServerCachingMemory>();
@@ -84,7 +85,7 @@ namespace linker.messenger.relay
{
serviceProvider.GetService<RelayServerReportResolver>(),
serviceProvider.GetService<RelayServerResolver>(),
serviceProvider.GetService<RelayServerConnectionResolver>(),
serviceProvider.GetService<NodeConnectionResolver>(),
});
RelayServerNodeTransfer relayServerNodeTransfer = serviceProvider.GetService<RelayServerNodeTransfer>();

View File

@@ -38,6 +38,7 @@
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="9.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\linker.messenger.node\linker.messenger.node.csproj" />
<ProjectReference Include="..\linker.libs\linker.libs.csproj" />
<ProjectReference Include="..\linker.messenger.signin\linker.messenger.signin.csproj" />
<ProjectReference Include="..\linker.messenger.sync\linker.messenger.sync.csproj" />

View File

@@ -1,45 +1,11 @@
using linker.libs.extends;
using linker.messenger.node;
using linker.tunnel.connection;
using System.Net;
using System.Text.Json.Serialization;
namespace linker.messenger.relay.server
{
public interface IRelayServerConfigStore
{
public int ServicePort { get; }
/// <summary>
/// 节点信息
/// </summary>
public RelayServerConfigInfo Config { get; }
/// <summary>
/// 设置
/// </summary>
/// <param name="config"></param>
public void SetInfo(RelayServerConfigInfo config);
/// <summary>
/// 设置月份
/// </summary>
/// <param name="month"></param>
public void SetDataMonth(int month);
/// <summary>
/// 设置剩余流量
/// </summary>
/// <param name="value"></param>
public void SetDataRemain(long value);
public void SetShareKey(string shareKey);
public void SetMasterKey(string masterKey);
/// <summary>
/// 提交保存
/// </summary>
public void Confirm();
}
public class RelayServerNodeInfo
{
private string nodeId = Guid.NewGuid().ToString().ToUpper();
@@ -60,7 +26,7 @@ namespace linker.messenger.relay.server
public string Logo { get; set; } = "https://linker.snltty.com/img/logo.png";
}
public sealed class RelayServerConfigInfo : RelayServerNodeInfo
public sealed class RelayServerConfigInfo : RelayServerNodeInfo, INodeConfigBase
{
[SaveJsonIgnore]
public DistributedInfoOld Distributed { get; set; } = new DistributedInfoOld { };
@@ -68,21 +34,21 @@ namespace linker.messenger.relay.server
public string ShareKey { get; set; } = string.Empty;
public string MasterKey { get; set; } = string.Empty;
public int DataMonth { get; set; }
}
public class RelayServerNodeReportInfo : RelayServerNodeInfo
public class RelayServerNodeReportInfo : RelayServerNodeInfo,INodeReportBase
{
public string MasterKey { get; set; } = string.Empty;
public string Version { get; set; } = string.Empty;
public int ConnectionsRatio { get; set; }
public double BandwidthRatio { get; set; }
public IPEndPoint[] Masters { get; set; } = Array.Empty<IPEndPoint>();
public int MasterCount { get; set; }
}
public sealed class RelayServerNodeStoreInfo : RelayServerNodeReportInfo
public sealed class RelayServerNodeStoreInfo : RelayServerNodeReportInfo,INodeStoreBase
{
public int Id { get; set; }
@@ -97,17 +63,6 @@ namespace linker.messenger.relay.server
public string ShareKey { get; set; } = string.Empty;
}
public class RelayServerNodeShareInfo
{
public string NodeId { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public string Host { get; set; } = string.Empty;
public string SystemId { get; set; } = string.Empty;
}
public sealed class DistributedInfoOld
{
public RelayServerNodeInfoOld Node { get; set; } = new RelayServerNodeInfoOld { };
@@ -116,7 +71,7 @@ namespace linker.messenger.relay.server
{
public string Id { get; set; }
public string Name{ get; set; }
public string Name { get; set; }
public string Host { get; set; } = string.Empty;
public int MaxConnection { get; set; }

View File

@@ -1,14 +0,0 @@
namespace linker.messenger.relay.server
{
public interface IRelayServerNodeStore
{
public Task<List<RelayServerNodeStoreInfo>> GetAll();
public Task<RelayServerNodeStoreInfo> GetByNodeId(string nodeId);
public Task<bool> Add(RelayServerNodeStoreInfo info);
public Task<bool> Report(RelayServerNodeReportInfo info);
public Task<bool> Delete(string nodeId);
public Task<bool> Update(RelayServerNodeStoreInfo info);
}
}

View File

@@ -1,44 +1,25 @@
namespace linker.messenger.relay.server
using linker.messenger.node;
namespace linker.messenger.relay.server
{
/// <summary>
/// 白名单接口
/// </summary>
public interface IRelayServerWhiteListStore
public interface IRelayServerWhiteListStore : INodeWhiteListStore
{
/// <summary>
/// 获取白名单
/// </summary>
/// <param name="userid"></param>
/// <param name="machineid"></param>
/// <returns></returns>
public Task<List<RelayWhiteListItem>> GetNodes(string userid, string machineid);
/// <summary>
/// 获取白名单
/// </summary>
/// <param name="userid"></param>
/// <param name="fromMachineId"></param>
/// <param name="toMachineId"></param>
/// <param name="nodeid"></param>
/// <returns></returns>
public Task<List<double>> GetBandwidth(string userid, string fromMachineId,string toMachineId, string nodeid);
}
public sealed class RelayServerWhiteListStore : IRelayServerWhiteListStore
{
public async Task<List<RelayWhiteListItem>> GetNodes(string userid, string machineid)
public string TypeName => "Relay";
public async Task<List<NodeWhiteListInfo>> GetNodes(string userid, string machineid)
{
return await Task.FromResult(new List<RelayWhiteListItem>());
return await Task.FromResult(new List<NodeWhiteListInfo>());
}
public async Task<List<double>> GetBandwidth(string userid, string fromMachineId, string toMachineId, string nodeid)
{
return await Task.FromResult(new List<double>());
}
}
public sealed class RelayWhiteListItem
{
public string[] Nodes { get; set; } = [];
public double Bandwidth { get; set; } = 0;
}
}

View File

@@ -1,45 +0,0 @@
using linker.libs;
using linker.libs.extends;
using System.Buffers;
using System.Net;
using System.Net.Sockets;
namespace linker.messenger.relay.server
{
public class RelayServerConnectionResolver : IResolver
{
public byte Type => (byte)ResolverType.RelayConnection;
private readonly IMessengerResolver messengerResolver;
public RelayServerConnectionResolver(IMessengerResolver messengerResolver)
{
this.messengerResolver = messengerResolver;
}
public virtual void Add(long receiveBytes, long sendtBytes)
{
}
public async Task Resolve(Socket socket, Memory<byte> memory)
{
try
{
await messengerResolver.BeginReceiveServer(socket, Helper.EmptyArray).ConfigureAwait(false);
}
catch (Exception ex)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Error(ex);
}
socket.SafeClose();
}
}
public async Task Resolve(Socket socket, IPEndPoint ep, Memory<byte> memory)
{
await Task.CompletedTask.ConfigureAwait(false);
}
}
}

View File

@@ -1,41 +1,8 @@
using System.Collections.Concurrent;
using linker.messenger.node;
namespace linker.messenger.relay.server
{
public sealed class RelayServerConnectionTransfer
public sealed class RelayServerConnectionTransfer : NodeConnectionTransfer
{
private readonly ConcurrentDictionary<string, IConnection>[] connections = [
new ConcurrentDictionary<string, IConnection>()
,new ConcurrentDictionary<string, IConnection>()
];
public RelayServerConnectionTransfer()
{
}
public List<IConnection> Get(ConnectionSideType type)
{
return connections[(byte)type].Values.Where(c => c.Connected).ToList();
}
public bool TryGet(ConnectionSideType type, string id, out IConnection connection)
{
return connections[(byte)type].TryGetValue(id, out connection);
}
public bool TryAdd(ConnectionSideType type, string id, IConnection connection)
{
if (connections[(byte)type].TryRemove(id, out IConnection _connection) && _connection.GetHashCode() != connection.GetHashCode())
{
_connection.Disponse();
}
return connections[(byte)type].TryAdd(id, connection);
}
}
public enum ConnectionSideType : byte
{
Node = 0,
Master = 1
}
}

View File

@@ -1,4 +1,5 @@

using linker.messenger.node;
using linker.messenger.signin;
namespace linker.messenger.relay.server
@@ -59,18 +60,4 @@ namespace linker.messenger.relay.server
}
}
public sealed partial class RelayCacheInfo
{
public ulong FlowId { get; set; }
public string FromId { get; set; }
public string FromName { get; set; }
public string ToId { get; set; }
public string ToName { get; set; }
public string GroupId { get; set; }
public bool Super { get; set; }
public double Bandwidth { get; set; }
public string UserId { get; set; } = string.Empty;
}
}

View File

@@ -1,177 +1,35 @@
using linker.libs;
using linker.libs.extends;
using linker.libs.timer;
using linker.messenger.node;
using linker.messenger.relay.messenger;
using System.Net;
using System.Net.Sockets;
namespace linker.messenger.relay.server
{
public sealed class RelayServerNodeReportTransfer
public sealed class RelayServerNodeReportTransfer : NodeReportTransfer<RelayServerConfigInfo, RelayServerNodeStoreInfo, RelayServerNodeReportInfo>
{
public RelayServerConfigInfo Config => relayServerConfigStore.Config;
public override ushort MessengerIdSahre => (ushort)RelayMessengerIds.Share;
public override ushort MessengerIdUpdateForward => (ushort)RelayMessengerIds.UpdateForward;
public override ushort MessengerIdUpgradeForward => (ushort)RelayMessengerIds.UpgradeForward;
public override ushort MessengerIdExitForward => (ushort)RelayMessengerIds.ExitForward;
public override ushort MessengerIdReport => (ushort)RelayMessengerIds.Report;
public override ushort MessengerIdSignIn => (ushort)RelayMessengerIds.SignIn;
private int connectionNum = 0;
private ulong bytes = 0;
private ulong lastBytes = 0;
private string md5 = string.Empty;
private readonly ICrypto crypto = CryptoFactory.CreateSymmetric(Helper.GlobalString);
public int ConnectionNum => connectionNum;
private readonly RelayServerConnectionTransfer relayServerConnectionTransfer;
private readonly IRelayServerConfigStore relayServerConfigStore;
private readonly ISerializer serializer;
private readonly IMessengerSender messengerSender;
private readonly IRelayServerNodeStore relayServerNodeStore;
private readonly IRelayServerWhiteListStore relayServerWhiteListStore;
private readonly IMessengerResolver messengerResolver;
private readonly INodeConfigStore<RelayServerConfigInfo> nodeConfigStore;
private readonly INodeStore<RelayServerNodeStoreInfo, RelayServerNodeReportInfo> nodeStore;
public RelayServerNodeReportTransfer(RelayServerConnectionTransfer relayServerConnectionTransfer, IRelayServerConfigStore relayServerConfigStore,
ISerializer serializer, IMessengerSender messengerSender, IRelayServerNodeStore relayServerNodeStore,
IRelayServerWhiteListStore relayServerWhiteListStore, IMessengerResolver messengerResolver, ICommonStore commonStore)
public RelayServerNodeReportTransfer(IRelayServerWhiteListStore relayServerWhiteListStore, RelayServerConnectionTransfer nodeConnectionTransfer,
INodeConfigStore<RelayServerConfigInfo> nodeConfigStore,
ISerializer serializer, IMessengerSender messengerSender, INodeStore<RelayServerNodeStoreInfo, RelayServerNodeReportInfo> nodeStore,
IMessengerResolver messengerResolver, ICommonStore commonStore)
: base(nodeConnectionTransfer, nodeConfigStore, serializer, messengerSender, nodeStore, messengerResolver, commonStore)
{
this.relayServerConnectionTransfer = relayServerConnectionTransfer;
this.relayServerConfigStore = relayServerConfigStore;
this.serializer = serializer;
this.messengerSender = messengerSender;
this.relayServerNodeStore = relayServerNodeStore;
this.relayServerWhiteListStore = relayServerWhiteListStore;
this.messengerResolver = messengerResolver;
md5 = Config.NodeId.Md5();
if (commonStore.Modes.HasFlag(CommonModes.Server))
{
_ = ReportTask();
SignInTask();
}
this.nodeConfigStore = nodeConfigStore;
this.nodeStore = nodeStore;
}
public void IncrementConnectionNum()
{
Interlocked.Increment(ref connectionNum);
}
public void DecrementConnectionNum()
{
Interlocked.Decrement(ref connectionNum);
}
public void AddBytes(long length)
{
Interlocked.Add(ref bytes, (ulong)length);
}
public async Task<bool> Report(string id, string name, string host)
{
return await relayServerNodeStore.Add(new RelayServerNodeStoreInfo
{
NodeId = id,
Name = name,
Host = host
}).ConfigureAwait(false);
}
public async Task<bool> Report(RelayServerNodeReportInfo info)
{
if (relayServerConnectionTransfer.TryGet(ConnectionSideType.Node, info.NodeId, out _) == false) return false;
return await relayServerNodeStore.Report(info).ConfigureAwait(false);
}
public async Task<bool> SignIn(string serverId, string shareKey, IConnection connection)
{
//未被配置,或默认配置的,设它为管理端
if (string.IsNullOrWhiteSpace(Config.MasterKey) || md5 == Config.MasterKey)
{
relayServerConfigStore.SetMasterKey(serverId.Md5());
relayServerConfigStore.Confirm();
}
if (shareKey != Config.ShareKey && serverId.Md5() != Config.MasterKey)
{
return false;
}
connection.Id = serverId;
relayServerConnectionTransfer.TryAdd(ConnectionSideType.Master, connection.Id, connection);
return true;
}
public async Task<string> GetShareKeyForward(string nodeId)
{
RelayServerNodeStoreInfo store = await relayServerNodeStore.GetByNodeId(nodeId);
if (store != null && store.Manageable && relayServerConnectionTransfer.TryGet(ConnectionSideType.Node, nodeId, out var connection))
{
var resp = await messengerSender.SendReply(new MessageRequestWrap
{
Connection = connection,
MessengerId = (ushort)RelayMessengerIds.Share,
Payload = serializer.Serialize(store.MasterKey)
});
if (resp.Code == MessageResponeCodes.OK)
{
return serializer.Deserialize<string>(resp.Data.Span);
}
}
return string.Empty;
}
public async Task<string> GetShareKey(string masterKey)
{
if (masterKey != Config.MasterKey) return string.Empty;
return Config.ShareKey;
}
public async Task<string> Import(string shareKey)
{
try
{
RelayServerNodeShareInfo info = serializer.Deserialize<RelayServerNodeShareInfo>(crypto.Decode(Convert.FromBase64String(shareKey)).Span);
bool result = await relayServerNodeStore.Add(new RelayServerNodeStoreInfo
{
NodeId = info.NodeId,
Host = info.Host,
Name = info.Name,
LastTicks = Environment.TickCount64,
ShareKey = shareKey
}).ConfigureAwait(false);
if (result == false)
{
return "node already exists";
}
}
catch (Exception ex)
{
return ex.Message;
}
return string.Empty;
}
public async Task<bool> Remove(string nodeId)
{
if (nodeId == Config.NodeId) return false;
return await relayServerNodeStore.Delete(nodeId).ConfigureAwait(false);
}
public async Task<bool> UpdateForward(RelayServerNodeStoreInfo info)
{
RelayServerNodeStoreInfo store = await relayServerNodeStore.GetByNodeId(info.NodeId);
if (store != null && store.Manageable && relayServerConnectionTransfer.TryGet(ConnectionSideType.Node, info.NodeId, out var connection))
{
info.MasterKey = store.MasterKey;
await messengerSender.SendOnly(new MessageRequestWrap
{
Connection = connection,
MessengerId = (ushort)RelayMessengerIds.Update,
Payload = serializer.Serialize(info)
});
}
return await relayServerNodeStore.Update(info).ConfigureAwait(false);
}
public async Task<bool> Update(RelayServerNodeStoreInfo info)
public override async Task<bool> Update(RelayServerNodeStoreInfo info)
{
if (info.MasterKey != Config.MasterKey) return false;
@@ -185,70 +43,24 @@ namespace linker.messenger.relay.server
Config.Url = info.Url;
Config.Host = info.Host.Split(':')[0];
relayServerConfigStore.Confirm();
nodeConfigStore.Confirm();
return true;
}
public async Task<bool> UpgradeForward(string nodeId, string version)
protected override void BuildReport(RelayServerNodeReportInfo info)
{
RelayServerNodeStoreInfo store = await relayServerNodeStore.GetByNodeId(nodeId);
if (store != null && store.Manageable && relayServerConnectionTransfer.TryGet(ConnectionSideType.Node, nodeId, out var connection))
{
await messengerSender.SendOnly(new MessageRequestWrap
{
Connection = connection,
MessengerId = (ushort)RelayMessengerIds.Update,
Payload = serializer.Serialize(new KeyValuePair<string, string>(store.MasterKey, version))
});
return true;
}
return false;
}
public async Task<bool> Upgrade(string masterKey, string version)
{
if (masterKey != Config.MasterKey) return false;
Helper.AppUpdate(version);
return true;
}
public async Task<bool> ExitForward(string nodeId)
{
RelayServerNodeStoreInfo store = await relayServerNodeStore.GetByNodeId(nodeId);
if (store != null && store.Manageable && relayServerConnectionTransfer.TryGet(ConnectionSideType.Node, nodeId, out var connection))
{
await messengerSender.SendOnly(new MessageRequestWrap
{
Connection = connection,
MessengerId = (ushort)RelayMessengerIds.Update,
Payload = serializer.Serialize(new KeyValuePair<string, string>(store.MasterKey, nodeId))
});
return true;
}
return false;
}
public async Task<bool> Exit(string masterKey)
{
if (masterKey != Config.MasterKey) return false;
Helper.AppExit(-1);
return true;
}
public async Task<List<RelayServerNodeStoreInfo>> GetNodes(bool validated, string userid, string machineId)
public override async Task<List<RelayServerNodeStoreInfo>> GetNodes(bool super, string userid, string machineId)
{
var nodes = (await relayServerWhiteListStore.GetNodes(userid, machineId)).Where(c => c.Bandwidth >= 0).SelectMany(c => c.Nodes);
var result = (await relayServerNodeStore.GetAll())
.Where(c => validated || Environment.TickCount64 - c.LastTicks < 15000)
var result = (await nodeStore.GetAll())
.Where(c => super || Environment.TickCount64 - c.LastTicks < 15000)
.Where(c =>
{
return validated || nodes.Contains(c.NodeId) || nodes.Contains("*")
return super || nodes.Contains(c.NodeId) || nodes.Contains("*")
|| (c.Public && c.ConnectionsRatio < c.Connections && (c.DataEachMonth == 0 || (c.DataEachMonth > 0 && c.DataRemain > 0)));
})
.OrderByDescending(c => c.LastTicks);
@@ -269,9 +81,11 @@ namespace linker.messenger.relay.server
});
return list;
}
public async Task<List<RelayServerNodeStoreInfo>> GetPublicNodes()
{
var result = (await relayServerNodeStore.GetAll())
var result = (await nodeStore.GetAll())
.Where(c => Environment.TickCount64 - c.LastTicks < 15000)
.Where(c => c.Public)
.OrderByDescending(c => c.LastTicks);
@@ -292,151 +106,5 @@ namespace linker.messenger.relay.server
return list;
}
private async Task BuildShareKey()
{
try
{
string host = Config.Host;
if (string.IsNullOrWhiteSpace(host))
{
using HttpClient httpClient = new HttpClient();
host = await httpClient.GetStringAsync($"https://ifconfig.me/ip").WaitAsync(TimeSpan.FromMilliseconds(5000)).ConfigureAwait(false);
}
RelayServerNodeShareInfo shareKeyInfo = new RelayServerNodeShareInfo
{
NodeId = Config.NodeId,
Host = $"{host}:{relayServerConfigStore.ServicePort}",
Name = Config.Name,
SystemId = SystemIdHelper.GetSystemId().Md5()
};
string shareKey = Convert.ToBase64String(crypto.Encode(serializer.Serialize(shareKeyInfo)));
relayServerConfigStore.SetShareKey(shareKey);
relayServerConfigStore.Confirm();
host = $"{IPAddress.Loopback}:{relayServerConfigStore.ServicePort}";
var node = await relayServerNodeStore.GetByNodeId(relayServerConfigStore.Config.NodeId);
if (node == null || node.ShareKey != shareKey || node.Name != Config.Name || node.Host != host)
{
await relayServerNodeStore.Delete(relayServerConfigStore.Config.NodeId);
await relayServerNodeStore.Add(new RelayServerNodeStoreInfo
{
NodeId = relayServerConfigStore.Config.NodeId,
Name = "default",
Host = $"{IPAddress.Loopback}:{relayServerConfigStore.ServicePort}",
ShareKey = shareKey
}).ConfigureAwait(false);
}
LoggerHelper.Instance.Warning($"build relay share key : {shareKey}");
}
catch (Exception ex)
{
LoggerHelper.Instance.Error($"build relay share key error : {ex}");
}
}
private async Task ReportTask()
{
await BuildShareKey().ConfigureAwait(false);
TimerHelper.SetIntervalLong(async () =>
{
try
{
var connections = relayServerConnectionTransfer.Get(ConnectionSideType.Master);
if (connections.Any())
{
double diff = (bytes - lastBytes) * 8 / 1024.0 / 1024.0;
lastBytes = bytes;
var config = relayServerConfigStore.Config;
RelayServerNodeReportInfo info = new RelayServerNodeReportInfo
{
Bandwidth = config.Bandwidth,
Connections = config.Connections,
DataEachMonth = config.DataEachMonth,
DataRemain = config.DataRemain,
Logo = config.Logo,
Name = config.Name,
NodeId = config.NodeId,
Protocol = config.Protocol,
Url = config.Url,
ConnectionsRatio = connectionNum,
BandwidthRatio = Math.Round(diff / 5, 2),
Version = VersionHelper.Version,
Masters = connections.Select(c => c.Address).ToArray(),
MasterKey = config.MasterKey,
};
byte[] memory = serializer.Serialize(info);
var tasks = connections.Select(c => messengerSender.SendOnly(new MessageRequestWrap
{
Connection = c,
MessengerId = (ushort)RelayMessengerIds.Report,
Payload = memory,
Timeout = 5000
})).ToList();
await Task.WhenAll(tasks).ConfigureAwait(false);
}
}
catch (Exception ex)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Error($"relay report : {ex}");
}
}
}, 5000);
}
private void SignInTask()
{
TimerHelper.SetIntervalLong(async () =>
{
try
{
var nodes = (await relayServerNodeStore.GetAll()).Where(c =>
{
return relayServerConnectionTransfer.TryGet(ConnectionSideType.Node, c.NodeId, out IConnection connection) == false || connection == null || connection.Connected == false;
}).ToList();
if (nodes.Count != 0)
{
var tasks = nodes.Select(async c =>
{
IPEndPoint remote = await NetworkHelper.GetEndPointAsync(c.Host, 1802).ConfigureAwait(false);
Socket socket = new Socket(remote.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.KeepAlive();
await socket.ConnectAsync(remote).WaitAsync(TimeSpan.FromMilliseconds(5000)).ConfigureAwait(false);
var connection = await messengerResolver.BeginReceiveClient(socket, true, (byte)ResolverType.RelayConnection, Helper.EmptyArray).ConfigureAwait(false);
var resp = await messengerSender.SendReply(new MessageRequestWrap
{
Connection = connection,
MessengerId = (ushort)RelayMessengerIds.SignIn,
Payload = serializer.Serialize(new KeyValuePair<string, string>(Config.NodeId, c.ShareKey)),
Timeout = 5000
}).ConfigureAwait(false);
if (resp.Code == MessageResponeCodes.OK && resp.Data.Span.SequenceEqual(Helper.TrueArray))
{
LoggerHelper.Instance.Debug($"relay sign in to node {c.NodeId} success");
relayServerConnectionTransfer.TryAdd(ConnectionSideType.Node, c.NodeId, connection);
}
else
{
connection.Disponse();
}
});
await Task.WhenAll(tasks).ConfigureAwait(false);
}
}
catch (Exception ex)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Error($"relay sign in : {ex}");
}
}
}, 10000);
}
}
}

View File

@@ -1,41 +1,31 @@
using linker.libs;
using linker.libs.timer;
using linker.messenger.node;
using linker.messenger.relay.messenger;
using linker.tunnel.connection;
using linker.tunnel.transport;
using System.Collections.Concurrent;
namespace linker.messenger.relay.server
{
/// <summary>
/// 中继节点操作
/// </summary>
public class RelayServerNodeTransfer
public class RelayServerNodeTransfer : NodeTransfer<RelayServerConfigInfo, RelayServerNodeStoreInfo, RelayServerNodeReportInfo>
{
private RelayServerConfigInfo Config => relayServerNodeReportTransfer.Config;
private readonly RelaySpeedLimit limitTotal = new RelaySpeedLimit();
private readonly ConcurrentDictionary<ulong, RelayTrafficCacheInfo> trafficDict = new();
private readonly ISerializer serializer;
private readonly IMessengerSender messengerSender;
private readonly IRelayServerConfigStore relayServerConfigStore;
private readonly RelayServerConnectionTransfer relayServerConnectionTransfer;
private readonly RelayServerNodeReportTransfer relayServerNodeReportTransfer;
public RelayServerNodeTransfer(ISerializer serializer, IMessengerSender messengerSender,
IRelayServerConfigStore relayServerConfigStore, RelayServerConnectionTransfer relayServerConnectionTransfer, RelayServerNodeReportTransfer relayServerNodeReportTransfer)
public RelayServerNodeTransfer(ISerializer serializer, IMessengerSender messengerSender, RelayServerConnectionTransfer relayServerConnectionTransfer,
ICommonStore commonStore, INodeConfigStore<RelayServerConfigInfo> nodeConfigStore,
RelayServerNodeReportTransfer relayServerNodeReportTransfer)
: base(commonStore, nodeConfigStore, relayServerNodeReportTransfer)
{
this.serializer = serializer;
this.relayServerConfigStore = relayServerConfigStore;
this.messengerSender = messengerSender;
this.relayServerConnectionTransfer = relayServerConnectionTransfer;
this.relayServerNodeReportTransfer = relayServerNodeReportTransfer;
limitTotal.SetLimit((uint)Math.Ceiling((Config.Bandwidth * 1024 * 1024) / 8.0));
TrafficTask();
}
public async Task<RelayCacheInfo> TryGetRelayCache(RelayMessageInfo relayMessage)
@@ -109,129 +99,5 @@ namespace linker.messenger.relay.server
return res;
}
/// <summary>
/// 增加连接数
/// </summary>
public void IncrementConnectionNum()
{
relayServerNodeReportTransfer.IncrementConnectionNum();
}
/// <summary>
/// 减少连接数
/// </summary>
public void DecrementConnectionNum()
{
relayServerNodeReportTransfer.DecrementConnectionNum();
}
/// <summary>
/// 是否需要总限速
/// </summary>
/// <returns></returns>
public bool NeedLimit(RelayTrafficCacheInfo relayCache)
{
return limitTotal.NeedLimit();
}
/// <summary>
/// 总限速
/// </summary>
/// <param name="length"></param>
/// <returns></returns>
public bool TryLimit(ref int length)
{
return limitTotal.TryLimit(ref length);
}
/// <summary>
/// 总限速
/// </summary>
/// <param name="length"></param>
/// <returns></returns>
public bool TryLimitPacket(int length)
{
return limitTotal.TryLimitPacket(length);
}
/// <summary>
/// 开始计算流量
/// </summary>
/// <param name="relayCache"></param>
public void AddTrafficCache(RelayTrafficCacheInfo relayCache)
{
SetLimit(relayCache);
trafficDict.TryAdd(relayCache.Cache.FlowId, relayCache);
}
/// <summary>
/// 取消计算流量
/// </summary>
/// <param name="relayCache"></param>
public void RemoveTrafficCache(RelayTrafficCacheInfo relayCache)
{
trafficDict.TryRemove(relayCache.Cache.FlowId, out _);
}
/// <summary>
/// 消耗流量
/// </summary>
/// <param name="length"></param>
/// <returns></returns>
public bool AddBytes(RelayTrafficCacheInfo cache, long length)
{
relayServerNodeReportTransfer.AddBytes(length);
if (Config.DataEachMonth == 0) return true;
Interlocked.Add(ref cache.Sendt, length);
return Config.DataRemain > 0;
}
/// <summary>
/// 设置限速
/// </summary>
/// <param name="relayCache"></param>
private void SetLimit(RelayTrafficCacheInfo cache)
{
if (cache.Cache.Bandwidth >= 0)
{
cache.Limit.SetLimit((uint)Math.Ceiling(cache.Cache.Bandwidth * 1024 * 1024 / 8.0));
return;
}
cache.Limit.SetLimit((uint)Math.Ceiling(Config.Bandwidth * 1024 * 1024 / 8.0));
}
private void ResetNodeBytes()
{
if (Config.DataEachMonth == 0) return;
foreach (var cache in trafficDict.Values)
{
long length = Interlocked.Exchange(ref cache.Sendt, 0);
if (Config.DataRemain >= length)
relayServerConfigStore.SetDataRemain(Config.DataRemain - length);
else relayServerConfigStore.SetDataRemain(0);
}
if (Config.DataMonth != DateTime.Now.Month)
{
relayServerConfigStore.SetDataMonth(DateTime.Now.Month);
relayServerConfigStore.SetDataRemain((long)(Config.DataEachMonth * 1024 * 1024 * 1024));
}
relayServerConfigStore.Confirm();
}
private void TrafficTask()
{
TimerHelper.SetIntervalLong(() =>
{
try
{
ResetNodeBytes();
}
catch (Exception ex)
{
LoggerHelper.Instance.Error(ex);
}
}, 3000);
}
}
}

View File

@@ -1,10 +1,11 @@
using System.Net.Sockets;
using linker.libs;
using linker.libs.extends;
using linker.messenger.node;
using linker.tunnel.transport;
using System.Buffers;
using System.Collections.Concurrent;
using System.Net;
using linker.libs;
using System.Buffers;
using linker.tunnel.transport;
using System.Net.Sockets;
namespace linker.messenger.relay.server
{
@@ -139,7 +140,7 @@ namespace linker.messenger.relay.server
LoggerHelper.Instance.Info($"relay server start {fromep} to {toep}");
string flowKey = relayMessage.Type == RelayMessengerType.Ask ? $"{relayMessage.FromId}->{relayMessage.ToId}" : $"{relayMessage.ToId}->{relayMessage.FromId}";
RelayTrafficCacheInfo trafficCacheInfo = new RelayTrafficCacheInfo { Cache = relayCache, Sendt = 0, Limit = new RelaySpeedLimit(), Key = flowKey };
RelayTrafficCacheInfo trafficCacheInfo = new RelayTrafficCacheInfo { Cache = relayCache, Sendt = 0, Limit = new SpeedLimit(), Key = flowKey };
relayServerNodeTransfer.AddTrafficCache(trafficCacheInfo);
relayServerNodeTransfer.IncrementConnectionNum();
await Task.WhenAll(CopyToAsync(trafficCacheInfo, socket, answerSocket), CopyToAsync(trafficCacheInfo, answerSocket, socket)).ConfigureAwait(false);
@@ -226,85 +227,18 @@ namespace linker.messenger.relay.server
Ask = 0,
Answer = 1,
}
public class RelaySpeedLimit
public sealed partial class RelayCacheInfo : CacheInfo
{
private uint relayLimit = 0;
private double relayLimitToken = 0;
private double relayLimitBucket = 0;
private long relayLimitTicks = Environment.TickCount64;
public string FromId { get; set; }
public string FromName { get; set; }
public string ToId { get; set; }
public string ToName { get; set; }
public string GroupId { get; set; }
public bool NeedLimit()
{
return relayLimit > 0;
}
public void SetLimit(uint bytes)
{
//每s多少字节
relayLimit = bytes;
//每ms多少字节
relayLimitToken = relayLimit / 1000.0;
//桶里有多少字节
relayLimitBucket = relayLimit;
}
public bool TryLimit(ref int length)
{
//0不限速
if (relayLimit == 0) return true;
lock (this)
{
long _relayLimitTicks = Environment.TickCount64;
//距离上次经过了多少ms
long relayLimitTicksTemp = _relayLimitTicks - relayLimitTicks;
relayLimitTicks = _relayLimitTicks;
//桶里增加多少字节
relayLimitBucket += relayLimitTicksTemp * relayLimitToken;
//桶溢出了
if (relayLimitBucket > relayLimit) relayLimitBucket = relayLimit;
//能全部消耗调
if (relayLimitBucket >= length)
{
relayLimitBucket -= length;
length = 0;
}
else
{
//只能消耗一部分
length -= (int)relayLimitBucket;
relayLimitBucket = 0;
}
}
return true;
}
public bool TryLimitPacket(int length)
{
if (relayLimit == 0) return true;
lock (this)
{
long _relayLimitTicks = Environment.TickCount64;
long relayLimitTicksTemp = _relayLimitTicks - relayLimitTicks;
relayLimitTicks = _relayLimitTicks;
relayLimitBucket += relayLimitTicksTemp * relayLimitToken;
if (relayLimitBucket > relayLimit) relayLimitBucket = relayLimit;
if (relayLimitBucket >= length)
{
relayLimitBucket -= length;
return true;
}
}
return false;
}
public string UserId { get; set; } = string.Empty;
}
public sealed class RelayTrafficCacheInfo
public sealed class RelayTrafficCacheInfo: TrafficCacheInfo
{
public long Sendt;
public long SendtCache;
public RelaySpeedLimit Limit { get; set; }
public RelayCacheInfo Cache { get; set; }
public string Key { get; set; }
public new RelayCacheInfo Cache { get; set; }
}
}

View File

@@ -61,12 +61,14 @@ namespace linker.messenger.serializer.memorypack
MemoryPackFormatterProvider.Register(new UpdaterSyncInfoFormatter());
MemoryPackFormatterProvider.Register(new NodeShareInfoFormatter());
MemoryPackFormatterProvider.Register(new RelayAskResultInfoFormatter());
MemoryPackFormatterProvider.Register(new RelayCacheInfoFormatter());
MemoryPackFormatterProvider.Register(new RelayMessageInfoFormatter());
MemoryPackFormatterProvider.Register(new RelayServerNodeReportInfoFormatter());
MemoryPackFormatterProvider.Register(new RelayServerNodeStoreInfoFormatter());
MemoryPackFormatterProvider.Register(new RelayServerNodeShareInfoFormatter());
MemoryPackFormatterProvider.Register(new RelayServerNodeReportInfoFormatterOld());
@@ -90,7 +92,6 @@ namespace linker.messenger.serializer.memorypack
MemoryPackFormatterProvider.Register(new SForwardProxyInfoFormatter());
MemoryPackFormatterProvider.Register(new SForwardServerNodeReportInfoFormatter());
MemoryPackFormatterProvider.Register(new SForwardServerNodeStoreInfoFormatter());
MemoryPackFormatterProvider.Register(new SForwardServerNodeShareInfoFormatter());
MemoryPackFormatterProvider.Register(new SForwardServerNodeReportInfoOldFormatter());

View File

@@ -0,0 +1,73 @@
using linker.messenger.node;
using MemoryPack;
namespace linker.messenger.serializer.memorypack
{
[MemoryPackable]
public readonly partial struct SerializableNodeShareInfo
{
[MemoryPackIgnore]
public readonly NodeShareInfo info;
[MemoryPackInclude]
string NodeId => info.NodeId;
[MemoryPackInclude]
string Name => info.Name;
[MemoryPackInclude]
string Host => info.Host;
[MemoryPackInclude]
string SystemId => info.SystemId;
[MemoryPackConstructor]
SerializableNodeShareInfo(string nodeId, string name, string host, string systemid)
{
var info = new NodeShareInfo
{
NodeId = nodeId,
Host = host,
Name = name,
SystemId = systemid
};
this.info = info;
}
public SerializableNodeShareInfo(NodeShareInfo info)
{
this.info = info;
}
}
public class NodeShareInfoFormatter : MemoryPackFormatter<NodeShareInfo>
{
public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref NodeShareInfo value)
{
if (value == null)
{
writer.WriteNullObjectHeader();
return;
}
writer.WritePackable(new SerializableNodeShareInfo(value));
}
public override void Deserialize(ref MemoryPackReader reader, scoped ref NodeShareInfo value)
{
if (reader.PeekIsNull())
{
reader.Advance(1); // skip null block
value = null;
return;
}
value = new NodeShareInfo();
reader.TryReadObjectHeader(out byte count);
value.NodeId = reader.ReadValue<string>();
value.Name = reader.ReadValue<string>();
value.Host = reader.ReadValue<string>();
value.SystemId = reader.ReadValue<string>();
}
}
}

View File

@@ -252,12 +252,12 @@ namespace linker.messenger.serializer.memorypack
[MemoryPackInclude]
double BandwidthRatio => info.BandwidthRatio;
[MemoryPackInclude]
IPEndPoint[] Masters => info.Masters;
int MasterCount => info.MasterCount;
[MemoryPackConstructor]
SerializableRelayServerNodeReportInfo(string nodeId, string name, string host, TunnelProtocolType protocol, int connections, int bandwidth, int dataEachMonth,
long dataRemain, string url, string logo, string masterKey, string version, int connectionsRatio, double bandwidthRatio, IPEndPoint[] masters)
long dataRemain, string url, string logo, string masterKey, string version, int connectionsRatio, double bandwidthRatio, int masterCount)
{
var info = new RelayServerNodeReportInfo
{
@@ -274,7 +274,7 @@ namespace linker.messenger.serializer.memorypack
Version = version,
ConnectionsRatio = connectionsRatio,
BandwidthRatio = bandwidthRatio,
Masters = masters,
MasterCount = masterCount,
Host = host
};
this.info = info;
@@ -323,8 +323,8 @@ namespace linker.messenger.serializer.memorypack
value.Version = reader.ReadValue<string>();
value.ConnectionsRatio = reader.ReadValue<int>();
value.BandwidthRatio = reader.ReadValue<double>();
value.Masters = reader.ReadValue<IPEndPoint[]>();
value.MasterCount = reader.ReadValue<int>();
}
}
@@ -365,7 +365,7 @@ namespace linker.messenger.serializer.memorypack
[MemoryPackInclude]
double BandwidthRatio => info.BandwidthRatio;
[MemoryPackInclude]
IPEndPoint[] Masters => info.Masters;
int MasterCount => info.MasterCount;
[MemoryPackInclude]
@@ -381,9 +381,9 @@ namespace linker.messenger.serializer.memorypack
bool Manageable => info.Manageable;
[MemoryPackConstructor]
SerializableRelayServerNodeStoreInfo(string nodeId, string name,string host, TunnelProtocolType protocol, int connections, int bandwidth, int dataEachMonth,
long dataRemain, string url, string logo, string masterKey, string version, int connectionsRatio, double bandwidthRatio, IPEndPoint[] masters,
int id, int bandwidthEachConnection, bool Public, long lastTicks, bool manageable)
SerializableRelayServerNodeStoreInfo(string nodeId, string name, string host, TunnelProtocolType protocol, int connections, int bandwidth, int dataEachMonth,
long dataRemain, string url, string logo, string masterKey, string version, int connectionsRatio, double bandwidthRatio, int masterCount,
int id, int bandwidthEachConnection, bool Public, long lastTicks, bool manageable)
{
var info = new RelayServerNodeStoreInfo
{
@@ -400,7 +400,7 @@ namespace linker.messenger.serializer.memorypack
Version = version,
ConnectionsRatio = connectionsRatio,
BandwidthRatio = bandwidthRatio,
Masters = masters,
MasterCount = masterCount,
Id = id,
Host = host,
BandwidthEach = bandwidthEachConnection,
@@ -454,9 +454,9 @@ namespace linker.messenger.serializer.memorypack
value.Version = reader.ReadValue<string>();
value.ConnectionsRatio = reader.ReadValue<int>();
value.BandwidthRatio = reader.ReadValue<double>();
value.Masters = reader.ReadValue<IPEndPoint[]>();
value.MasterCount = reader.ReadValue<int>();
value.Id = reader.ReadValue<int>();
value.BandwidthEach = reader.ReadValue<int>();
value.Public = reader.ReadValue<bool>();
value.LastTicks = reader.ReadValue<long>();
@@ -465,72 +465,6 @@ namespace linker.messenger.serializer.memorypack
}
[MemoryPackable]
public readonly partial struct SerializableRelayServerNodeShareInfo
{
[MemoryPackIgnore]
public readonly RelayServerNodeShareInfo info;
[MemoryPackInclude]
string NodeId => info.NodeId;
[MemoryPackInclude]
string Name => info.Name;
[MemoryPackInclude]
string Host => info.Host;
[MemoryPackInclude]
string SystemId => info.SystemId;
[MemoryPackConstructor]
SerializableRelayServerNodeShareInfo(string nodeId, string name, string host, string systemid)
{
var info = new RelayServerNodeShareInfo
{
NodeId = nodeId,
Host = host,
Name = name,
SystemId = systemid
};
this.info = info;
}
public SerializableRelayServerNodeShareInfo(RelayServerNodeShareInfo info)
{
this.info = info;
}
}
public class RelayServerNodeShareInfoFormatter : MemoryPackFormatter<RelayServerNodeShareInfo>
{
public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref RelayServerNodeShareInfo value)
{
if (value == null)
{
writer.WriteNullObjectHeader();
return;
}
writer.WritePackable(new SerializableRelayServerNodeShareInfo(value));
}
public override void Deserialize(ref MemoryPackReader reader, scoped ref RelayServerNodeShareInfo value)
{
if (reader.PeekIsNull())
{
reader.Advance(1); // skip null block
value = null;
return;
}
value = new RelayServerNodeShareInfo();
reader.TryReadObjectHeader(out byte count);
value.NodeId = reader.ReadValue<string>();
value.Name = reader.ReadValue<string>();
value.Host = reader.ReadValue<string>();
value.SystemId = reader.ReadValue<string>();
}
}
[MemoryPackable]
public readonly partial struct SerializableRelayServerNodeReportInfoOld
{

View File

@@ -503,12 +503,12 @@ namespace linker.messenger.serializer.memorypack
[MemoryPackInclude]
double BandwidthRatio => info.BandwidthRatio;
[MemoryPackInclude]
IPEndPoint[] Masters => info.Masters;
int MasterCount => info.MasterCount;
[MemoryPackConstructor]
SerializableSForwardServerNodeReportInfo(string nodeId, string name, string host, string domain, int webport, string tunnelports, int connections, int bandwidth, int dataEachMonth,
long dataRemain, string url, string logo, string masterKey, string version, int connectionsRatio, double bandwidthRatio, IPEndPoint[] masters)
long dataRemain, string url, string logo, string masterKey, string version, int connectionsRatio, double bandwidthRatio,int masterCount)
{
var info = new SForwardServerNodeReportInfo
{
@@ -528,7 +528,7 @@ namespace linker.messenger.serializer.memorypack
Version = version,
ConnectionsRatio = connectionsRatio,
BandwidthRatio = bandwidthRatio,
Masters = masters,
MasterCount = masterCount,
};
this.info = info;
@@ -579,7 +579,7 @@ namespace linker.messenger.serializer.memorypack
value.Version = reader.ReadValue<string>();
value.ConnectionsRatio = reader.ReadValue<int>();
value.BandwidthRatio = reader.ReadValue<double>();
value.Masters = reader.ReadValue<IPEndPoint[]>();
value.MasterCount = reader.ReadValue<int>();
}
}
@@ -625,7 +625,7 @@ namespace linker.messenger.serializer.memorypack
[MemoryPackInclude]
double BandwidthRatio => info.BandwidthRatio;
[MemoryPackInclude]
IPEndPoint[] Masters => info.Masters;
int MasterCount => info.MasterCount;
[MemoryPackInclude]
@@ -642,7 +642,7 @@ namespace linker.messenger.serializer.memorypack
[MemoryPackConstructor]
SerializableSForwardServerNodeStoreInfo(string nodeId, string name, string host, string domain, int webport, string tunnelports, int connections, int bandwidth, int dataEachMonth,
long dataRemain, string url, string logo, string masterKey, string version, int connectionsRatio, double bandwidthRatio, IPEndPoint[] masters,
long dataRemain, string url, string logo, string masterKey, string version, int connectionsRatio, double bandwidthRatio,int masterCount,
int id, int bandwidthEachConnection, bool Public, long lastTicks, bool manageable)
{
var info = new SForwardServerNodeStoreInfo
@@ -663,7 +663,7 @@ namespace linker.messenger.serializer.memorypack
Version = version,
ConnectionsRatio = connectionsRatio,
BandwidthRatio = bandwidthRatio,
Masters = masters,
MasterCount = masterCount,
Id = id,
BandwidthEach = bandwidthEachConnection,
@@ -719,7 +719,7 @@ namespace linker.messenger.serializer.memorypack
value.Version = reader.ReadValue<string>();
value.ConnectionsRatio = reader.ReadValue<int>();
value.BandwidthRatio = reader.ReadValue<double>();
value.Masters = reader.ReadValue<IPEndPoint[]>();
value.MasterCount = reader.ReadValue<int>();
value.Id = reader.ReadValue<int>();
value.BandwidthEach = reader.ReadValue<int>();
@@ -730,71 +730,6 @@ namespace linker.messenger.serializer.memorypack
}
[MemoryPackable]
public readonly partial struct SerializableSForwardServerNodeShareInfo
{
[MemoryPackIgnore]
public readonly SForwardServerNodeShareInfo info;
[MemoryPackInclude]
string NodeId => info.NodeId;
[MemoryPackInclude]
string Name => info.Name;
[MemoryPackInclude]
string Host => info.Host;
[MemoryPackInclude]
string SystemId => info.SystemId;
[MemoryPackConstructor]
SerializableSForwardServerNodeShareInfo(string nodeId, string name, string host, string systemid)
{
var info = new SForwardServerNodeShareInfo
{
NodeId = nodeId,
Host = host,
Name = name,
SystemId = systemid
};
this.info = info;
}
public SerializableSForwardServerNodeShareInfo(SForwardServerNodeShareInfo info)
{
this.info = info;
}
}
public class SForwardServerNodeShareInfoFormatter : MemoryPackFormatter<SForwardServerNodeShareInfo>
{
public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref SForwardServerNodeShareInfo value)
{
if (value == null)
{
writer.WriteNullObjectHeader();
return;
}
writer.WritePackable(new SerializableSForwardServerNodeShareInfo(value));
}
public override void Deserialize(ref MemoryPackReader reader, scoped ref SForwardServerNodeShareInfo value)
{
if (reader.PeekIsNull())
{
reader.Advance(1); // skip null block
value = null;
return;
}
value = new SForwardServerNodeShareInfo();
reader.TryReadObjectHeader(out byte count);
value.NodeId = reader.ReadValue<string>();
value.Name = reader.ReadValue<string>();
value.Host = reader.ReadValue<string>();
value.SystemId = reader.ReadValue<string>();
}
}
[MemoryPackable]
public readonly partial struct SerializableSForwardServerNodeReportInfoOld

View File

@@ -1,5 +1,6 @@
using linker.libs;
using linker.libs.web;
using linker.messenger.node;
using linker.messenger.plan;
using linker.messenger.sforward.client;
using linker.messenger.sforward.messenger;
@@ -32,7 +33,7 @@ namespace linker.messenger.sforward
linker.messenger.api.IWebServer apiServer = serviceProvider.GetService<linker.messenger.api.IWebServer>();
apiServer.AddPlugins(new List<IApiController> { serviceProvider.GetService<SForwardApiController>() });
SForwardClientTransfer sForwardClientTransfer = serviceProvider.GetService<SForwardClientTransfer>();
SForwardClientTransfer sforwardClientTransfer = serviceProvider.GetService<SForwardClientTransfer>();
IMessengerResolver messengerResolver = serviceProvider.GetService<IMessengerResolver>();
messengerResolver.AddMessenger(new List<IMessenger> { serviceProvider.GetService<SForwardClientMessenger>() });
@@ -60,7 +61,7 @@ namespace linker.messenger.sforward
serviceCollection.AddSingleton<SForwardServerNodeTransfer>();
serviceCollection.AddSingleton<SForwardServerReportResolver>();
serviceCollection.AddSingleton<SForwardServerConnectionResolver>();
serviceCollection.AddSingleton<NodeConnectionResolver>();
serviceCollection.AddSingleton<SForwardServerConnectionTransfer>();
serviceCollection.AddSingleton<SForwardServerNodeReportTransfer>();
@@ -74,25 +75,25 @@ namespace linker.messenger.sforward
IMessengerResolver messengerResolver = serviceProvider.GetService<IMessengerResolver>();
messengerResolver.AddMessenger(new List<IMessenger> { serviceProvider.GetService<SForwardServerMessenger>() });
SForwardValidatorTransfer sForwardValidatorTransfer = serviceProvider.GetService<SForwardValidatorTransfer>();
sForwardValidatorTransfer.AddValidators(new List<ISForwardValidator> { serviceProvider.GetService<SForwardValidator>() });
SForwardValidatorTransfer sforwardValidatorTransfer = serviceProvider.GetService<SForwardValidatorTransfer>();
sforwardValidatorTransfer.AddValidators(new List<ISForwardValidator> { serviceProvider.GetService<SForwardValidator>() });
ResolverTransfer resolverTransfer = serviceProvider.GetService<ResolverTransfer>();
resolverTransfer.AddResolvers(new List<IResolver>
{
serviceProvider.GetService<SForwardServerReportResolver>(),
serviceProvider.GetService<SForwardServerConnectionResolver>(),
serviceProvider.GetService<NodeConnectionResolver>(),
});
SForwardServerNodeTransfer relayServerNodeTransfer = serviceProvider.GetService<SForwardServerNodeTransfer>();
SForwardServerMasterTransfer relayServerMasterTransfer = serviceProvider.GetService<SForwardServerMasterTransfer>();
serviceProvider.GetService<SForwardServerNodeTransfer>();
serviceProvider.GetService<SForwardServerMasterTransfer>();
SForwardProxy sForwardProxy = serviceProvider.GetService<SForwardProxy>();
ISForwardServerConfigStore sForwardServerStore = serviceProvider.GetService<ISForwardServerConfigStore>();
if (sForwardServerStore.Config.WebPort > 0)
INodeConfigStore<SForwardServerConfigInfo> sforwardServerStore = serviceProvider.GetService<INodeConfigStore<SForwardServerConfigInfo>>();
if (sforwardServerStore.Config.WebPort > 0)
{
sForwardProxy.StartHttp(sForwardServerStore.Config.WebPort, 3 );
LoggerHelper.Instance.Debug($"start web forward in {sForwardServerStore.Config.WebPort}");
sForwardProxy.StartHttp(sforwardServerStore.Config.WebPort, 3 );
LoggerHelper.Instance.Debug($"start web forward in {sforwardServerStore.Config.WebPort}");
}
return serviceProvider;

View File

@@ -36,6 +36,7 @@
<DebugType>embedded</DebugType>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\linker.messenger.node\linker.messenger.node.csproj" />
<ProjectReference Include="..\linker.libs\linker.libs.csproj" />
<ProjectReference Include="..\linker.messenger.decenter\linker.messenger.decenter.csproj" />
<ProjectReference Include="..\linker.messenger.plan\linker.messenger.plan.csproj" />

View File

@@ -26,12 +26,11 @@ namespace linker.messenger.sforward.messenger
private readonly SForwardServerMasterTransfer sForwardServerMasterTransfer;
private readonly SForwardServerNodeTransfer sForwardServerNodeTransfer;
private readonly SForwardServerNodeReportTransfer sForwardServerNodeReportTransfer;
private readonly SForwardServerConnectionTransfer sForwardServerConnectionTransfer;
public SForwardServerMessenger(SForwardProxy proxy, ISForwardServerCahing sForwardServerCahing, IMessengerSender sender,
SignInServerCaching signCaching, SForwardValidatorTransfer validator, ISerializer serializer,
SForwardServerMasterTransfer sForwardServerMasterTransfer, SForwardServerNodeTransfer sForwardServerNodeTransfer,
SForwardServerNodeReportTransfer sForwardServerNodeReportTransfer, SForwardServerConnectionTransfer sForwardServerConnectionTransfer)
SForwardServerNodeReportTransfer sForwardServerNodeReportTransfer)
{
this.proxy = proxy;
proxy.WebConnect = WebConnect;
@@ -45,7 +44,6 @@ namespace linker.messenger.sforward.messenger
this.sForwardServerMasterTransfer = sForwardServerMasterTransfer;
this.sForwardServerNodeTransfer = sForwardServerNodeTransfer;
this.sForwardServerNodeReportTransfer = sForwardServerNodeReportTransfer;
this.sForwardServerConnectionTransfer = sForwardServerConnectionTransfer;
ClearTask();

View File

@@ -1,4 +1,5 @@
using linker.libs;
using linker.messenger.node;
using linker.messenger.sforward.server;
using System.Text;
namespace linker.plugins.sforward.proxy
@@ -9,10 +10,10 @@ namespace linker.plugins.sforward.proxy
private readonly NumberSpace ns = new NumberSpace(65537);
private byte[] flagBytes = Encoding.UTF8.GetBytes($"{Helper.GlobalString}.sforward");
private readonly SForwardServerNodeTransfer sForwardServerNodeTransfer;
public SForwardProxy(SForwardServerNodeTransfer sForwardServerNodeTransfer)
private readonly SForwardServerNodeTransfer sforwardServerNodeTransfer;
public SForwardProxy(SForwardServerNodeTransfer sforwardServerNodeTransfer)
{
this.sForwardServerNodeTransfer = sForwardServerNodeTransfer;
this.sforwardServerNodeTransfer = sforwardServerNodeTransfer;
UdpTask();
}
@@ -25,7 +26,7 @@ namespace linker.plugins.sforward.proxy
{
try
{
SForwardTrafficCacheInfo sForwardTrafficCacheInfo = sForwardServerNodeTransfer.AddTrafficCache(super, bandwidth);
TrafficCacheInfo sForwardTrafficCacheInfo = sforwardServerNodeTransfer.AddTrafficCache(super, bandwidth);
StartTcp(port, false, bufferSize, groupid, sForwardTrafficCacheInfo);
StartUdp(port, bufferSize, groupid, sForwardTrafficCacheInfo);
return string.Empty;

View File

@@ -1,6 +1,6 @@
using linker.libs;
using linker.libs.extends;
using linker.messenger.sforward.server;
using linker.messenger.node;
using System.Buffers;
using System.Collections.Concurrent;
using System.Net;
@@ -14,7 +14,7 @@ namespace linker.plugins.sforward.proxy
private readonly ConcurrentDictionary<int, AsyncUserToken> tcpListens = new ConcurrentDictionary<int, AsyncUserToken>();
private readonly ConcurrentDictionary<ulong, TaskCompletionSource<Socket>> tcpConnections = new ConcurrentDictionary<ulong, TaskCompletionSource<Socket>>();
private readonly ConcurrentDictionary<ulong, AsyncUserToken> httpConnections = new ConcurrentDictionary<ulong, AsyncUserToken>();
private readonly ConcurrentDictionary<string, SForwardTrafficCacheInfo> httpCaches = new ConcurrentDictionary<string, SForwardTrafficCacheInfo>();
private readonly ConcurrentDictionary<string,TrafficCacheInfo> httpCaches = new ConcurrentDictionary<string, TrafficCacheInfo>();
public Func<int, ulong, Task<string>> TunnelConnect { get; set; } = async (port, id) => { return await Task.FromResult(string.Empty).ConfigureAwait(false); };
public Func<string, int, ulong, Task<string>> WebConnect { get; set; } = async (host, port, id) => { return await Task.FromResult(string.Empty).ConfigureAwait(false); };
@@ -22,7 +22,7 @@ namespace linker.plugins.sforward.proxy
#region
private void StartTcp(int port, bool isweb, byte bufferSize, string groupid, SForwardTrafficCacheInfo cache)
private void StartTcp(int port, bool isweb, byte bufferSize, string groupid, TrafficCacheInfo cache)
{
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, port);
Socket socket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
@@ -127,7 +127,7 @@ namespace linker.plugins.sforward.proxy
}
string key = token.ListenPort.ToString();
SForwardTrafficCacheInfo cache = token.Cache;
TrafficCacheInfo cache = token.Cache;
//是web的去获取host请求头匹配不同的服务
if (token.IsWeb)
{
@@ -209,7 +209,7 @@ namespace linker.plugins.sforward.proxy
{
if (userToken.Cache != null)
{
sForwardServerNodeTransfer.RemoveTrafficCache(userToken.Cache.Cache.FlowId);
sforwardServerNodeTransfer.RemoveTrafficCache(userToken.Cache.Cache.FlowId);
}
CloseClientSocket(userToken);
}
@@ -248,21 +248,21 @@ namespace linker.plugins.sforward.proxy
{
if (host.Contains('.') == false)
{
host = $"{host}.{sForwardServerNodeTransfer.Config.Domain}";
host = $"{host}.{sforwardServerNodeTransfer.Config.Domain}";
}
SForwardTrafficCacheInfo sForwardTrafficCacheInfo = sForwardServerNodeTransfer.AddTrafficCache(super, bandwidth);
TrafficCacheInfo sForwardTrafficCacheInfo = sforwardServerNodeTransfer.AddTrafficCache(super, bandwidth);
httpCaches.AddOrUpdate(host, sForwardTrafficCacheInfo, (a, b) => sForwardTrafficCacheInfo);
}
public void RemoveHttp(string host)
{
if (host.Contains('.') == false)
{
host = $"{host}.{sForwardServerNodeTransfer.Config.Domain}";
host = $"{host}.{sforwardServerNodeTransfer.Config.Domain}";
}
if (httpCaches.TryRemove(host, out var cache))
{
sForwardServerNodeTransfer.RemoveTrafficCache(cache.Cache.FlowId);
sforwardServerNodeTransfer.RemoveTrafficCache(cache.Cache.FlowId);
}
foreach (var item in httpConnections.Where(c => c.Value.Host == host).Select(c => c.Key).ToList())
{
@@ -347,7 +347,7 @@ namespace linker.plugins.sforward.proxy
/// <param name="source"></param>
/// <param name="target"></param>
/// <returns></returns>
private async Task CopyToAsync(string key, string groupid, Memory<byte> buffer, Socket source, Socket target, SForwardTrafficCacheInfo trafficCacheInfo = null)
private async Task CopyToAsync(string key, string groupid, Memory<byte> buffer, Socket source, Socket target,TrafficCacheInfo trafficCacheInfo = null)
{
try
{
@@ -357,21 +357,21 @@ namespace linker.plugins.sforward.proxy
if (trafficCacheInfo != null)
{
//流量限制
if (sForwardServerNodeTransfer.AddBytes(trafficCacheInfo, bytesRead) == false)
if (sforwardServerNodeTransfer.AddBytes(trafficCacheInfo, bytesRead) == false)
{
source.SafeClose();
break;
}
//总速度
if (sForwardServerNodeTransfer.NeedLimit(trafficCacheInfo))
if (sforwardServerNodeTransfer.NeedLimit(trafficCacheInfo))
{
int length = bytesRead;
sForwardServerNodeTransfer.TryLimit(ref length);
sforwardServerNodeTransfer.TryLimit(ref length);
while (length > 0)
{
await Task.Delay(30).ConfigureAwait(false);
sForwardServerNodeTransfer.TryLimit(ref length);
sforwardServerNodeTransfer.TryLimit(ref length);
}
}
//单个速度
@@ -417,7 +417,7 @@ namespace linker.plugins.sforward.proxy
public byte BufferSize { get; set; }
public SForwardTrafficCacheInfo Cache { get; set; }
public TrafficCacheInfo Cache { get; set; }
public void Clear()
{

View File

@@ -1,6 +1,7 @@
using linker.libs;
using linker.libs.extends;
using linker.libs.timer;
using linker.messenger.node;
using linker.messenger.sforward.server;
using System.Buffers;
using System.Collections.Concurrent;
@@ -25,7 +26,7 @@ namespace linker.plugins.sforward.proxy
#region
private void StartUdp(int port, byte bufferSize, string groupid, SForwardTrafficCacheInfo cache)
private void StartUdp(int port, byte bufferSize, string groupid, TrafficCacheInfo cache)
{
Socket socketUdp = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socketUdp.Bind(new IPEndPoint(IPAddress.Any, port));
@@ -74,12 +75,12 @@ namespace linker.plugins.sforward.proxy
if (token.Cache != null)
{
//流量限制
if (sForwardServerNodeTransfer.AddBytes(token.Cache, bytesRead) == false)
if (sforwardServerNodeTransfer.AddBytes(token.Cache, bytesRead) == false)
{
continue;
}
//总速度
if (sForwardServerNodeTransfer.NeedLimit(token.Cache) && sForwardServerNodeTransfer.TryLimitPacket(bytesRead) == false)
if (sforwardServerNodeTransfer.NeedLimit(token.Cache) && sforwardServerNodeTransfer.TryLimitPacket(bytesRead) == false)
{
continue;
}
@@ -334,7 +335,7 @@ namespace linker.plugins.sforward.proxy
public string GroupId { get; set; }
public Socket SourceSocket { get; set; }
public SForwardTrafficCacheInfo Cache { get; set; }
public TrafficCacheInfo Cache { get; set; }
public void Clear()
{

View File

@@ -1,47 +1,10 @@
using linker.libs.extends;
using linker.messenger.node;
using System.Net;
using System.Text.Json.Serialization;
namespace linker.messenger.sforward.server
{
public interface ISForwardServerConfigStore
{
public int ServicePort { get; }
/// <summary>
/// 节点信息
/// </summary>
public SForwardServerConfigInfo Config { get; }
/// <summary>
/// 设置
/// </summary>
/// <param name="config"></param>
public void SetInfo(SForwardServerConfigInfo config);
/// <summary>
/// 设置月份
/// </summary>
/// <param name="month"></param>
public void SetDataMonth(int month);
/// <summary>
/// 设置剩余流量
/// </summary>
/// <param name="value"></param>
public void SetDataRemain(long value);
public void SetShareKey(string shareKey);
public void SetMasterKey(string masterKey);
/// <summary>
/// 提交保存
/// </summary>
public void Confirm();
}
public class SForwardServerNodeInfo
{
private string nodeId = Guid.NewGuid().ToString().ToUpper();
@@ -64,7 +27,7 @@ namespace linker.messenger.sforward.server
public string Logo { get; set; } = "https://linker.snltty.com/img/logo.png";
}
public sealed class SForwardServerConfigInfo : SForwardServerNodeInfo
public sealed class SForwardServerConfigInfo : SForwardServerNodeInfo,INodeConfigBase
{
[SaveJsonIgnore]
public DistributedInfoOld Distributed { get; set; } = new DistributedInfoOld { };
@@ -73,22 +36,21 @@ namespace linker.messenger.sforward.server
public string MasterKey { get; set; } = string.Empty;
public int DataMonth { get; set; }
public string Host { get; set; } = string.Empty;
}
public class SForwardServerNodeReportInfo : SForwardServerNodeInfo
public class SForwardServerNodeReportInfo : SForwardServerNodeInfo,INodeReportBase
{
public string MasterKey { get; set; } = string.Empty;
public string Version { get; set; } = string.Empty;
public int ConnectionsRatio { get; set; }
public double BandwidthRatio { get; set; }
public IPEndPoint[] Masters { get; set; } = Array.Empty<IPEndPoint>();
public int MasterCount { get; set; }
public string Host { get; set; } = string.Empty;
}
public sealed class SForwardServerNodeStoreInfo : SForwardServerNodeReportInfo
public sealed class SForwardServerNodeStoreInfo : SForwardServerNodeReportInfo,INodeStoreBase
{
public int Id { get; set; }
@@ -103,18 +65,6 @@ namespace linker.messenger.sforward.server
public string ShareKey { get; set; } = string.Empty;
}
public class SForwardServerNodeShareInfo
{
public string NodeId { get; set; } = string.Empty;
public string Host { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public string SystemId { get; set; } = string.Empty;
}
public sealed class DistributedInfoOld
{
public SForwardServerNodeInfoOld Node { get; set; } = new SForwardServerNodeInfoOld { };
@@ -133,8 +83,6 @@ namespace linker.messenger.sforward.server
public int MaxGbTotalMonth { get; set; }
public string Url { get; set; } = "https://linker-doc.snltty.com";
}
public partial class SForwardServerNodeReportInfoOld
{
public string Id { get; set; } = string.Empty;

View File

@@ -1,12 +0,0 @@
namespace linker.messenger.sforward.server
{
public interface ISForwardServerNodeStore
{
public Task<List<SForwardServerNodeStoreInfo>> GetAll();
public Task<SForwardServerNodeStoreInfo> GetByNodeId(string nodeId);
public Task<bool> Add(SForwardServerNodeStoreInfo info);
public Task<bool> Report(SForwardServerNodeReportInfo info);
public Task<bool> Delete(string nodeId);
public Task<bool> Update(SForwardServerNodeStoreInfo info);
}
}

View File

@@ -1,29 +1,25 @@
namespace linker.messenger.sforward.server
using linker.messenger.node;
namespace linker.messenger.sforward.server
{
/// <summary>
/// 白名单接口
/// </summary>
public interface ISForwardServerWhiteListStore
public interface ISForwardServerWhiteListStore : INodeWhiteListStore
{
/// <summary>
/// 获取白名单
/// </summary>
/// <param name="userid"></param>
/// <returns></returns>
public Task<List<SForwardWhiteListItem>> GetNodes(string userid, string machineid);
}
public sealed class SForwardServerWhiteListStore : ISForwardServerWhiteListStore
{
public async Task<List<SForwardWhiteListItem>> GetNodes(string userid, string machineid)
public string TypeName => "SForward";
public async Task<List<NodeWhiteListInfo>> GetNodes(string userid, string machineid)
{
return await Task.FromResult(new List<SForwardWhiteListItem>());
return await Task.FromResult(new List<NodeWhiteListInfo>());
}
public async Task<List<double>> GetBandwidth(string userid, string fromMachineId, string toMachineId, string nodeid)
{
return await Task.FromResult(new List<double>());
}
}
public sealed class SForwardWhiteListItem
{
public string[] Nodes { get; set; } = [];
public double Bandwidth { get; set; } = 0;
}
}

View File

@@ -1,41 +1,8 @@
using System.Collections.Concurrent;
using linker.messenger.node;
namespace linker.messenger.sforward.server
{
public sealed class SForwardServerConnectionTransfer
public sealed class SForwardServerConnectionTransfer: NodeConnectionTransfer
{
private readonly ConcurrentDictionary<string, IConnection>[] connections = [
new ConcurrentDictionary<string, IConnection>()
,new ConcurrentDictionary<string, IConnection>()
];
public SForwardServerConnectionTransfer()
{
}
public List<IConnection> Get(ConnectionSideType type)
{
return connections[(byte)type].Values.Where(c => c.Connected).ToList();
}
public bool TryGet(ConnectionSideType type, string id, out IConnection connection)
{
return connections[(byte)type].TryGetValue(id, out connection);
}
public bool TryAdd(ConnectionSideType type, string id, IConnection connection)
{
if (connections[(byte)type].TryRemove(id, out IConnection _connection) && _connection.GetHashCode() != connection.GetHashCode())
{
_connection.Disponse();
}
return connections[(byte)type].TryAdd(id, connection);
}
}
public enum ConnectionSideType : byte
{
Node = 0,
Master = 1
}
}

View File

@@ -1,5 +1,6 @@
using linker.libs;
using linker.libs.extends;
using linker.messenger.node;
using linker.messenger.sforward.messenger;
using linker.messenger.signin;
@@ -13,18 +14,16 @@ namespace linker.messenger.sforward.server
private readonly ISerializer serializer;
private readonly IMessengerSender messengerSender;
private readonly ISForwardServerWhiteListStore sForwardServerWhiteListStore;
private readonly ISForwardServerNodeStore sForwardServerNodeStore;
private readonly SForwardServerConnectionTransfer sForwardServerConnectionTransfer;
private readonly SForwardServerNodeReportTransfer sForwardServerNodeReportTransfer;
public SForwardServerMasterTransfer(ISerializer serializer, IMessengerSender messengerSender, ISForwardServerWhiteListStore sForwardServerWhiteListStore,
ISForwardServerNodeStore sForwardServerNodeStore, SForwardServerConnectionTransfer sForwardServerConnectionTransfer, SForwardServerNodeReportTransfer sForwardServerNodeReportTransfer)
SForwardServerConnectionTransfer sForwardServerConnectionTransfer, SForwardServerNodeReportTransfer sForwardServerNodeReportTransfer)
{
this.serializer = serializer;
this.messengerSender = messengerSender;
this.sForwardServerWhiteListStore = sForwardServerWhiteListStore;
this.sForwardServerNodeStore = sForwardServerNodeStore;
this.sForwardServerConnectionTransfer = sForwardServerConnectionTransfer;
this.sForwardServerNodeReportTransfer = sForwardServerNodeReportTransfer;
}
@@ -50,7 +49,7 @@ namespace linker.messenger.sforward.server
};
}
List<SForwardWhiteListItem> sforward = await sForwardServerWhiteListStore.GetNodes(from.UserId, from.MachineId);
List<NodeWhiteListInfo> sforward = await sForwardServerWhiteListStore.GetNodes(from.UserId, from.MachineId);
string target = string.IsNullOrWhiteSpace(info.Domain) ? info.RemotePort.ToString() : info.Domain;
info.Super = from.Super;

View File

@@ -1,176 +1,35 @@
using linker.libs;
using linker.libs.extends;
using linker.libs.timer;
using linker.messenger.node;
using linker.messenger.sforward.messenger;
using System.Net;
using System.Net.Sockets;
namespace linker.messenger.sforward.server
{
public sealed class SForwardServerNodeReportTransfer
public sealed class SForwardServerNodeReportTransfer : NodeReportTransfer<SForwardServerConfigInfo, SForwardServerNodeStoreInfo, SForwardServerNodeReportInfo>
{
public SForwardServerConfigInfo Config => sForwardServerConfigStore.Config;
public override ushort MessengerIdSahre => (ushort)SForwardMessengerIds.Share;
public override ushort MessengerIdUpdateForward => (ushort)SForwardMessengerIds.UpdateForward;
public override ushort MessengerIdUpgradeForward => (ushort)SForwardMessengerIds.UpgradeForward;
public override ushort MessengerIdExitForward => (ushort)SForwardMessengerIds.ExitForward;
public override ushort MessengerIdReport => (ushort)SForwardMessengerIds.Report;
public override ushort MessengerIdSignIn => (ushort)SForwardMessengerIds.SignIn;
private int connectionNum = 0;
private ulong bytes = 0;
private ulong lastBytes = 0;
private string md5 = string.Empty;
private readonly ISForwardServerWhiteListStore sforwardServerWhiteListStore;
private readonly INodeConfigStore<SForwardServerConfigInfo> nodeConfigStore;
private readonly INodeStore<SForwardServerNodeStoreInfo, SForwardServerNodeReportInfo> nodeStore;
private readonly ICrypto crypto = CryptoFactory.CreateSymmetric(Helper.GlobalString);
public int ConnectionNum => connectionNum;
private readonly SForwardServerConnectionTransfer sForwardServerConnectionTransfer;
private readonly ISForwardServerConfigStore sForwardServerConfigStore;
private readonly ISerializer serializer;
private readonly IMessengerSender messengerSender;
private readonly ISForwardServerNodeStore sForwardServerNodeStore;
private readonly ISForwardServerWhiteListStore sForwardServerWhiteListStore;
private readonly IMessengerResolver messengerResolver;
public SForwardServerNodeReportTransfer(SForwardServerConnectionTransfer SForwardServerConnectionTransfer, ISForwardServerConfigStore SForwardServerConfigStore,
ISerializer serializer, IMessengerSender messengerSender, ISForwardServerNodeStore sForwardServerNodeStore,
ISForwardServerWhiteListStore sForwardServerWhiteListStore, IMessengerResolver messengerResolver, ICommonStore commonStore)
public SForwardServerNodeReportTransfer(ISForwardServerWhiteListStore sforwardServerWhiteListStore, SForwardServerConnectionTransfer nodeConnectionTransfer,
INodeConfigStore<SForwardServerConfigInfo> nodeConfigStore,
ISerializer serializer, IMessengerSender messengerSender, INodeStore<SForwardServerNodeStoreInfo, SForwardServerNodeReportInfo> nodeStore,
IMessengerResolver messengerResolver, ICommonStore commonStore)
: base(nodeConnectionTransfer, nodeConfigStore, serializer, messengerSender, nodeStore, messengerResolver, commonStore)
{
this.sForwardServerConnectionTransfer = SForwardServerConnectionTransfer;
this.sForwardServerConfigStore = SForwardServerConfigStore;
this.serializer = serializer;
this.messengerSender = messengerSender;
this.sForwardServerNodeStore = sForwardServerNodeStore;
this.sForwardServerWhiteListStore = sForwardServerWhiteListStore;
this.messengerResolver = messengerResolver;
md5 = Config.NodeId.Md5();
if (commonStore.Modes.HasFlag(CommonModes.Server))
{
_ = ReportTask();
SignInTask();
}
this.sforwardServerWhiteListStore = sforwardServerWhiteListStore;
this.nodeConfigStore = nodeConfigStore;
this.nodeStore = nodeStore;
}
public void IncrementConnectionNum()
{
Interlocked.Increment(ref connectionNum);
}
public void DecrementConnectionNum()
{
Interlocked.Decrement(ref connectionNum);
}
public void AddBytes(long length)
{
Interlocked.Add(ref bytes, (ulong)length);
}
public async Task<bool> Report(string id, string name, string host)
{
return await sForwardServerNodeStore.Add(new SForwardServerNodeStoreInfo
{
NodeId = id,
Name = name,
Host = host
}).ConfigureAwait(false);
}
public async Task<bool> Report(SForwardServerNodeReportInfo info)
{
if (sForwardServerConnectionTransfer.TryGet(ConnectionSideType.Node, info.NodeId, out _) == false) return false;
return await sForwardServerNodeStore.Report(info).ConfigureAwait(false);
}
public async Task<bool> SignIn(string serverId, string shareKey, IConnection connection)
{
//未被配置,或默认配置的,设它为管理端
if (string.IsNullOrWhiteSpace(Config.MasterKey) || md5 == Config.MasterKey)
{
sForwardServerConfigStore.SetMasterKey(serverId.Md5());
sForwardServerConfigStore.Confirm();
}
if (shareKey != Config.ShareKey && serverId.Md5() != Config.MasterKey)
{
return false;
}
connection.Id = serverId;
sForwardServerConnectionTransfer.TryAdd(ConnectionSideType.Master, connection.Id, connection);
return true;
}
public async Task<string> GetShareKeyForward(string nodeId)
{
SForwardServerNodeStoreInfo store = await sForwardServerNodeStore.GetByNodeId(nodeId);
if (store != null && store.Manageable && sForwardServerConnectionTransfer.TryGet(ConnectionSideType.Node, nodeId, out var connection))
{
var resp = await messengerSender.SendReply(new MessageRequestWrap
{
Connection = connection,
MessengerId = (ushort)SForwardMessengerIds.Share,
Payload = serializer.Serialize(store.MasterKey)
});
if (resp.Code == MessageResponeCodes.OK)
{
return serializer.Deserialize<string>(resp.Data.Span);
}
}
return string.Empty;
}
public async Task<string> GetShareKey(string masterKey)
{
if (masterKey != Config.MasterKey) return string.Empty;
return Config.ShareKey;
}
public async Task<string> Import(string shareKey)
{
try
{
SForwardServerNodeShareInfo info = serializer.Deserialize<SForwardServerNodeShareInfo>(crypto.Decode(Convert.FromBase64String(shareKey)).Span);
bool result = await sForwardServerNodeStore.Add(new SForwardServerNodeStoreInfo
{
NodeId = info.NodeId,
Host = info.Host,
Name = info.Name,
LastTicks = Environment.TickCount64,
ShareKey = shareKey
}).ConfigureAwait(false);
if (result == false)
{
return "node already exists";
}
}
catch (Exception ex)
{
return ex.Message;
}
return string.Empty;
}
public async Task<bool> Remove(string nodeId)
{
if (nodeId == Config.NodeId) return false;
return await sForwardServerNodeStore.Delete(nodeId).ConfigureAwait(false);
}
public async Task<bool> UpdateForward(SForwardServerNodeStoreInfo info)
{
SForwardServerNodeStoreInfo store = await sForwardServerNodeStore.GetByNodeId(info.NodeId);
if (store != null && store.Manageable && sForwardServerConnectionTransfer.TryGet(ConnectionSideType.Node, info.NodeId, out var connection))
{
info.MasterKey = store.MasterKey;
await messengerSender.SendOnly(new MessageRequestWrap
{
Connection = connection,
MessengerId = (ushort)SForwardMessengerIds.Update,
Payload = serializer.Serialize(info)
});
}
return await sForwardServerNodeStore.Update(info).ConfigureAwait(false);
}
public async Task<bool> Update(SForwardServerNodeStoreInfo info)
public override async Task<bool> Update(SForwardServerNodeStoreInfo info)
{
if (info.MasterKey != Config.MasterKey) return false;
@@ -183,60 +42,18 @@ namespace linker.messenger.sforward.server
Config.Url = info.Url;
Config.Host = info.Host.Split(':')[0];
Config.Domain = info.Domain;
Config.WebPort = info.WebPort;
Config.TunnelPorts = info.TunnelPorts;
sForwardServerConfigStore.Confirm();
nodeConfigStore.Confirm();
return true;
}
public async Task<bool> UpgradeForward(string nodeId, string version)
protected override void BuildReport(SForwardServerNodeReportInfo info)
{
SForwardServerNodeStoreInfo store = await sForwardServerNodeStore.GetByNodeId(nodeId);
if (store != null && store.Manageable && sForwardServerConnectionTransfer.TryGet(ConnectionSideType.Node, nodeId, out var connection))
{
await messengerSender.SendOnly(new MessageRequestWrap
{
Connection = connection,
MessengerId = (ushort)SForwardMessengerIds.Update,
Payload = serializer.Serialize(new KeyValuePair<string, string>(store.MasterKey, version))
});
return true;
}
return false;
}
public async Task<bool> Upgrade(string masterKey, string version)
{
if (masterKey != Config.MasterKey) return false;
Helper.AppUpdate(version);
return true;
}
public async Task<bool> ExitForward(string nodeId)
{
SForwardServerNodeStoreInfo store = await sForwardServerNodeStore.GetByNodeId(nodeId);
if (store != null && store.Manageable && sForwardServerConnectionTransfer.TryGet(ConnectionSideType.Node, nodeId, out var connection))
{
await messengerSender.SendOnly(new MessageRequestWrap
{
Connection = connection,
MessengerId = (ushort)SForwardMessengerIds.Update,
Payload = serializer.Serialize(new KeyValuePair<string, string>(store.MasterKey, nodeId))
});
return true;
}
return false;
}
public async Task<bool> Exit(string masterKey)
{
if (masterKey != Config.MasterKey) return false;
Helper.AppExit(-1);
return true;
info.Domain = Config.Domain;
info.TunnelPorts = Config.TunnelPorts;
info.WebPort = Config.WebPort;
}
/// <summary>
@@ -244,11 +61,11 @@ namespace linker.messenger.sforward.server
/// </summary>
/// <param name="super">是否已认证</param>
/// <returns></returns>
public async Task<List<SForwardServerNodeStoreInfo>> GetNodes(bool super, string userid, string machineId)
public override async Task<List<SForwardServerNodeStoreInfo>> GetNodes(bool super, string userid, string machineId)
{
List<string> sforward = (await sForwardServerWhiteListStore.GetNodes(userid, machineId)).Where(c => c.Bandwidth >= 0).SelectMany(c => c.Nodes).ToList();
List<string> sforward = (await sforwardServerWhiteListStore.GetNodes(userid, machineId)).Where(c => c.Bandwidth >= 0).SelectMany(c => c.Nodes).ToList();
var result = (await sForwardServerNodeStore.GetAll())
var result = (await nodeStore.GetAll())
.Where(c => super || Environment.TickCount64 - c.LastTicks < 15000)
.Where(c =>
{
@@ -269,164 +86,5 @@ namespace linker.messenger.sforward.server
});
return list;
}
public async Task<SForwardServerNodeStoreInfo> GetNode(string nodeId)
{
SForwardServerNodeStoreInfo node = await sForwardServerNodeStore.GetByNodeId(nodeId).ConfigureAwait(false);
if (node == null || Environment.TickCount64 - node.LastTicks > 15000)
{
return null;
}
return node;
}
private async Task BuildShareKey()
{
try
{
string host = Config.Host;
if (string.IsNullOrWhiteSpace(host))
{
using HttpClient httpClient = new HttpClient();
host = await httpClient.GetStringAsync($"https://ifconfig.me/ip").WaitAsync(TimeSpan.FromMilliseconds(5000)).ConfigureAwait(false);
}
SForwardServerNodeShareInfo shareKeyInfo = new SForwardServerNodeShareInfo
{
NodeId = Config.NodeId,
Host = $"{host}:{sForwardServerConfigStore.ServicePort}",
Name = Config.Name,
SystemId = SystemIdHelper.GetSystemId().Md5()
};
string shareKey = Convert.ToBase64String(crypto.Encode(serializer.Serialize(shareKeyInfo)));
sForwardServerConfigStore.SetShareKey(shareKey);
sForwardServerConfigStore.Confirm();
host = $"{IPAddress.Loopback}:{sForwardServerConfigStore.ServicePort}";
var node = await sForwardServerNodeStore.GetByNodeId(sForwardServerConfigStore.Config.NodeId);
if (node == null || node.ShareKey != shareKey || node.Name != Config.Name || node.Host != host)
{
await sForwardServerNodeStore.Delete(sForwardServerConfigStore.Config.NodeId);
await sForwardServerNodeStore.Add(new SForwardServerNodeStoreInfo
{
NodeId = sForwardServerConfigStore.Config.NodeId,
Name = "default",
Host = $"{IPAddress.Loopback}:{sForwardServerConfigStore.ServicePort}",
ShareKey = shareKey
}).ConfigureAwait(false);
}
LoggerHelper.Instance.Warning($"build SForward share key : {shareKey}");
}
catch (Exception ex)
{
LoggerHelper.Instance.Error($"build SForward share key error : {ex}");
}
}
private async Task ReportTask()
{
await BuildShareKey().ConfigureAwait(false);
TimerHelper.SetIntervalLong(async () =>
{
try
{
var connections = sForwardServerConnectionTransfer.Get(ConnectionSideType.Master);
if (connections.Any())
{
double diff = (bytes - lastBytes) * 8 / 1024.0 / 1024.0;
lastBytes = bytes;
var config = sForwardServerConfigStore.Config;
SForwardServerNodeReportInfo info = new SForwardServerNodeReportInfo
{
Bandwidth = config.Bandwidth,
Connections = config.Connections,
DataEachMonth = config.DataEachMonth,
DataRemain = config.DataRemain,
Logo = config.Logo,
Name = config.Name,
NodeId = config.NodeId,
Url = config.Url,
ConnectionsRatio = connectionNum,
BandwidthRatio = Math.Round(diff / 5, 2),
Version = VersionHelper.Version,
Masters = connections.Select(c => c.Address).ToArray(),
MasterKey = config.MasterKey,
Domain = config.Domain,
TunnelPorts = config.TunnelPorts,
WebPort = config.WebPort,
};
byte[] memory = serializer.Serialize(info);
var tasks = connections.Select(c => messengerSender.SendOnly(new MessageRequestWrap
{
Connection = c,
MessengerId = (ushort)SForwardMessengerIds.Report,
Payload = memory,
Timeout = 5000
})).ToList();
await Task.WhenAll(tasks).ConfigureAwait(false);
}
}
catch (Exception ex)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Error($"SForward report : {ex}");
}
}
}, 5000);
}
private void SignInTask()
{
TimerHelper.SetIntervalLong(async () =>
{
try
{
var nodes = (await sForwardServerNodeStore.GetAll()).Where(c =>
{
return sForwardServerConnectionTransfer.TryGet(ConnectionSideType.Node, c.NodeId, out IConnection connection) == false || connection == null || connection.Connected == false;
}).ToList();
if (nodes.Count != 0)
{
var tasks = nodes.Select(async c =>
{
IPEndPoint remote = await NetworkHelper.GetEndPointAsync(c.Host, 1802).ConfigureAwait(false);
Socket socket = new Socket(remote.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.KeepAlive();
await socket.ConnectAsync(remote).WaitAsync(TimeSpan.FromMilliseconds(5000)).ConfigureAwait(false);
var connection = await messengerResolver.BeginReceiveClient(socket, true, (byte)ResolverType.SForwardConnection, Helper.EmptyArray).ConfigureAwait(false);
var resp = await messengerSender.SendReply(new MessageRequestWrap
{
Connection = connection,
MessengerId = (ushort)SForwardMessengerIds.SignIn,
Payload = serializer.Serialize(new KeyValuePair<string, string>(Config.NodeId, c.ShareKey)),
Timeout = 5000
}).ConfigureAwait(false);
if (resp.Code == MessageResponeCodes.OK && resp.Data.Span.SequenceEqual(Helper.TrueArray))
{
LoggerHelper.Instance.Debug($"SForward sign in to node {c.NodeId} success");
sForwardServerConnectionTransfer.TryAdd(ConnectionSideType.Node, c.NodeId, connection);
}
else
{
connection?.Disponse();
}
});
await Task.WhenAll(tasks).ConfigureAwait(false);
}
}
catch (Exception ex)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Error($"SForward sign in : {ex}");
}
}
}, 10000);
}
}
}

View File

@@ -1,47 +1,30 @@
using linker.libs;
using linker.libs.timer;
using linker.messenger.node;
using linker.messenger.sforward.messenger;
using System.Collections.Concurrent;
namespace linker.messenger.sforward.server
{
/// <summary>
/// 穿透节点操作
/// </summary>
public class SForwardServerNodeTransfer
public class SForwardServerNodeTransfer : NodeTransfer<SForwardServerConfigInfo, SForwardServerNodeStoreInfo, SForwardServerNodeReportInfo>
{
public SForwardServerConfigInfo Config => sForwardServerConfigStore.Config;
private readonly NumberSpace ns = new(65537);
private readonly SForwardSpeedLimit limitTotal = new();
private readonly ConcurrentDictionary<ulong, SForwardTrafficCacheInfo> trafficDict = new();
private readonly ISerializer serializer;
private readonly IMessengerSender messengerSender;
private readonly ISForwardServerConfigStore sForwardServerConfigStore;
private readonly SForwardServerConnectionTransfer sForwardServerConnectionTransfer;
private readonly SForwardServerNodeReportTransfer sForwardServerNodeReportTransfer;
public SForwardServerNodeTransfer(ISerializer serializer, IMessengerSender messengerSender, ICommonStore commonStore
, ISForwardServerConfigStore sForwardServerConfigStore, SForwardServerConnectionTransfer sForwardServerConnectionTransfer, SForwardServerNodeReportTransfer sForwardServerNodeReportTransfer)
private readonly SForwardServerConnectionTransfer sforwardServerConnectionTransfer;
public SForwardServerNodeTransfer(ISerializer serializer, IMessengerSender messengerSender, SForwardServerConnectionTransfer sforwardServerConnectionTransfer,
ICommonStore commonStore, INodeConfigStore<SForwardServerConfigInfo> nodeConfigStore,
SForwardServerNodeReportTransfer sforwardServerNodeReportTransfer)
: base(commonStore, nodeConfigStore, sforwardServerNodeReportTransfer)
{
this.serializer = serializer;
this.messengerSender = messengerSender;
this.sForwardServerConfigStore = sForwardServerConfigStore;
this.sForwardServerConnectionTransfer = sForwardServerConnectionTransfer;
this.sForwardServerNodeReportTransfer = sForwardServerNodeReportTransfer;
if ((commonStore.Modes & CommonModes.Server) == CommonModes.Server)
{
limitTotal.SetLimit((uint)Math.Ceiling((Config.Bandwidth * 1024 * 1024) / 8.0));
TrafficTask();
}
this.sforwardServerConnectionTransfer = sforwardServerConnectionTransfer;
}
public async Task<bool> ProxyNode(SForwardProxyInfo info)
{
if (sForwardServerConnectionTransfer.TryGet(ConnectionSideType.Master, info.NodeId, out var connection))
if (sforwardServerConnectionTransfer.TryGet(ConnectionSideType.Master, info.NodeId, out var connection))
{
return await messengerSender.SendOnly(new MessageRequestWrap
{
@@ -54,7 +37,7 @@ namespace linker.messenger.sforward.server
}
public async Task<List<string>> Heart(List<string> ids, string masterNodeId)
{
if (sForwardServerConnectionTransfer.TryGet(ConnectionSideType.Master, masterNodeId, out var connection))
if (sforwardServerConnectionTransfer.TryGet(ConnectionSideType.Master, masterNodeId, out var connection))
{
var resp = await messengerSender.SendReply(new MessageRequestWrap
{
@@ -72,205 +55,6 @@ namespace linker.messenger.sforward.server
return [];
}
/// <summary>
/// 是否需要总限速
/// </summary>
/// <returns></returns>
public bool NeedLimit(SForwardTrafficCacheInfo relayCache)
{
return limitTotal.NeedLimit();
}
/// <summary>
/// 总限速
/// </summary>
/// <param name="length"></param>
/// <returns></returns>
public bool TryLimit(ref int length)
{
return limitTotal.TryLimit(ref length);
}
/// <summary>
/// 总限速
/// </summary>
/// <param name="length"></param>
/// <returns></returns>
public bool TryLimitPacket(int length)
{
return limitTotal.TryLimitPacket(length);
}
/// <summary>
/// 开始计算流量
/// </summary>
/// <param name="super"></param>
/// <returns></returns>
public SForwardTrafficCacheInfo AddTrafficCache(bool super, double bandwidth)
{
SForwardTrafficCacheInfo cache = new SForwardTrafficCacheInfo { Cache = new SForwardCacheInfo { FlowId = ns.Increment(), Super = super, Bandwidth = bandwidth }, Limit = new SForwardSpeedLimit(), Sendt = 0, SendtCache = 0 };
if (cache.Cache.Bandwidth < 0)
{
cache.Cache.Bandwidth = Config.Bandwidth;
}
SetLimit(cache);
trafficDict.TryAdd(cache.Cache.FlowId, cache);
return cache;
}
public void RemoveTrafficCache(ulong id)
{
trafficDict.TryRemove(id, out _);
}
/// <summary>
/// 消耗流量
/// </summary>
/// <param name="length"></param>
/// <returns></returns>
public bool AddBytes(SForwardTrafficCacheInfo cache, long length)
{
sForwardServerNodeReportTransfer.AddBytes(length);
if (Config.DataEachMonth == 0) return true;
Interlocked.Add(ref cache.Sendt, length);
return Config.DataRemain > 0;
}
/// <summary>
/// 设置限速
/// </summary>
/// <param name="cache"></param>
private void SetLimit(SForwardTrafficCacheInfo cache)
{
if (cache.Cache.Bandwidth >= 0)
{
cache.Limit.SetLimit((uint)Math.Ceiling(cache.Cache.Bandwidth * 1024 * 1024 / 8.0));
return;
}
cache.Limit.SetLimit((uint)Math.Ceiling(Config.Bandwidth * 1024 * 1024 / 8.0));
}
private void ResetNodeBytes()
{
if (Config.DataEachMonth == 0) return;
foreach (var cache in trafficDict.Values)
{
long length = Interlocked.Exchange(ref cache.Sendt, 0);
if (Config.DataRemain >= length)
sForwardServerConfigStore.SetDataRemain(Config.DataRemain - length);
else sForwardServerConfigStore.SetDataRemain(0);
}
if (Config.DataMonth != DateTime.Now.Month)
{
sForwardServerConfigStore.SetDataMonth(DateTime.Now.Month);
sForwardServerConfigStore.SetDataRemain((long)(Config.DataEachMonth * 1024 * 1024 * 1024));
}
sForwardServerConfigStore.Confirm();
}
private void TrafficTask()
{
TimerHelper.SetIntervalLong(() =>
{
try
{
ResetNodeBytes();
}
catch (Exception ex)
{
LoggerHelper.Instance.Error(ex);
}
}, 3000);
}
}
public sealed partial class SForwardCacheInfo
{
public ulong FlowId { get; set; }
public bool Super { get; set; }
public double Bandwidth { get; set; } = double.MinValue;
}
public class SForwardSpeedLimit
{
private uint sforwardLimit = 0;
private double sforwardLimitToken = 0;
private double sforwardLimitBucket = 0;
private long sforwardLimitTicks = Environment.TickCount64;
public bool NeedLimit()
{
return sforwardLimit > 0;
}
public void SetLimit(uint bytes)
{
//每s多少字节
sforwardLimit = bytes;
//每ms多少字节
sforwardLimitToken = sforwardLimit / 1000.0;
//桶里有多少字节
sforwardLimitBucket = sforwardLimit;
}
public bool TryLimit(ref int length)
{
//0不限速
if (sforwardLimit == 0) return true;
lock (this)
{
long _sforwardLimitTicks = Environment.TickCount64;
//距离上次经过了多少ms
long sforwardLimitTicksTemp = _sforwardLimitTicks - sforwardLimitTicks;
sforwardLimitTicks = _sforwardLimitTicks;
//桶里增加多少字节
sforwardLimitBucket += sforwardLimitTicksTemp * sforwardLimitToken;
//桶溢出了
if (sforwardLimitBucket > sforwardLimit) sforwardLimitBucket = sforwardLimit;
//能全部消耗调
if (sforwardLimitBucket >= length)
{
sforwardLimitBucket -= length;
length = 0;
}
else
{
//只能消耗一部分
length -= (int)sforwardLimitBucket;
sforwardLimitBucket = 0;
}
}
return true;
}
public bool TryLimitPacket(int length)
{
if (sforwardLimit == 0) return true;
lock (this)
{
long _sforwardLimitTicks = Environment.TickCount64;
long sforwardLimitTicksTemp = _sforwardLimitTicks - sforwardLimitTicks;
sforwardLimitTicks = _sforwardLimitTicks;
sforwardLimitBucket += sforwardLimitTicksTemp * sforwardLimitToken;
if (sforwardLimitBucket > sforwardLimit) sforwardLimitBucket = sforwardLimit;
if (sforwardLimitBucket >= length)
{
sforwardLimitBucket -= length;
return true;
}
}
return false;
}
}
public sealed class SForwardTrafficCacheInfo
{
public long Sendt;
public long SendtCache;
public SForwardSpeedLimit Limit { get; set; }
public SForwardCacheInfo Cache { get; set; }
}
}

View File

@@ -1,4 +1,5 @@
using linker.messenger.signin;
using linker.messenger.node;
using linker.messenger.signin;
namespace linker.messenger.sforward.server.validator
{
@@ -9,10 +10,10 @@ namespace linker.messenger.sforward.server.validator
{
public string Name => "default";
private readonly ISForwardServerConfigStore sForwardServerConfigStore;
public SForwardValidator(ISForwardServerConfigStore sForwardServerConfigStore)
private readonly INodeConfigStore<SForwardServerConfigInfo> nodeConfigStore;
public SForwardValidator(INodeConfigStore<SForwardServerConfigInfo> nodeConfigStore)
{
this.sForwardServerConfigStore = sForwardServerConfigStore;
this.nodeConfigStore = nodeConfigStore;
}
public async Task<string> Validate(SignCacheInfo signCacheInfo, SForwardAddInfo sForwardAddInfo)
@@ -30,7 +31,7 @@ namespace linker.messenger.sforward.server.validator
return true;
}
string ports = sForwardServerConfigStore.Config.TunnelPorts;
string ports = nodeConfigStore.Config.TunnelPorts;
return string.IsNullOrWhiteSpace(ports)
|| $",{ports},".Contains($",{port},")
|| ports.Split(',').Where(c => c.Contains('-')).Any(c =>

View File

@@ -7,6 +7,7 @@ using linker.messenger.flow.history;
using linker.messenger.forward;
using linker.messenger.listen;
using linker.messenger.logger;
using linker.messenger.node;
using linker.messenger.pcp;
using linker.messenger.plan;
using linker.messenger.relay.client;
@@ -69,8 +70,10 @@ namespace linker.messenger.store.file
serviceCollection.AddSingleton<IUpdaterServerStore, UpdaterServerStore>();
serviceCollection.AddSingleton<IRelayClientStore, RelayClientStore>();
serviceCollection.AddSingleton<IRelayServerConfigStore, RelayServerConfigStore>();
serviceCollection.AddSingleton<IRelayServerNodeStore, RelayServerNodeStore>();
serviceCollection.AddSingleton<INodeConfigStore<RelayServerConfigInfo>, RelayServerConfigStore>();
serviceCollection.AddSingleton<INodeStore<RelayServerNodeStoreInfo, RelayServerNodeReportInfo>, RelayServerNodeStore>();
serviceCollection.AddSingleton<IRelayServerWhiteListStore, RelayNodeWhiteListStore>();
serviceCollection.AddSingleton<ITunnelClientStore, TunnelClientStore>();
@@ -95,9 +98,9 @@ namespace linker.messenger.store.file
serviceCollection.AddSingleton<ISocks5Store, Socks5Store>();
serviceCollection.AddSingleton<ISForwardClientStore, SForwardClientStore>();
serviceCollection.AddSingleton<ISForwardServerConfigStore, SForwardServerConfigStore>();
serviceCollection.AddSingleton<ISForwardServerNodeStore, SForwardServerNodeStore>();
serviceCollection.AddSingleton<ISForwardServerNodeStore, SForwardServerNodeStore>();
serviceCollection.AddSingleton<INodeConfigStore<SForwardServerConfigInfo>, SForwardServerConfigStore>();
serviceCollection.AddSingleton<INodeStore<SForwardServerNodeStoreInfo, SForwardServerNodeReportInfo>, SForwardServerNodeStore>();
serviceCollection.AddSingleton<ISForwardServerWhiteListStore, SForwardNodeWhiteListStore>();
serviceCollection.AddSingleton<ILoggerStore, LoggerStore>();

View File

@@ -0,0 +1,41 @@
using linker.messenger.node;
namespace linker.messenger.store.file.node
{
public class NodeConfigStore<TConfig> : INodeConfigStore<TConfig> where TConfig : class, INodeConfigBase, new()
{
public int ServicePort => config.Data.Server.ServicePort;
public virtual TConfig Config { get; }
private readonly FileConfig config;
public NodeConfigStore(FileConfig config)
{
this.config = config;
}
public void Confirm()
{
config.Data.Update();
}
public void SetDataRemain(long value)
{
Config.DataRemain = value;
}
public void SetDataMonth(int month)
{
Config.DataMonth = month;
}
public void SetShareKey(string shareKey)
{
Config.ShareKey = shareKey;
}
public void SetMasterKey(string masterKey)
{
Config.MasterKey = masterKey;
}
}
}

View File

@@ -0,0 +1,55 @@
using linker.messenger.node;
using LiteDB;
namespace linker.messenger.store.file.node
{
public class NodeStore<TStore, TReport> : INodeStore<TStore, TReport>
where TStore : class, INodeStoreBase, new()
where TReport : class, INodeReportBase, new()
{
public virtual string StoreName => "relay";
protected readonly ILiteCollection<TStore> liteCollection;
public NodeStore(Storefactory storefactory)
{
liteCollection = storefactory.GetCollection<TStore>($"{StoreName}_server_master");
}
public async Task<bool> Add(TStore info)
{
if (liteCollection.FindOne(c => c.NodeId == info.NodeId) != null)
{
return false;
}
liteCollection.Insert(info);
return await Task.FromResult(true).ConfigureAwait(false);
}
public async Task<bool> Delete(string nodeId)
{
return await Task.FromResult(liteCollection.DeleteMany(c => c.NodeId == nodeId) > 0).ConfigureAwait(false);
}
public async Task<List<TStore>> GetAll()
{
return await Task.FromResult(liteCollection.FindAll().ToList()).ConfigureAwait(false);
}
public async Task<TStore> GetByNodeId(string nodeId)
{
return await Task.FromResult(liteCollection.FindOne(c => c.NodeId == nodeId)).ConfigureAwait(false);
}
public virtual async Task<bool> Report(TReport info)
{
return false;
}
public virtual async Task<bool> Update(TStore info)
{
return false;
}
}
}

View File

@@ -0,0 +1,26 @@
using linker.messenger.node;
using linker.messenger.wlist;
namespace linker.messenger.store.file.node
{
public class NodeWhiteListStore : INodeWhiteListStore
{
public virtual string TypeName => string.Empty;
private readonly IWhiteListServerStore whiteListServerStore;
public NodeWhiteListStore(IWhiteListServerStore whiteListServerStore)
{
this.whiteListServerStore = whiteListServerStore;
}
public async Task<List<NodeWhiteListInfo>> GetNodes(string userid,string machineid)
{
return (await whiteListServerStore.Get(TypeName, [userid], [machineid]).ConfigureAwait(false)).Select(c => new NodeWhiteListInfo { Nodes = c.Nodes, Bandwidth = c.Bandwidth }).ToList();
}
public async Task<List<double>> GetBandwidth(string userid, string fromMachineId, string toMachineId, string nodeid)
{
return (await whiteListServerStore.Get(TypeName, [userid], [fromMachineId, toMachineId]).ConfigureAwait(false)).Where(c => c.Nodes.Contains(nodeid) || c.Nodes.Contains("*")).Select(c => c.Bandwidth).ToList();
}
}
}

View File

@@ -0,0 +1,12 @@
using linker.messenger.relay.server;
using linker.messenger.wlist;
namespace linker.messenger.store.file.relay
{
public class RelayNodeWhiteListStore : node.NodeWhiteListStore, IRelayServerWhiteListStore
{
public RelayNodeWhiteListStore(IWhiteListServerStore whiteListServerStore) : base(whiteListServerStore) { }
public override string TypeName => "Relay";
}
}

View File

@@ -1,63 +1,37 @@
using linker.libs;
using linker.messenger.relay.server;
using linker.messenger.store.file.node;
namespace linker.messenger.store.file.relay
{
public sealed class RelayServerConfigStore : IRelayServerConfigStore
public sealed class RelayServerConfigStore : NodeConfigStore<RelayServerConfigInfo>
{
public int ServicePort => config.Data.Server.ServicePort;
public RelayServerConfigInfo Config => config.Data.Server.Relay;
public override RelayServerConfigInfo Config => config.Data.Server.Relay;
private readonly FileConfig config;
public RelayServerConfigStore(FileConfig config)
public RelayServerConfigStore(FileConfig config) : base(config)
{
this.config = config;
if (string.IsNullOrWhiteSpace(Config.Distributed.Node.Id) == false)
{
Config.NodeId = Config.Distributed.Node.Id;
Config.Connections = Config.Distributed.Node.MaxConnection;
Config.DataRemain = Config.Distributed.Node.MaxGbTotalLastBytes;
Config.DataMonth = Config.Distributed.Node.MaxGbTotalMonth;
Config.Bandwidth = (int)Config.Distributed.Node.MaxBandwidthTotal;
Config.DataEachMonth = (int)Config.Distributed.Node.MaxGbTotal;
Config.Name = Config.Distributed.Node.Name;
Config.Url = Config.Distributed.Node.Url;
this.config = config;
Config.Host = NetworkHelper.GetEndPoint(Config.Distributed.Node.Host, ServicePort).Address.ToString();
if (string.IsNullOrWhiteSpace(Config.Distributed.Node.Id) == false)
{
Config.NodeId = Config.Distributed.Node.Id;
Config.Connections = Config.Distributed.Node.MaxConnection;
Config.DataRemain = Config.Distributed.Node.MaxGbTotalLastBytes;
Config.DataMonth = Config.Distributed.Node.MaxGbTotalMonth;
Config.Bandwidth = (int)Config.Distributed.Node.MaxBandwidthTotal;
Config.DataEachMonth = (int)Config.Distributed.Node.MaxGbTotal;
Config.Name = Config.Distributed.Node.Name;
Config.Url = Config.Distributed.Node.Url;
Config.Distributed.Node.Id = string.Empty;
config.Data.Update();
Config.Host = NetworkHelper.GetEndPoint(Config.Distributed.Node.Host, ServicePort).Address.ToString();
Config.Distributed.Node.Id = string.Empty;
Confirm();
}
}
}
public void Confirm()
{
config.Data.Update();
}
public void SetInfo(RelayServerConfigInfo node)
{
config.Data.Server.Relay = node;
}
public void SetDataRemain(long value)
{
config.Data.Server.Relay.DataRemain = value;
}
public void SetDataMonth(int month)
{
config.Data.Server.Relay.DataMonth = month;
}
public void SetShareKey(string shareKey)
{
config.Data.Server.Relay.ShareKey = shareKey;
}
public void SetMasterKey(string masterKey)
{
config.Data.Server.Relay.MasterKey = masterKey;
}
}
}

View File

@@ -1,46 +1,20 @@
using linker.libs.extends;
using linker.messenger.node;
using linker.messenger.relay.server;
using LiteDB;
using linker.messenger.store.file.node;
namespace linker.messenger.store.file.relay
{
public sealed class RelayServerNodeStore : IRelayServerNodeStore
public sealed class RelayServerNodeStore : NodeStore<RelayServerNodeStoreInfo, RelayServerNodeReportInfo>
{
private readonly ILiteCollection<RelayServerNodeStoreInfo> liteCollection;
public override string StoreName => "relay";
private string md5 = string.Empty;
public RelayServerNodeStore(Storefactory storefactory, IRelayServerConfigStore relayServerConfigStore)
public RelayServerNodeStore(Storefactory storefactory, INodeConfigStore<RelayServerConfigInfo> relayServerConfigStore) : base(storefactory)
{
liteCollection = storefactory.GetCollection<RelayServerNodeStoreInfo>("relay_server_master");
md5 = relayServerConfigStore.Config.NodeId.Md5();
}
public async Task<bool> Add(RelayServerNodeStoreInfo info)
{
if (liteCollection.FindOne(c => c.NodeId == info.NodeId) != null)
{
return false;
}
liteCollection.Insert(info);
return await Task.FromResult(true).ConfigureAwait(false);
}
public async Task<bool> Delete(string nodeId)
{
return await Task.FromResult(liteCollection.DeleteMany(c => c.NodeId == nodeId) > 0).ConfigureAwait(false);
}
public async Task<List<RelayServerNodeStoreInfo>> GetAll()
{
return await Task.FromResult(liteCollection.FindAll().ToList()).ConfigureAwait(false);
}
public async Task<RelayServerNodeStoreInfo> GetByNodeId(string nodeId)
{
return await Task.FromResult(liteCollection.FindOne(c => c.NodeId == nodeId)).ConfigureAwait(false);
}
public async Task<bool> Report(RelayServerNodeReportInfo info)
public override async Task<bool> Report(RelayServerNodeReportInfo info)
{
int length = liteCollection.UpdateMany(p => new RelayServerNodeStoreInfo
{
@@ -57,7 +31,7 @@ namespace linker.messenger.store.file.relay
Name = info.Name,
Protocol = info.Protocol,
MasterKey = info.MasterKey,
Masters = info.Masters,
MasterCount = info.MasterCount,
//是我初始化的,可以管理
Manageable = info.MasterKey == md5
}, c => c.NodeId == info.NodeId);
@@ -65,7 +39,7 @@ namespace linker.messenger.store.file.relay
return await Task.FromResult(length > 0).ConfigureAwait(false);
}
public async Task<bool> Update(RelayServerNodeStoreInfo info)
public override async Task<bool> Update(RelayServerNodeStoreInfo info)
{
int length = liteCollection.UpdateMany(p => new RelayServerNodeStoreInfo
{

View File

@@ -0,0 +1,13 @@
using linker.messenger.relay.server;
using linker.messenger.sforward.server;
using linker.messenger.wlist;
namespace linker.messenger.store.file.sforward
{
public class SForwardNodeWhiteListStore : node.NodeWhiteListStore, ISForwardServerWhiteListStore
{
public SForwardNodeWhiteListStore(IWhiteListServerStore whiteListServerStore) : base(whiteListServerStore) { }
public override string TypeName => "SForward";
}
}

View File

@@ -1,18 +1,17 @@
using linker.libs;
using linker.messenger.sforward.server;
using linker.messenger.store.file.node;
namespace linker.messenger.store.file.sforward
{
public sealed class SForwardServerConfigStore : ISForwardServerConfigStore
public sealed class SForwardServerConfigStore : NodeConfigStore<SForwardServerConfigInfo>
{
public int ServicePort => config.Data.Server.ServicePort;
public SForwardServerConfigInfo Config => config.Data.Server.SForward;
public override SForwardServerConfigInfo Config => config.Data.Server.SForward;
private readonly FileConfig config;
public SForwardServerConfigStore(FileConfig config)
public SForwardServerConfigStore(FileConfig config) : base(config)
{
this.config = config;
if (string.IsNullOrWhiteSpace(Config.Distributed.Node.Id) == false)
{
Config.NodeId = Config.Distributed.Node.Id;
@@ -26,37 +25,9 @@ namespace linker.messenger.store.file.sforward
Config.Host = NetworkHelper.GetEndPoint(Config.Distributed.Node.Host, ServicePort).Address.ToString();
Config.Distributed.Node.Id = string.Empty;
config.Data.Update();
Confirm();
}
}
public void Confirm()
{
config.Data.Update();
}
public void SetInfo(SForwardServerConfigInfo node)
{
config.Data.Server.SForward = node;
}
public void SetDataRemain(long value)
{
config.Data.Server.SForward.DataRemain = value;
}
public void SetDataMonth(int month)
{
config.Data.Server.SForward.DataMonth = month;
}
public void SetShareKey(string shareKey)
{
config.Data.Server.SForward.ShareKey = shareKey;
}
public void SetMasterKey(string masterKey)
{
config.Data.Server.SForward.MasterKey = masterKey;
}
}
}

View File

@@ -1,46 +1,22 @@
using linker.libs.extends;
using linker.messenger.node;
using linker.messenger.relay.server;
using linker.messenger.sforward.server;
using linker.messenger.store.file.node;
using LiteDB;
namespace linker.messenger.store.file.sforward
{
public sealed class SForwardServerNodeStore : ISForwardServerNodeStore
public sealed class SForwardServerNodeStore : NodeStore<SForwardServerNodeStoreInfo, SForwardServerNodeReportInfo>
{
private readonly ILiteCollection<SForwardServerNodeStoreInfo> liteCollection;
public override string StoreName => "sforward";
private string md5 = string.Empty;
public SForwardServerNodeStore(Storefactory storefactory, ISForwardServerConfigStore SForwardServerConfigStore)
public SForwardServerNodeStore(Storefactory storefactory, INodeConfigStore<SForwardServerConfigInfo> nodeConfigStore) : base(storefactory)
{
liteCollection = storefactory.GetCollection<SForwardServerNodeStoreInfo>("SForward_server_master");
md5 = SForwardServerConfigStore.Config.NodeId.Md5();
md5 = nodeConfigStore.Config.NodeId.Md5();
}
public async Task<bool> Add(SForwardServerNodeStoreInfo info)
{
if (liteCollection.FindOne(c => c.NodeId == info.NodeId) != null)
{
return false;
}
liteCollection.Insert(info);
return await Task.FromResult(true).ConfigureAwait(false);
}
public async Task<bool> Delete(string nodeId)
{
return await Task.FromResult(liteCollection.DeleteMany(c => c.NodeId == nodeId) > 0).ConfigureAwait(false);
}
public async Task<List<SForwardServerNodeStoreInfo>> GetAll()
{
return await Task.FromResult(liteCollection.FindAll().ToList()).ConfigureAwait(false);
}
public async Task<SForwardServerNodeStoreInfo> GetByNodeId(string nodeId)
{
return await Task.FromResult(liteCollection.FindOne(c => c.NodeId == nodeId)).ConfigureAwait(false);
}
public async Task<bool> Report(SForwardServerNodeReportInfo info)
public override async Task<bool> Report(SForwardServerNodeReportInfo info)
{
int length = liteCollection.UpdateMany(p => new SForwardServerNodeStoreInfo
{
@@ -56,7 +32,7 @@ namespace linker.messenger.store.file.sforward
DataRemain = info.DataRemain,
Name = info.Name,
MasterKey = info.MasterKey,
Masters = info.Masters,
MasterCount = info.MasterCount,
//是我初始化的,可以管理
Manageable = info.MasterKey == md5,
Domain = info.Domain,
@@ -67,7 +43,7 @@ namespace linker.messenger.store.file.sforward
return await Task.FromResult(length > 0).ConfigureAwait(false);
}
public async Task<bool> Update(SForwardServerNodeStoreInfo info)
public override async Task<bool> Update(SForwardServerNodeStoreInfo info)
{
int length = liteCollection.UpdateMany(p => new SForwardServerNodeStoreInfo
{

View File

@@ -1,6 +1,4 @@
using linker.libs.web;
using linker.messenger.relay.server;
using linker.messenger.sforward.server;
using linker.messenger.wlist.order;
using Microsoft.Extensions.DependencyInjection;
namespace linker.messenger.wlist
@@ -26,13 +24,9 @@ namespace linker.messenger.wlist
{
serviceCollection.AddSingleton<WhiteListServerMessenger>();
serviceCollection.AddSingleton<IRelayServerWhiteListStore, RelayWhiteListStore>();
serviceCollection.AddSingleton<ISForwardServerWhiteListStore, SForwardWhiteListStore>();
serviceCollection.AddSingleton<OrderTransfer>();
serviceCollection.AddSingleton<OrderAfdian>();
return serviceCollection;
}

View File

@@ -1,21 +0,0 @@
using linker.messenger.relay.server;
namespace linker.messenger.wlist
{
internal sealed class RelayWhiteListStore : IRelayServerWhiteListStore
{
private readonly IWhiteListServerStore whiteListServerStore;
public RelayWhiteListStore(IWhiteListServerStore whiteListServerStore)
{
this.whiteListServerStore = whiteListServerStore;
}
public async Task<List<RelayWhiteListItem>> GetNodes(string userid,string machineid)
{
return (await whiteListServerStore.Get("Relay", [userid], [machineid]).ConfigureAwait(false)).Select(c => new RelayWhiteListItem { Nodes = c.Nodes, Bandwidth = c.Bandwidth }).ToList();
}
public async Task<List<double>> GetBandwidth(string userid, string fromMachineId, string toMachineId, string nodeid)
{
return (await whiteListServerStore.Get("Relay", [userid], [fromMachineId, toMachineId]).ConfigureAwait(false)).Where(c => c.Nodes.Contains(nodeid) || c.Nodes.Contains("*")).Select(c => c.Bandwidth).ToList();
}
}
}

View File

@@ -1,17 +0,0 @@
using linker.messenger.sforward.server;
namespace linker.messenger.wlist
{
internal sealed class SForwardWhiteListStore : ISForwardServerWhiteListStore
{
private readonly IWhiteListServerStore whiteListServerStore;
public SForwardWhiteListStore(IWhiteListServerStore whiteListServerStore)
{
this.whiteListServerStore = whiteListServerStore;
}
public async Task<List<SForwardWhiteListItem>> GetNodes(string userid,string machineid)
{
return (await whiteListServerStore.Get("SForward", [userid], [machineid]).ConfigureAwait(false)).Select(c => new SForwardWhiteListItem { Nodes = c.Nodes, Bandwidth = c.Bandwidth }).ToList();
}
}
}

View File

@@ -38,8 +38,6 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\linker.libs\linker.libs.csproj" />
<ProjectReference Include="..\linker.messenger.relay\linker.messenger.relay.csproj" />
<ProjectReference Include="..\linker.messenger.sforward\linker.messenger.sforward.csproj" />
<ProjectReference Include="..\linker.messenger.signin\linker.messenger.signin.csproj" />
<ProjectReference Include="..\linker.messenger.sync\linker.messenger.sync.csproj" />
<ProjectReference Include="..\linker.messenger\linker.messenger.csproj" />

View File

@@ -40,14 +40,9 @@ namespace linker.messenger
SForwardReport = 8,
/// <summary>
/// 中继联机
/// 节点联机
/// </summary>
RelayConnection = 9,
/// <summary>
/// 穿透联机
/// </summary>
SForwardConnection = 10,
NodeConnection = 9,
}
public interface IResolver
{

View File

@@ -24,7 +24,11 @@
</div>
<div class="flex-1">
<p class="flex">
<a :href="scope.row.Url" class="a-line" target="_blank"><strong>{{ scope.row.Name }}</strong></a>
<el-badge @click.stop type="success" :value="scope.row.MasterCount" :offset="[20, 10]">
<a :href="scope.row.Url" class="a-line" target="_blank">
<strong>{{ scope.row.Name }}</strong>
</a>
</el-badge>
</p>
<p class="flex">
<span>{{ scope.row.Host }}</span>

View File

@@ -24,9 +24,11 @@
</div>
<div class="flex-1">
<p class="flex">
<a :href="scope.row.Url" class="a-line"
:class="{green:scope.row.Public}" target="_blank"
:title="scope.row.Public?$t('server.relayPublic'):''"><strong>{{ scope.row.Name }}</strong></a>
<el-badge @click.stop type="success" :value="scope.row.MasterCount" :offset="[20, 10]">
<a :href="scope.row.Url" class="a-line" :class="{green:scope.row.Public}" target="_blank" >
<strong>{{ scope.row.Name }}</strong>
</a>
</el-badge>
<span class="flex-1"></span>
<a href="javascript:;" class="protocol">
<span v-if="(scope.row.Protocol & 1) == 1">tcp</span>
@@ -310,6 +312,6 @@ a.a-edit{
}
.gray{
filter: grayscale(100%);
}
filter: grayscale(100%);
}
</style>