mirror of
https://github.com/snltty/linker.git
synced 2025-12-24 12:38:04 +08:00
合并中继和穿透的多节点公共代码,公用多节点逻辑
This commit is contained in:
3
.github/workflows/nuget.yml
vendored
3
.github/workflows/nuget.yml
vendored
@@ -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
|
||||
|
||||
59
linker.messenger.node/INodeConfigStore.cs
Normal file
59
linker.messenger.node/INodeConfigStore.cs
Normal 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;
|
||||
|
||||
}
|
||||
}
|
||||
32
linker.messenger.node/INodeMasterDenyStore.cs
Normal file
32
linker.messenger.node/INodeMasterDenyStore.cs
Normal 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; }
|
||||
}
|
||||
|
||||
}
|
||||
52
linker.messenger.node/INodeStore.cs
Normal file
52
linker.messenger.node/INodeStore.cs
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
48
linker.messenger.node/INodeWhiteListStore.cs
Normal file
48
linker.messenger.node/INodeWhiteListStore.cs
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
41
linker.messenger.node/NodeConnectionTransfer.cs
Normal file
41
linker.messenger.node/NodeConnectionTransfer.cs
Normal 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
|
||||
}
|
||||
}
|
||||
407
linker.messenger.node/NodeReportTransfer.cs
Normal file
407
linker.messenger.node/NodeReportTransfer.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
269
linker.messenger.node/NodeTransfer.cs
Normal file
269
linker.messenger.node/NodeTransfer.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
43
linker.messenger.node/linker.messenger.node.csproj
Normal file
43
linker.messenger.node/linker.messenger.node.csproj
Normal 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>
|
||||
18
linker.sln
18
linker.sln
@@ -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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
v1.9.7
|
||||
2025-12-09 16:23:22
|
||||
2025-12-10 17:13:38
|
||||
1. 一些累计更新,一些BUG修复
|
||||
2. 重构中继和穿透的多节点模式
|
||||
3. 中继连接合并到隧道协议中
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
```
|
||||
:::
|
||||
@@ -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>();
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
|
||||
|
||||
|
||||
73
src/linker.messenger.serializer.memorypack/NodeSerializer.cs
Normal file
73
src/linker.messenger.serializer.memorypack/NodeSerializer.cs
Normal 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>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 =>
|
||||
|
||||
@@ -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>();
|
||||
|
||||
|
||||
41
src/linker.messenger.store.file/node/NodeConfigStore.cs
Normal file
41
src/linker.messenger.store.file/node/NodeConfigStore.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
55
src/linker.messenger.store.file/node/NodeStore.cs
Normal file
55
src/linker.messenger.store.file/node/NodeStore.cs
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
26
src/linker.messenger.store.file/node/NodeWhiteListStore.cs
Normal file
26
src/linker.messenger.store.file/node/NodeWhiteListStore.cs
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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" />
|
||||
|
||||
@@ -40,14 +40,9 @@ namespace linker.messenger
|
||||
SForwardReport = 8,
|
||||
|
||||
/// <summary>
|
||||
/// 中继联机
|
||||
/// 节点联机
|
||||
/// </summary>
|
||||
RelayConnection = 9,
|
||||
|
||||
/// <summary>
|
||||
/// 穿透联机
|
||||
/// </summary>
|
||||
SForwardConnection = 10,
|
||||
NodeConnection = 9,
|
||||
}
|
||||
public interface IResolver
|
||||
{
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user