mirror of
https://github.com/snltty/linker.git
synced 2025-09-26 21:15:57 +08:00
cdkey
This commit is contained in:
2
.github/workflows/dotnet.yml
vendored
2
.github/workflows/dotnet.yml
vendored
@@ -35,7 +35,7 @@ jobs:
|
||||
release_name: v1.6.9.${{ steps.date.outputs.today }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
body: "1. 优化linux下路由跟踪问题\r\n2. 优化linux下获取本机IP问题\r\n3. 增加ICS,让win7+、win server2008+支持NAT\r\n4. 增加中继卡密\r\n5. 增加内外穿透定时开关功能\r\n6. 优化管理页面连接接口的体验\r\n7. 优化一些UI体验,去除同步页面,将同步功能放置各个实际的位置\r\n8. 其它一些修复优化"
|
||||
body: "1. 优化linux下路由跟踪问题\r\n2. 优化linux下获取本机IP问题\r\n3. 增加ICS,让win7+、win server2008+支持NAT\r\n4. 增加中继cdkey,使用cdkey解锁公开中继节点的带宽、流量、连接数限制\r\n5. 增加内外穿透定时开关功能\r\n6. 优化管理页面连接接口的体验\r\n7. 优化一些UI体验,去除同步页面,将同步功能放至各个实际的位置\r\n8. 优化端口转发,让不同分组间可以使用相同端口\r\n9. 其它一些修复优化"
|
||||
- name: publish projects
|
||||
run: ./publish.bat
|
||||
- name: upload-win-x86-oss
|
||||
|
@@ -58,6 +58,7 @@ For user convenience, this project provides **public messenger servers** and **p
|
||||
- [x] Distributed architecture: Multiple relay nodes for massive scalability
|
||||
- [x] SOCKS5 proxy: Dynamic port forwarding without specifying ports
|
||||
- [x] Easy integration: Use `linker.messenger.entry` to embed into your projects
|
||||
- [x] CDKEY,It can temporarily lift certain restrictions
|
||||
|
||||
## Quick Integration
|
||||
In a .NET 8+ project, install the NuGet package `linker.messenger.entry`
|
||||
|
@@ -58,6 +58,7 @@
|
||||
- [x] 分布式,多中继服务器节点,承载海量设备
|
||||
- [x] socks5代理,端口转发需要指定端口,而socks5代理可以代理所有端口
|
||||
- [x] 集成linker,使用`linker.messenger.entry`入口库,轻松集成到你的项目中
|
||||
- [x] CDKEY,可以临时解锁一些限制,中继,内外穿透什么的
|
||||
|
||||
## 轻松集成
|
||||
在.NET8+项目中,nuget 安装 `linker.messenger.entry`
|
||||
|
@@ -44,7 +44,7 @@ sidebar_position: 1
|
||||
- [x] 分布式,多中继服务器节点,承载海量设备
|
||||
- [x] socks5代理,端口转发需要指定端口,而socks5代理可以代理所有端口
|
||||
- [x] 集成linker,使用`linker.messenger.entry`入口库,轻松集成到你的项目中
|
||||
|
||||
- [x] CDKEY,可以临时解锁一些限制,中继,内外穿透什么的
|
||||
|
||||
#### 1.4、加入组织
|
||||
<a href="https://jq.qq.com/?_wv=1027&k=ucoIVfz4" target="_blank">你可以加入QQ群:1121552990</a>
|
||||
|
@@ -13,48 +13,87 @@ namespace linker.libs
|
||||
action();
|
||||
});
|
||||
}
|
||||
|
||||
public static void SetInterval(Func<bool> action, int delayMs)
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
while (true)
|
||||
while (action())
|
||||
{
|
||||
if (action() == false)
|
||||
{
|
||||
break;
|
||||
}
|
||||
await Task.Delay(delayMs).ConfigureAwait(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
public static void SetIntervalLong(Func<bool> action, int delayMs)
|
||||
{
|
||||
Task.Factory.StartNew(async () =>
|
||||
{
|
||||
while (action())
|
||||
{
|
||||
await Task.Delay(delayMs).ConfigureAwait(false);
|
||||
}
|
||||
}, TaskCreationOptions.LongRunning);
|
||||
}
|
||||
public static void SetInterval(Func<Task<bool>> action, int delayMs)
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
while (await action())
|
||||
{
|
||||
await Task.Delay(delayMs).ConfigureAwait(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
public static void SetIntervalLong(Func<Task<bool>> action, int delay)
|
||||
{
|
||||
Task.Factory.StartNew(async () =>
|
||||
{
|
||||
while (await action())
|
||||
{
|
||||
await Task.Delay(delay).ConfigureAwait(false);
|
||||
}
|
||||
}, TaskCreationOptions.LongRunning);
|
||||
}
|
||||
public static void SetInterval(Func<bool> action, Func<int> delay)
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
while (true)
|
||||
while (action())
|
||||
{
|
||||
if (action() == false)
|
||||
{
|
||||
break;
|
||||
}
|
||||
await Task.Delay(delay()).ConfigureAwait(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
public static void SetIntervalLong(Func<bool> action, Func<int> delay)
|
||||
{
|
||||
Task.Factory.StartNew(async () =>
|
||||
{
|
||||
while (action())
|
||||
{
|
||||
await Task.Delay(delay()).ConfigureAwait(false);
|
||||
}
|
||||
}, TaskCreationOptions.LongRunning);
|
||||
}
|
||||
public static void SetInterval(Func<Task<bool>> action, Func<int> delay)
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
while (true)
|
||||
while (await action())
|
||||
{
|
||||
if (await action() == false)
|
||||
{
|
||||
break;
|
||||
}
|
||||
await Task.Delay(delay()).ConfigureAwait(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
public static void SetIntervalLong(Func<Task<bool>> action, Func<int> delay)
|
||||
{
|
||||
Task.Factory.StartNew(async () =>
|
||||
{
|
||||
while (await action())
|
||||
{
|
||||
await Task.Delay(delay()).ConfigureAwait(false);
|
||||
}
|
||||
}, TaskCreationOptions.LongRunning);
|
||||
}
|
||||
|
||||
public static void Async(Action action)
|
||||
{
|
||||
@@ -68,5 +107,6 @@ namespace linker.libs
|
||||
{
|
||||
Task.Factory.StartNew(action,TaskCreationOptions.LongRunning);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -53,7 +53,7 @@ namespace linker.messenger.decenter
|
||||
|
||||
private void SyncTask()
|
||||
{
|
||||
TimerHelper.SetInterval(async () =>
|
||||
TimerHelper.SetIntervalLong(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -100,7 +100,7 @@ namespace linker.messenger.decenter
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}, () => 300);
|
||||
}, 300);
|
||||
}
|
||||
|
||||
class DecenterSyncTaskInfo
|
||||
|
@@ -4,8 +4,8 @@ namespace linker.messenger.flow
|
||||
{
|
||||
public sealed class ExternalFlow : IFlow
|
||||
{
|
||||
public ulong ReceiveBytes { get; private set; }
|
||||
public ulong SendtBytes { get; private set; }
|
||||
public long ReceiveBytes { get; private set; }
|
||||
public long SendtBytes { get; private set; }
|
||||
public string FlowName => "External";
|
||||
public VersionManager Version { get; } = new VersionManager();
|
||||
|
||||
@@ -16,11 +16,11 @@ namespace linker.messenger.flow
|
||||
|
||||
public string GetItems() => string.Empty;
|
||||
public void SetItems(string json) { }
|
||||
public void SetBytes(ulong receiveBytes, ulong sendtBytes) { ReceiveBytes = receiveBytes; SendtBytes = sendtBytes; }
|
||||
public void SetBytes(long receiveBytes, long sendtBytes) { ReceiveBytes = receiveBytes; SendtBytes = sendtBytes; }
|
||||
public void Clear() { ReceiveBytes = 0; SendtBytes = 0;}
|
||||
|
||||
public void AddReceive(ulong bytes) { ReceiveBytes += bytes; Version.Add(); }
|
||||
public void AddSendt(ulong bytes) { SendtBytes += bytes; Version.Add(); }
|
||||
public void AddReceive(long bytes) { ReceiveBytes += bytes; Version.Add(); }
|
||||
public void AddSendt(long bytes) { SendtBytes += bytes; Version.Add(); }
|
||||
|
||||
}
|
||||
|
||||
@@ -35,8 +35,8 @@ namespace linker.messenger.flow
|
||||
this.externalFlow = externalFlow;
|
||||
}
|
||||
|
||||
public override void AddReceive(ulong bytes) { externalFlow.AddReceive(bytes); }
|
||||
public override void AddSendt(ulong bytes) { externalFlow.AddSendt(bytes); }
|
||||
public override void AddReceive(long bytes) { externalFlow.AddReceive(bytes); }
|
||||
public override void AddSendt(long bytes) { externalFlow.AddSendt(bytes); }
|
||||
|
||||
}
|
||||
|
||||
|
@@ -18,11 +18,11 @@ namespace linker.messenger.flow
|
||||
/// <summary>
|
||||
/// 在线 | 总数
|
||||
/// </summary>
|
||||
public ulong ReceiveBytes { get; private set; }
|
||||
public long ReceiveBytes { get; private set; }
|
||||
/// <summary>
|
||||
/// 服务器数
|
||||
/// </summary>
|
||||
public ulong SendtBytes { get; private set; }
|
||||
public long SendtBytes { get; private set; }
|
||||
|
||||
|
||||
private ConcurrentDictionary<IPAddress, OnlineFlowInfo> servers = new ConcurrentDictionary<IPAddress, OnlineFlowInfo>(new IPAddressComparer());
|
||||
@@ -69,7 +69,7 @@ namespace linker.messenger.flow
|
||||
|
||||
public string GetItems() => string.Empty;
|
||||
public void SetItems(string json) { }
|
||||
public void SetBytes(ulong receiveBytes, ulong sendtBytes) { }
|
||||
public void SetBytes(long receiveBytes, long sendtBytes) { }
|
||||
public void Clear() { }
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace linker.messenger.flow
|
||||
|
||||
private void OnlineTask()
|
||||
{
|
||||
TimerHelper.SetInterval(() =>
|
||||
TimerHelper.SetIntervalLong(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -110,11 +110,11 @@ namespace linker.messenger.flow
|
||||
servers.TryRemove(key, out _);
|
||||
}
|
||||
|
||||
ulong online = (ulong)servers.Sum(c => c.Value.Online) << 32;
|
||||
ulong total = (ulong)servers.Sum(c => c.Value.Total);
|
||||
long online = servers.Sum(c => c.Value.Online) << 32;
|
||||
long total = servers.Sum(c => c.Value.Total);
|
||||
|
||||
ReceiveBytes = online | total;
|
||||
SendtBytes = (ulong)servers.Count;
|
||||
SendtBytes = servers.Count;
|
||||
Version.Add();
|
||||
}
|
||||
private void Report()
|
||||
|
@@ -5,21 +5,21 @@ namespace linker.messenger.flow
|
||||
{
|
||||
public interface IFlow
|
||||
{
|
||||
public ulong ReceiveBytes { get; }
|
||||
public ulong SendtBytes { get; }
|
||||
public long ReceiveBytes { get; }
|
||||
public long SendtBytes { get; }
|
||||
public string FlowName { get; }
|
||||
|
||||
public VersionManager Version { get; }
|
||||
public string GetItems();
|
||||
public void SetItems(string json);
|
||||
public void SetBytes(ulong receiveBytes,ulong sendtBytes);
|
||||
public void SetBytes(long receiveBytes,long sendtBytes);
|
||||
public void Clear();
|
||||
}
|
||||
|
||||
public partial class FlowItemInfo
|
||||
{
|
||||
public ulong ReceiveBytes { get; set; }
|
||||
public ulong SendtBytes { get; set; }
|
||||
public long ReceiveBytes { get; set; }
|
||||
public long SendtBytes { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public string FlowName { get; set; }
|
||||
|
@@ -1,13 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace linker.messenger.flow
|
||||
{
|
||||
public interface IFlowStore
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@@ -12,11 +12,11 @@ namespace linker.messenger.flow
|
||||
this.messengerFlow = messengerFlow;
|
||||
}
|
||||
|
||||
public override void AddReceive(ushort id, ulong bytes)
|
||||
public override void AddReceive(ushort id, long bytes)
|
||||
{
|
||||
messengerFlow.AddReceive(id, bytes);
|
||||
}
|
||||
public override void AddSendt(ushort id, ulong bytes)
|
||||
public override void AddSendt(ushort id, long bytes)
|
||||
{
|
||||
messengerFlow.AddSendt(id, bytes);
|
||||
}
|
||||
@@ -29,11 +29,11 @@ namespace linker.messenger.flow
|
||||
this.messengerFlow = messengerFlow;
|
||||
}
|
||||
|
||||
public override void AddReceive(ushort id, ulong bytes)
|
||||
public override void AddReceive(ushort id, long bytes)
|
||||
{
|
||||
messengerFlow.AddReceive(id, bytes);
|
||||
}
|
||||
public override void AddSendt(ushort id, ulong bytes)
|
||||
public override void AddSendt(ushort id, long bytes)
|
||||
{
|
||||
messengerFlow.AddSendt(id, bytes);
|
||||
}
|
||||
@@ -43,8 +43,8 @@ namespace linker.messenger.flow
|
||||
|
||||
public sealed class MessengerFlow : IFlow
|
||||
{
|
||||
public ulong ReceiveBytes { get; private set; }
|
||||
public ulong SendtBytes { get; private set; }
|
||||
public long ReceiveBytes { get; private set; }
|
||||
public long SendtBytes { get; private set; }
|
||||
public string FlowName => "Messenger";
|
||||
public VersionManager Version { get; } = new VersionManager();
|
||||
|
||||
@@ -56,10 +56,10 @@ namespace linker.messenger.flow
|
||||
|
||||
public string GetItems() => flows.ToJson();
|
||||
public void SetItems(string json) { flows = json.DeJson<Dictionary<ushort, FlowItemInfo>>(); }
|
||||
public void SetBytes(ulong receiveBytes, ulong sendtBytes) { ReceiveBytes = receiveBytes; SendtBytes = sendtBytes; }
|
||||
public void SetBytes(long receiveBytes, long sendtBytes) { ReceiveBytes = receiveBytes; SendtBytes = sendtBytes; }
|
||||
public void Clear() { ReceiveBytes = 0; SendtBytes = 0;flows.Clear(); }
|
||||
|
||||
public void AddReceive(ushort id, ulong bytes)
|
||||
public void AddReceive(ushort id, long bytes)
|
||||
{
|
||||
if (flows.TryGetValue(id, out FlowItemInfo messengerFlowItemInfo) == false)
|
||||
{
|
||||
@@ -70,7 +70,7 @@ namespace linker.messenger.flow
|
||||
messengerFlowItemInfo.ReceiveBytes += bytes;
|
||||
Version.Add();
|
||||
}
|
||||
public void AddSendt(ushort id, ulong bytes)
|
||||
public void AddSendt(ushort id, long bytes)
|
||||
{
|
||||
if (flows.TryGetValue(id, out FlowItemInfo messengerFlowItemInfo) == false)
|
||||
{
|
||||
|
@@ -7,8 +7,8 @@ namespace linker.messenger.flow
|
||||
{
|
||||
public sealed class RelayReportFlow : IFlow
|
||||
{
|
||||
public ulong ReceiveBytes { get; private set; }
|
||||
public ulong SendtBytes { get; private set; }
|
||||
public long ReceiveBytes { get; private set; }
|
||||
public long SendtBytes { get; private set; }
|
||||
public string FlowName => "RelayReport";
|
||||
public VersionManager Version { get; } = new VersionManager();
|
||||
public RelayReportFlow()
|
||||
@@ -16,11 +16,11 @@ namespace linker.messenger.flow
|
||||
}
|
||||
public string GetItems() => string.Empty;
|
||||
public void SetItems(string json) { }
|
||||
public void SetBytes(ulong receiveBytes, ulong sendtBytes) { ReceiveBytes = receiveBytes; SendtBytes = sendtBytes; }
|
||||
public void SetBytes(long receiveBytes, long sendtBytes) { ReceiveBytes = receiveBytes; SendtBytes = sendtBytes; }
|
||||
public void Clear() { ReceiveBytes = 0; SendtBytes = 0; }
|
||||
|
||||
public void AddReceive(ulong bytes) { ReceiveBytes += bytes; Version.Add(); }
|
||||
public void AddSendt(ulong bytes) { SendtBytes += bytes; Version.Add(); }
|
||||
public void AddReceive(long bytes) { ReceiveBytes += bytes; Version.Add(); }
|
||||
public void AddSendt(long bytes) { SendtBytes += bytes; Version.Add(); }
|
||||
|
||||
}
|
||||
|
||||
@@ -32,8 +32,8 @@ namespace linker.messenger.flow
|
||||
this.relayReportFlow = relayReportFlow;
|
||||
}
|
||||
|
||||
public override void AddReceive(ulong bytes) { relayReportFlow.AddReceive(bytes); }
|
||||
public override void AddSendt(ulong bytes) { relayReportFlow.AddSendt(bytes); }
|
||||
public override void AddReceive(long bytes) { relayReportFlow.AddReceive(bytes); }
|
||||
public override void AddSendt(long bytes) { relayReportFlow.AddSendt(bytes); }
|
||||
|
||||
}
|
||||
|
||||
@@ -47,19 +47,19 @@ namespace linker.messenger.flow
|
||||
this.relayFlow = relayFlow;
|
||||
}
|
||||
|
||||
public override void AddReceive(string key, string from, string to, string groupid, ulong bytes)
|
||||
public override void AddReceive(string key, string from, string to, string groupid, long bytes)
|
||||
{
|
||||
relayFlow.AddReceive(key, from, to, groupid, bytes);
|
||||
}
|
||||
public override void AddSendt(string key, string from, string to, string groupid, ulong bytes)
|
||||
public override void AddSendt(string key, string from, string to, string groupid, long bytes)
|
||||
{
|
||||
relayFlow.AddSendt(key, from, to, groupid, bytes);
|
||||
}
|
||||
public override void AddReceive(string key, ulong bytes)
|
||||
public override void AddReceive(string key, long bytes)
|
||||
{
|
||||
relayFlow.AddReceive(key, bytes);
|
||||
}
|
||||
public override void AddSendt(string key, ulong bytes)
|
||||
public override void AddSendt(string key, long bytes)
|
||||
{
|
||||
relayFlow.AddSendt(key, bytes);
|
||||
}
|
||||
@@ -68,8 +68,8 @@ namespace linker.messenger.flow
|
||||
|
||||
public sealed class RelayFlow : IFlow
|
||||
{
|
||||
public ulong ReceiveBytes { get; private set; }
|
||||
public ulong SendtBytes { get; private set; }
|
||||
public long ReceiveBytes { get; private set; }
|
||||
public long SendtBytes { get; private set; }
|
||||
public string FlowName => "Relay";
|
||||
public VersionManager Version { get; } = new VersionManager();
|
||||
|
||||
@@ -79,7 +79,7 @@ namespace linker.messenger.flow
|
||||
|
||||
public RelayFlow()
|
||||
{
|
||||
TimerHelper.SetInterval(() =>
|
||||
TimerHelper.SetIntervalLong(() =>
|
||||
{
|
||||
if (lastTicksManager.DiffLessEqual(5000))
|
||||
{
|
||||
@@ -103,10 +103,10 @@ namespace linker.messenger.flow
|
||||
|
||||
public string GetItems() => flows.ToJson();
|
||||
public void SetItems(string json) { flows = json.DeJson<Dictionary<string, RelayFlowItemInfo>>(); }
|
||||
public void SetBytes(ulong receiveBytes, ulong sendtBytes) { ReceiveBytes = receiveBytes; SendtBytes = sendtBytes; }
|
||||
public void SetBytes(long receiveBytes, long sendtBytes) { ReceiveBytes = receiveBytes; SendtBytes = sendtBytes; }
|
||||
public void Clear() { ReceiveBytes = 0; SendtBytes = 0;flows.Clear(); }
|
||||
|
||||
public void AddReceive(string key, string from, string to, string groupid, ulong bytes)
|
||||
public void AddReceive(string key, string from, string to, string groupid, long bytes)
|
||||
{
|
||||
if (flows.TryGetValue(key, out RelayFlowItemInfo messengerFlowItemInfo) == false)
|
||||
{
|
||||
@@ -117,7 +117,7 @@ namespace linker.messenger.flow
|
||||
messengerFlowItemInfo.ReceiveBytes += bytes;
|
||||
Version.Add();
|
||||
}
|
||||
public void AddSendt(string key, string from, string to, string groupid, ulong bytes)
|
||||
public void AddSendt(string key, string from, string to, string groupid, long bytes)
|
||||
{
|
||||
if (flows.TryGetValue(key, out RelayFlowItemInfo messengerFlowItemInfo) == false)
|
||||
{
|
||||
@@ -129,7 +129,7 @@ namespace linker.messenger.flow
|
||||
Version.Add();
|
||||
}
|
||||
|
||||
public void AddReceive(string key, ulong bytes)
|
||||
public void AddReceive(string key, long bytes)
|
||||
{
|
||||
if (flows.TryGetValue(key, out RelayFlowItemInfo messengerFlowItemInfo))
|
||||
{
|
||||
@@ -139,7 +139,7 @@ namespace linker.messenger.flow
|
||||
}
|
||||
|
||||
}
|
||||
public void AddSendt(string key, ulong bytes)
|
||||
public void AddSendt(string key, long bytes)
|
||||
{
|
||||
if (flows.TryGetValue(key, out RelayFlowItemInfo messengerFlowItemInfo))
|
||||
{
|
||||
@@ -201,17 +201,17 @@ namespace linker.messenger.flow
|
||||
|
||||
public sealed partial class RelayFlowItemInfo : FlowItemInfo
|
||||
{
|
||||
public ulong DiffReceiveBytes { get; set; }
|
||||
public ulong DiffSendtBytes { get; set; }
|
||||
public long DiffReceiveBytes { get; set; }
|
||||
public long DiffSendtBytes { get; set; }
|
||||
public string FromName { get; set; }
|
||||
public string ToName { get; set; }
|
||||
|
||||
public string GroupId { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public ulong OldReceiveBytes { get; set; }
|
||||
public long OldReceiveBytes { get; set; }
|
||||
[JsonIgnore]
|
||||
public ulong OldSendtBytes { get; set; }
|
||||
public long OldSendtBytes { get; set; }
|
||||
}
|
||||
|
||||
public sealed partial class RelayFlowRequestInfo
|
||||
|
@@ -12,11 +12,11 @@ namespace linker.messenger.flow
|
||||
{
|
||||
this.sForwardFlow = sForwardFlow;
|
||||
}
|
||||
public override void AddReceive(string key, string groupid, ulong bytes)
|
||||
public override void AddReceive(string key, string groupid, long bytes)
|
||||
{
|
||||
sForwardFlow.AddReceive(key, groupid, bytes);
|
||||
}
|
||||
public override void AddSendt(string key, string groupid, ulong bytes)
|
||||
public override void AddSendt(string key, string groupid, long bytes)
|
||||
{
|
||||
sForwardFlow.AddSendt(key, groupid, bytes);
|
||||
}
|
||||
@@ -24,8 +24,8 @@ namespace linker.messenger.flow
|
||||
|
||||
public sealed class SForwardFlow : IFlow
|
||||
{
|
||||
public ulong ReceiveBytes { get; private set; }
|
||||
public ulong SendtBytes { get; private set; }
|
||||
public long ReceiveBytes { get; private set; }
|
||||
public long SendtBytes { get; private set; }
|
||||
public string FlowName => "SForward";
|
||||
public VersionManager Version { get; } = new VersionManager();
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace linker.messenger.flow
|
||||
|
||||
public SForwardFlow()
|
||||
{
|
||||
TimerHelper.SetInterval(() =>
|
||||
TimerHelper.SetIntervalLong(() =>
|
||||
{
|
||||
if (lastTicksManager.DiffLessEqual(5000))
|
||||
{
|
||||
@@ -54,7 +54,7 @@ namespace linker.messenger.flow
|
||||
|
||||
public string GetItems() => flows.ToJson();
|
||||
public void SetItems(string json) { flows = json.DeJson<Dictionary<string, SForwardFlowItemInfo>>(); }
|
||||
public void SetBytes(ulong receiveBytes, ulong sendtBytes) { ReceiveBytes = receiveBytes; SendtBytes = sendtBytes; }
|
||||
public void SetBytes(long receiveBytes, long sendtBytes) { ReceiveBytes = receiveBytes; SendtBytes = sendtBytes; }
|
||||
public void Clear() { ReceiveBytes = 0; SendtBytes = 0;flows.Clear(); }
|
||||
|
||||
public void Update()
|
||||
@@ -62,7 +62,7 @@ namespace linker.messenger.flow
|
||||
lastTicksManager.Update();
|
||||
}
|
||||
|
||||
public void AddReceive(string key, string groupid, ulong bytes)
|
||||
public void AddReceive(string key, string groupid, long bytes)
|
||||
{
|
||||
if (flows.TryGetValue(key, out SForwardFlowItemInfo messengerFlowItemInfo) == false)
|
||||
{
|
||||
@@ -73,7 +73,7 @@ namespace linker.messenger.flow
|
||||
messengerFlowItemInfo.ReceiveBytes += bytes;
|
||||
Version.Add();
|
||||
}
|
||||
public void AddSendt(string key, string groupid, ulong bytes)
|
||||
public void AddSendt(string key, string groupid, long bytes)
|
||||
{
|
||||
if (flows.TryGetValue(key, out SForwardFlowItemInfo messengerFlowItemInfo) == false)
|
||||
{
|
||||
@@ -134,16 +134,16 @@ namespace linker.messenger.flow
|
||||
|
||||
public sealed partial class SForwardFlowItemInfo : FlowItemInfo
|
||||
{
|
||||
public ulong DiffReceiveBytes { get; set; }
|
||||
public ulong DiffSendtBytes { get; set; }
|
||||
public long DiffReceiveBytes { get; set; }
|
||||
public long DiffSendtBytes { get; set; }
|
||||
public string Key { get; set; }
|
||||
|
||||
public string GroupId { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public ulong OldReceiveBytes { get; set; }
|
||||
public long OldReceiveBytes { get; set; }
|
||||
[JsonIgnore]
|
||||
public ulong OldSendtBytes { get; set; }
|
||||
public long OldSendtBytes { get; set; }
|
||||
}
|
||||
|
||||
public sealed partial class SForwardFlowRequestInfo
|
||||
|
@@ -38,7 +38,7 @@ namespace linker.messenger.flow.messenger
|
||||
Dictionary<string, FlowItemInfo> dic = flowTransfer.GetFlows();
|
||||
|
||||
signCaching.GetOnline(out int all, out int online);
|
||||
dic.TryAdd("_", new FlowItemInfo { FlowName = "_", ReceiveBytes = (ulong)all, SendtBytes = (ulong)online });
|
||||
dic.TryAdd("_", new FlowItemInfo { FlowName = "_", ReceiveBytes = all, SendtBytes = online });
|
||||
|
||||
FlowInfo serverFlowInfo = new FlowInfo
|
||||
{
|
||||
|
@@ -7,7 +7,7 @@ namespace linker.messenger.forward
|
||||
public sealed partial class ForwardInfo
|
||||
{
|
||||
public ForwardInfo() { }
|
||||
public uint Id { get; set; }
|
||||
public long Id { get; set; }
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
@@ -60,7 +60,7 @@ namespace linker.messenger.forward
|
||||
public sealed partial class ForwardRemoveForwardInfo
|
||||
{
|
||||
public string MachineId { get; set; }
|
||||
public uint Id { get; set; }
|
||||
public long Id { get; set; }
|
||||
}
|
||||
public sealed partial class ForwardCountInfo
|
||||
{
|
||||
|
@@ -18,9 +18,6 @@ namespace linker.messenger.forward
|
||||
private readonly IMessengerSender messengerSender;
|
||||
private readonly ISignInClientStore signInClientStore;
|
||||
private readonly ISerializer serializer;
|
||||
|
||||
private readonly NumberSpaceUInt32 ns = new NumberSpaceUInt32();
|
||||
|
||||
public ForwardTransfer(IForwardClientStore forwardClientStore, ForwardProxy forwardProxy, SignInClientState signInClientState, IMessengerSender messengerSender, ISignInClientStore signInClientStore, ISerializer serializer)
|
||||
{
|
||||
this.forwardClientStore = forwardClientStore;
|
||||
@@ -54,9 +51,6 @@ namespace linker.messenger.forward
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
uint maxid = forwardClientStore.Count() > 0 ? forwardClientStore.Get().Max(c => c.Id) : 1;
|
||||
ns.Reset(maxid);
|
||||
|
||||
foreach (var item in forwardClientStore.Get(signInClientStore.Group.Id))
|
||||
{
|
||||
if (item.Started)
|
||||
@@ -149,7 +143,7 @@ namespace linker.messenger.forward
|
||||
public bool Add(ForwardInfo forwardInfo)
|
||||
{
|
||||
//同名或者同端口,但是ID不一样
|
||||
ForwardInfo old = forwardClientStore.Get().FirstOrDefault(c => (c.Port == forwardInfo.Port && c.Port != 0) && c.MachineId == forwardInfo.MachineId);
|
||||
ForwardInfo old = forwardClientStore.Get().FirstOrDefault(c => (c.Port == forwardInfo.Port && c.Port != 0) && c.GroupId == signInClientStore.Group.Id && c.MachineId == forwardInfo.MachineId);
|
||||
if (old != null && old.Id != forwardInfo.Id) return false;
|
||||
|
||||
if (forwardInfo.Id != 0)
|
||||
@@ -169,10 +163,10 @@ namespace linker.messenger.forward
|
||||
old.Started = forwardInfo.Started;
|
||||
old.BufferSize = forwardInfo.BufferSize;
|
||||
old.GroupId = signInClientStore.Group.Id;
|
||||
forwardClientStore.Update(forwardInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
forwardInfo.Id = ns.Increment();
|
||||
forwardInfo.GroupId = signInClientStore.Group.Id;
|
||||
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
@@ -186,7 +180,7 @@ namespace linker.messenger.forward
|
||||
|
||||
return true;
|
||||
}
|
||||
public bool Remove(uint id)
|
||||
public bool Remove(long id)
|
||||
{
|
||||
//同名或者同端口,但是ID不一样
|
||||
ForwardInfo old = forwardClientStore.Get(id);
|
||||
|
@@ -18,7 +18,7 @@
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
public ForwardInfo Get(uint id);
|
||||
public ForwardInfo Get(long id);
|
||||
/// <summary>
|
||||
/// 根据分组获取
|
||||
/// </summary>
|
||||
@@ -42,7 +42,7 @@
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
public bool Remove(uint id);
|
||||
public bool Remove(long id);
|
||||
|
||||
/// <summary>
|
||||
/// 提交更新
|
||||
|
@@ -270,7 +270,7 @@ namespace linker.messenger.forward.proxy
|
||||
/// </summary>
|
||||
private void TaskUdp()
|
||||
{
|
||||
TimerHelper.SetInterval(() =>
|
||||
TimerHelper.SetIntervalLong(() =>
|
||||
{
|
||||
if(udpConnections.Count > 0)
|
||||
{
|
||||
|
@@ -69,7 +69,7 @@ namespace linker.messenger.logger
|
||||
{
|
||||
}
|
||||
};
|
||||
TimerHelper.SetInterval(() =>
|
||||
TimerHelper.SetIntervalLong(() =>
|
||||
{
|
||||
string[] files = Directory.GetFiles("logs").OrderBy(c => c).ToArray();
|
||||
for (int i = 0; i < files.Length - 180; i++)
|
||||
|
@@ -72,7 +72,7 @@ namespace linker.messenger.relay
|
||||
[Access(AccessValue.RelayCdkey)]
|
||||
public async Task<bool> AddCdkey(ApiControllerParamsInfo param)
|
||||
{
|
||||
RelayServerCdkeyInfo info = param.Content.DeJson<RelayServerCdkeyInfo>();
|
||||
RelayServerCdkeyStoreInfo info = param.Content.DeJson<RelayServerCdkeyStoreInfo>();
|
||||
var resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||
{
|
||||
Connection = signInClientState.Connection,
|
||||
@@ -96,7 +96,7 @@ namespace linker.messenger.relay
|
||||
MessengerId = (ushort)RelayMessengerIds.DelCdkey,
|
||||
Payload = serializer.Serialize(new RelayServerCdkeyDelInfo
|
||||
{
|
||||
Id = param.Content,
|
||||
CdkeyId = long.Parse(param.Content),
|
||||
SecretKey = relayClientStore.Server.SecretKey
|
||||
})
|
||||
});
|
||||
|
@@ -66,14 +66,14 @@ namespace linker.messenger.relay
|
||||
}
|
||||
private void TestTask()
|
||||
{
|
||||
TimerHelper.SetInterval(async () =>
|
||||
TimerHelper.SetIntervalLong(async () =>
|
||||
{
|
||||
if (lastTicksManager.DiffLessEqual(3000))
|
||||
{
|
||||
await TaskRelay();
|
||||
}
|
||||
return true;
|
||||
}, () => 3000);
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -5,6 +5,7 @@ using linker.messenger.relay.client;
|
||||
using linker.messenger.relay.server;
|
||||
using linker.messenger.signin;
|
||||
using linker.messenger.relay.server.validator;
|
||||
using linker.libs.extends;
|
||||
|
||||
namespace linker.messenger.relay.messenger
|
||||
{
|
||||
@@ -81,7 +82,7 @@ namespace linker.messenger.relay.messenger
|
||||
TransportName = "test",
|
||||
}, cache, null);
|
||||
|
||||
var nodes = relayServerTransfer.GetNodes(string.IsNullOrWhiteSpace(result), info.UserId);
|
||||
var nodes = relayServerTransfer.GetNodes(string.IsNullOrWhiteSpace(result));
|
||||
connection.Write(serializer.Serialize(nodes));
|
||||
}
|
||||
|
||||
@@ -110,11 +111,11 @@ namespace linker.messenger.relay.messenger
|
||||
bool validated = string.IsNullOrWhiteSpace(error);
|
||||
result.Nodes = relayServerTransfer.GetNodes(validated);
|
||||
|
||||
List<RelayServerCdkeyInfo> cdkeys = await relayServerCdkeyStore.Get(info.UserId);
|
||||
List<RelayServerCdkeyStoreInfo> cdkeys = await relayServerCdkeyStore.GetAvailable(info.UserId);
|
||||
|
||||
if (result.Nodes.Count > 0)
|
||||
{
|
||||
result.FlowingId = relayServerTransfer.AddRelay(cacheFrom.MachineId, cacheFrom.MachineName, cacheTo.MachineId, cacheTo.MachineName, cacheFrom.GroupId, validated, cdkeys);
|
||||
result.FlowingId = relayServerTransfer.AddRelay(cacheFrom.MachineId, cacheFrom.MachineName, cacheTo.MachineId, cacheTo.MachineName, cacheFrom.GroupId, validated, cdkeys.Select(c => new RelayServerCdkeyInfo { Bandwidth = c.Bandwidth, CdkeyId = c.CdkeyId, LastBytes = c.LastBytes }).ToList());
|
||||
}
|
||||
|
||||
connection.Write(serializer.Serialize(result));
|
||||
@@ -230,7 +231,7 @@ namespace linker.messenger.relay.messenger
|
||||
return;
|
||||
}
|
||||
|
||||
await relayServerCdkeyStore.Del(info.Id);
|
||||
await relayServerCdkeyStore.Del(info.CdkeyId);
|
||||
connection.Write(Helper.TrueArray);
|
||||
}
|
||||
|
||||
@@ -266,9 +267,17 @@ namespace linker.messenger.relay.messenger
|
||||
/// <param name="connection"></param>
|
||||
/// <returns></returns>
|
||||
[MessengerId((ushort)RelayMessengerIds.NodeGetCache)]
|
||||
public async Task NodeGetCache(IConnection connection)
|
||||
public void NodeGetCache(IConnection connection)
|
||||
{
|
||||
|
||||
string key = serializer.Deserialize<string>(connection.ReceiveRequestWrap.Payload.Span);
|
||||
if (relayServerTransfer.TryGetRelayCache(key, out RelayCacheInfo cache))
|
||||
{
|
||||
connection.Write(serializer.Serialize(cache));
|
||||
}
|
||||
else
|
||||
{
|
||||
connection.Write(Helper.EmptyArray);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取缓存
|
||||
@@ -276,9 +285,14 @@ namespace linker.messenger.relay.messenger
|
||||
/// <param name="connection"></param>
|
||||
/// <returns></returns>
|
||||
[MessengerId((ushort)RelayMessengerIds.NodeReport)]
|
||||
public async Task NodeReport(IConnection connection)
|
||||
public void NodeReport(IConnection connection)
|
||||
{
|
||||
|
||||
RelayServerNodeReportInfo info = serializer.Deserialize<RelayServerNodeReportInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
{
|
||||
LoggerHelper.Instance.Debug($"relay node report : {info.ToJson()}");
|
||||
}
|
||||
relayServerTransfer.SetNodeReport(connection, info);
|
||||
}
|
||||
/// <summary>
|
||||
/// 消耗流量报告
|
||||
@@ -288,12 +302,14 @@ namespace linker.messenger.relay.messenger
|
||||
[MessengerId((ushort)RelayMessengerIds.TrafficReport)]
|
||||
public async Task TrafficReport(IConnection connection)
|
||||
{
|
||||
RelayTrafficReportInfo info = serializer.Deserialize<RelayTrafficReportInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||
if (relayServerStore.SecretKey != info.SecretKey )
|
||||
RelayTrafficUpdateInfo info = serializer.Deserialize<RelayTrafficUpdateInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||
if (relayServerStore.SecretKey != info.SecretKey)
|
||||
{
|
||||
connection.Write(serializer.Serialize(new Dictionary<string,ulong>()));
|
||||
connection.Write(serializer.Serialize(new Dictionary<string, long>()));
|
||||
return;
|
||||
}
|
||||
Dictionary<long, long> result = await relayServerTransfer.AddTraffic(info);
|
||||
connection.Write(serializer.Serialize(result));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,18 +2,41 @@
|
||||
{
|
||||
public interface IRelayServerCdkeyStore
|
||||
{
|
||||
public Task<bool> Add(RelayServerCdkeyInfo info);
|
||||
public Task<bool> Del(string id);
|
||||
public Task<bool> Add(RelayServerCdkeyStoreInfo info);
|
||||
public Task<bool> Del(long id);
|
||||
|
||||
/// <summary>
|
||||
/// 获取有效的CDKEY
|
||||
/// </summary>
|
||||
/// <param name="userid"></param>
|
||||
/// <returns></returns>
|
||||
public Task<List<RelayServerCdkeyInfo>> Get(string userid);
|
||||
public Task<List<RelayServerCdkeyStoreInfo>> GetAvailable(string userid);
|
||||
public Task<List<RelayServerCdkeyStoreInfo>> Get(List<long> ids);
|
||||
|
||||
public Task<bool> Traffic(Dictionary<long, long> dic);
|
||||
public Task<RelayServerCdkeyPageResultInfo> Get(RelayServerCdkeyPageRequestInfo relayServerCdkeyPageRequestInfo);
|
||||
}
|
||||
|
||||
public sealed class RelayServerCdkeyConfigInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取可用的CDKEY
|
||||
/// </summary>
|
||||
public string CdkeyAvailablePostUrl { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// 分页获取CDKEY
|
||||
/// </summary>
|
||||
public string CdkeyPagePostUrl { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// id列表获取CDKEY
|
||||
/// </summary>
|
||||
public string CdkeyListPostUrl { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// 报告流量websocket
|
||||
/// </summary>
|
||||
public string CdkeyTrafficWsUrl { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public sealed partial class RelayServerCdkeyPageRequestInfo
|
||||
{
|
||||
public int Page { get; set; }
|
||||
@@ -29,24 +52,24 @@
|
||||
public int Page { get; set; }
|
||||
public int Size { get; set; }
|
||||
public int Count { get; set; }
|
||||
public List<RelayServerCdkeyInfo> List { get; set; }
|
||||
public List<RelayServerCdkeyStoreInfo> List { get; set; }
|
||||
}
|
||||
|
||||
public sealed partial class RelayServerCdkeyAddInfo
|
||||
{
|
||||
public string SecretKey { get; set; }
|
||||
public RelayServerCdkeyInfo Data { get; set; }
|
||||
public RelayServerCdkeyStoreInfo Data { get; set; }
|
||||
}
|
||||
public sealed partial class RelayServerCdkeyDelInfo
|
||||
{
|
||||
public string SecretKey { get; set; }
|
||||
public string Id { get; set; }
|
||||
public long CdkeyId { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 中继CDKEY
|
||||
/// 中继CDKEY存储
|
||||
/// </summary>
|
||||
public sealed partial class RelayServerCdkeyInfo
|
||||
public sealed partial class RelayServerCdkeyStoreInfo : RelayServerCdkeyInfo
|
||||
{
|
||||
public string Id { get; set; }
|
||||
|
||||
@@ -72,21 +95,17 @@
|
||||
/// </summary>
|
||||
public DateTime EndTime { get; set; }
|
||||
/// <summary>
|
||||
/// 最后使用时间
|
||||
/// </summary>
|
||||
public DateTime UseTime { get; set; }
|
||||
/// <summary>
|
||||
/// 允许节点
|
||||
/// </summary>
|
||||
public List<string> Nodes { get; set; }
|
||||
/// <summary>
|
||||
/// 带宽Mbps
|
||||
/// </summary>
|
||||
public double Bandwidth { get; set; }
|
||||
/// <summary>
|
||||
/// 流量
|
||||
/// </summary>
|
||||
public ulong MaxBytes { get; set; }
|
||||
/// <summary>
|
||||
/// 剩余流量
|
||||
/// </summary>
|
||||
public ulong LastBytes { get; set; }
|
||||
public long MaxBytes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 原价
|
||||
|
@@ -33,7 +33,7 @@ namespace linker.messenger.relay.server
|
||||
/// 设置剩余流量
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public void SetMaxGbTotalLastBytes(ulong value);
|
||||
public void SetMaxGbTotalLastBytes(long value);
|
||||
/// <summary>
|
||||
/// 提交保存
|
||||
/// </summary>
|
||||
@@ -68,7 +68,7 @@ namespace linker.messenger.relay.server
|
||||
public double MaxBandwidth { get; set; }
|
||||
public double MaxBandwidthTotal { get; set; }
|
||||
public double MaxGbTotal { get; set; }
|
||||
public ulong MaxGbTotalLastBytes { get; set; }
|
||||
public long MaxGbTotalLastBytes { get; set; }
|
||||
public int MaxGbTotalMonth { get; set; }
|
||||
|
||||
public bool Public { get; set; }
|
||||
@@ -79,8 +79,6 @@ namespace linker.messenger.relay.server
|
||||
#else
|
||||
public string MasterSecretKey { get; set; } = string.Empty;
|
||||
#endif
|
||||
|
||||
public List<string> UserIds { get; set; } = new List<string>();
|
||||
}
|
||||
|
||||
public sealed partial class RelayServerNodeReportInfo
|
||||
@@ -92,7 +90,7 @@ namespace linker.messenger.relay.server
|
||||
public double MaxBandwidth { get; set; }
|
||||
public double MaxBandwidthTotal { get; set; }
|
||||
public double MaxGbTotal { get; set; }
|
||||
public ulong MaxGbTotalLastBytes { get; set; }
|
||||
public long MaxGbTotalLastBytes { get; set; }
|
||||
|
||||
public double ConnectionRatio { get; set; }
|
||||
public double BandwidthRatio { get; set; }
|
||||
@@ -104,8 +102,6 @@ namespace linker.messenger.relay.server
|
||||
public IPEndPoint EndPoint { get; set; }
|
||||
|
||||
public long LastTicks { get; set; }
|
||||
|
||||
public List<string> UserIds { get; set; } = new List<string>();
|
||||
}
|
||||
|
||||
|
||||
|
@@ -13,14 +13,17 @@ namespace linker.messenger.relay.server
|
||||
|
||||
private ulong relayFlowingId = 0;
|
||||
private readonly ConcurrentDictionary<string, RelayServerNodeReportInfo> reports = new ConcurrentDictionary<string, RelayServerNodeReportInfo>();
|
||||
|
||||
private readonly ConcurrentQueue<Dictionary<long, long>> trafficQueue = new ConcurrentQueue<Dictionary<long, long>>();
|
||||
|
||||
private readonly IRelayServerCaching relayCaching;
|
||||
private readonly ISerializer serializer;
|
||||
public RelayServerMasterTransfer(IRelayServerCaching relayCaching, ISerializer serializer, IRelayServerMasterStore relayServerMasterStore)
|
||||
private readonly IRelayServerCdkeyStore relayServerCdkeyStore;
|
||||
public RelayServerMasterTransfer(IRelayServerCaching relayCaching, ISerializer serializer, IRelayServerMasterStore relayServerMasterStore, IRelayServerCdkeyStore relayServerCdkeyStore)
|
||||
{
|
||||
this.relayCaching = relayCaching;
|
||||
this.serializer = serializer;
|
||||
this.relayServerCdkeyStore = relayServerCdkeyStore;
|
||||
TrafficTask();
|
||||
}
|
||||
|
||||
|
||||
@@ -82,10 +85,10 @@ namespace linker.messenger.relay.server
|
||||
/// </summary>
|
||||
/// <param name="validated">是否已认证</param>
|
||||
/// <returns></returns>
|
||||
public List<RelayServerNodeReportInfo> GetNodes(bool validated, string userid)
|
||||
public List<RelayServerNodeReportInfo> GetNodes(bool validated)
|
||||
{
|
||||
var result = reports.Values
|
||||
.Where(c => c.Public || (c.Public == false && validated) || c.UserIds.Contains(userid))
|
||||
.Where(c => c.Public || validated)
|
||||
.Where(c => Environment.TickCount64 - c.LastTicks < 15000)
|
||||
.Where(c => c.ConnectionRatio < 100 && (c.MaxGbTotal == 0 || (c.MaxGbTotal > 0 && c.MaxGbTotalLastBytes > 0)))
|
||||
.OrderByDescending(c => c.LastTicks);
|
||||
@@ -96,7 +99,7 @@ namespace linker.messenger.relay.server
|
||||
.ThenByDescending(x => x.MaxBandwidth == 0 ? double.MaxValue : x.MaxBandwidth)
|
||||
.ThenByDescending(x => x.MaxBandwidthTotal == 0 ? double.MaxValue : x.MaxBandwidthTotal)
|
||||
.ThenByDescending(x => x.MaxGbTotal == 0 ? double.MaxValue : x.MaxGbTotal)
|
||||
.ThenByDescending(x => x.MaxGbTotalLastBytes == 0 ? ulong.MaxValue : x.MaxGbTotalLastBytes)
|
||||
.ThenByDescending(x => x.MaxGbTotalLastBytes == 0 ? long.MaxValue : x.MaxGbTotalLastBytes)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
@@ -109,7 +112,29 @@ namespace linker.messenger.relay.server
|
||||
{
|
||||
return reports.TryGetValue(nodeId, out RelayServerNodeReportInfo relayNodeReportInfo) && relayNodeReportInfo.Public == false;
|
||||
}
|
||||
|
||||
|
||||
public async Task<Dictionary<long, long>> AddTraffic(RelayTrafficUpdateInfo relayTrafficUpdateInfo)
|
||||
{
|
||||
if (relayTrafficUpdateInfo.Dic.Count > 0)
|
||||
trafficQueue.Enqueue(relayTrafficUpdateInfo.Dic);
|
||||
|
||||
if (relayTrafficUpdateInfo.Ids == null || relayTrafficUpdateInfo.Ids.Count == 0)
|
||||
{
|
||||
return new Dictionary<long, long>();
|
||||
}
|
||||
return (await relayServerCdkeyStore.Get(relayTrafficUpdateInfo.Ids)).ToDictionary(c => c.CdkeyId, c => c.LastBytes);
|
||||
}
|
||||
private void TrafficTask()
|
||||
{
|
||||
TimerHelper.SetIntervalLong(async () =>
|
||||
{
|
||||
while (trafficQueue.TryDequeue(out Dictionary<long, long> dic))
|
||||
{
|
||||
await relayServerCdkeyStore.Traffic(dic).ConfigureAwait(false);
|
||||
}
|
||||
return true;
|
||||
},3000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -5,7 +5,6 @@ using System.Buffers;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace linker.messenger.relay.server
|
||||
{
|
||||
@@ -18,11 +17,11 @@ namespace linker.messenger.relay.server
|
||||
private IConnection localConnection;
|
||||
private IConnection remoteConnection;
|
||||
|
||||
private ulong bytes = 0;
|
||||
private ulong lastBytes = 0;
|
||||
RelaySpeedLimit limitTotal = new RelaySpeedLimit();
|
||||
private long bytes = 0;
|
||||
private long lastBytes = 0;
|
||||
private RelaySpeedLimit limitTotal = new RelaySpeedLimit();
|
||||
private readonly ConcurrentDictionary<ulong, RelayTrafficCacheInfo> trafficDict = new ConcurrentDictionary<ulong, RelayTrafficCacheInfo>();
|
||||
private readonly ConcurrentDictionary<string, ulong> cdkeyLastBytes = new ConcurrentDictionary<string, ulong>();
|
||||
private readonly ConcurrentDictionary<long, long> cdkeyLastBytes = new ConcurrentDictionary<long, long>();
|
||||
|
||||
private readonly ISerializer serializer;
|
||||
private readonly IRelayServerNodeStore relayServerNodeStore;
|
||||
@@ -50,7 +49,7 @@ namespace linker.messenger.relay.server
|
||||
{
|
||||
try
|
||||
{
|
||||
IConnection connection = nodeid == RelayServerNodeInfo.MASTER_NODE_ID ? localConnection : remoteConnection;
|
||||
IConnection connection = relayServerNodeStore.Node.Id == RelayServerNodeInfo.MASTER_NODE_ID ? localConnection : remoteConnection;
|
||||
|
||||
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||
{
|
||||
@@ -133,6 +132,7 @@ namespace linker.messenger.relay.server
|
||||
public bool NeedLimit(RelayTrafficCacheInfo relayCache)
|
||||
{
|
||||
if (relayCache.Cache.Validated) return false;
|
||||
//if (relayCache.CurrentCdkey != null) return false;
|
||||
return limitTotal.NeedLimit();
|
||||
}
|
||||
/// <summary>
|
||||
@@ -164,7 +164,7 @@ namespace linker.messenger.relay.server
|
||||
trafficDict.TryRemove(relayCache.Cache.FlowId, out _);
|
||||
foreach (var item in relayCache.Cache.Cdkey)
|
||||
{
|
||||
cdkeyLastBytes.TryRemove(item.Id, out _);
|
||||
cdkeyLastBytes.TryRemove(item.CdkeyId, out _);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
@@ -172,7 +172,7 @@ namespace linker.messenger.relay.server
|
||||
/// </summary>
|
||||
/// <param name="length"></param>
|
||||
/// <returns></returns>
|
||||
public bool AddBytes(RelayTrafficCacheInfo cache, ulong length)
|
||||
public bool AddBytes(RelayTrafficCacheInfo cache, long length)
|
||||
{
|
||||
Interlocked.Add(ref bytes, length);
|
||||
|
||||
@@ -194,20 +194,13 @@ namespace linker.messenger.relay.server
|
||||
/// <param name="relayCache"></param>
|
||||
private void SetLimit(RelayTrafficCacheInfo relayCache)
|
||||
{
|
||||
//验证过的,无限制
|
||||
if (relayCache.Cache.Validated)
|
||||
//无限制
|
||||
if (relayCache.Cache.Validated || relayServerNodeStore.Node.MaxBandwidth == 0)
|
||||
{
|
||||
relayCache.Limit.SetLimit(0);
|
||||
return;
|
||||
}
|
||||
|
||||
//节点无限制
|
||||
if (relayServerNodeStore.Node.MaxBandwidth == 0)
|
||||
{
|
||||
relayCache.Limit.SetLimit((uint)Math.Ceiling((relayServerNodeStore.Node.MaxBandwidth * 1024 * 1024) / 8.0));
|
||||
return;
|
||||
}
|
||||
|
||||
RelayServerCdkeyInfo currentCdkey = relayCache.Cache.Cdkey.Where(c => c.LastBytes > 0).OrderByDescending(c => c.Bandwidth).FirstOrDefault();
|
||||
//有cdkey,且带宽大于节点带宽,就用cdkey的带宽
|
||||
if (currentCdkey != null && (currentCdkey.Bandwidth == 0 || currentCdkey.Bandwidth > relayServerNodeStore.Node.MaxBandwidth))
|
||||
@@ -220,91 +213,129 @@ namespace linker.messenger.relay.server
|
||||
relayCache.Limit.SetLimit((uint)Math.Ceiling((relayServerNodeStore.Node.MaxBandwidth * 1024 * 1024) / 8.0));
|
||||
}
|
||||
|
||||
private void ResetNodeBytes(ulong length)
|
||||
private void ResetNodeBytes()
|
||||
{
|
||||
if (relayServerNodeStore.Node.MaxGbTotalLastBytes >= length)
|
||||
relayServerNodeStore.SetMaxGbTotalLastBytes(relayServerNodeStore.Node.MaxGbTotalLastBytes - length);
|
||||
else relayServerNodeStore.SetMaxGbTotalLastBytes(0);
|
||||
|
||||
foreach (var cache in trafficDict.Values.Where(c => c.CurrentCdkey == null))
|
||||
{
|
||||
long length = cache.Sendt;
|
||||
Interlocked.Exchange(ref cache.Sendt, 0);
|
||||
if (relayServerNodeStore.Node.MaxGbTotalLastBytes >= length)
|
||||
relayServerNodeStore.SetMaxGbTotalLastBytes(relayServerNodeStore.Node.MaxGbTotalLastBytes - length);
|
||||
else relayServerNodeStore.SetMaxGbTotalLastBytes(0);
|
||||
}
|
||||
if (relayServerNodeStore.Node.MaxGbTotalMonth != DateTime.Now.Month)
|
||||
{
|
||||
relayServerNodeStore.SetMaxGbTotalMonth(DateTime.Now.Month);
|
||||
relayServerNodeStore.SetMaxGbTotalLastBytes((ulong)(relayServerNodeStore.Node.MaxGbTotal * 1024 * 1024 * 1024));
|
||||
relayServerNodeStore.SetMaxGbTotalLastBytes((long)(relayServerNodeStore.Node.MaxGbTotal * 1024 * 1024 * 1024));
|
||||
}
|
||||
relayServerNodeStore.Confirm();
|
||||
}
|
||||
private void TrafficTask()
|
||||
private void DownloadBytes()
|
||||
{
|
||||
TimerHelper.SetInterval(async () =>
|
||||
TimerHelper.Async(async () =>
|
||||
{
|
||||
//需要报告Cdkey的流量
|
||||
_ = messengerSender.SendReply(new MessageRequestWrap
|
||||
List<long> ids = trafficDict.Values.SelectMany(c => c.Cache.Cdkey).Select(c => c.CdkeyId).Distinct().ToList();
|
||||
while (ids.Count > 0)
|
||||
{
|
||||
//分批更新,可能数量很大
|
||||
List<long> id = ids.Take(100).ToList();
|
||||
ids.RemoveRange(0, id.Count);
|
||||
|
||||
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||
{
|
||||
Connection = relayServerNodeStore.Node.Id == RelayServerNodeInfo.MASTER_NODE_ID ? localConnection : remoteConnection,
|
||||
MessengerId = (ushort)RelayMessengerIds.TrafficReport,
|
||||
Payload = serializer.Serialize(new RelayTrafficUpdateInfo
|
||||
{
|
||||
Dic = [],
|
||||
Ids = id,
|
||||
SecretKey = relayServerNodeStore.Node.Id == RelayServerNodeInfo.MASTER_NODE_ID
|
||||
? relayServerMasterStore.Master.SecretKey
|
||||
: relayServerNodeStore.Node.MasterSecretKey
|
||||
}),
|
||||
Timeout = 4000
|
||||
});
|
||||
|
||||
if (resp.Code == MessageResponeCodes.OK && resp.Data.Length > 0)
|
||||
{
|
||||
Dictionary<long, long> dic = serializer.Deserialize<Dictionary<long, long>>(resp.Data.Span);
|
||||
//更新剩余流量
|
||||
foreach (KeyValuePair<long, long> item in dic)
|
||||
{
|
||||
cdkeyLastBytes.AddOrUpdate(item.Key, item.Value, (a, b) => item.Value);
|
||||
}
|
||||
//查不到的,归零
|
||||
foreach (long item in id.Except(dic.Keys))
|
||||
{
|
||||
cdkeyLastBytes.AddOrUpdate(item, 0, (a, b) => 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
private void UploadBytes()
|
||||
{
|
||||
TimerHelper.Async(async () =>
|
||||
{
|
||||
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||
{
|
||||
Connection = relayServerNodeStore.Node.Id == RelayServerNodeInfo.MASTER_NODE_ID ? localConnection : remoteConnection,
|
||||
MessengerId = (ushort)RelayMessengerIds.TrafficReport,
|
||||
Payload = serializer.Serialize(new RelayTrafficReportInfo
|
||||
Payload = serializer.Serialize(new RelayTrafficUpdateInfo
|
||||
{
|
||||
Id2Bytes = trafficDict.Values
|
||||
.Where(c => c.CurrentCdkey != null && c.Sendt > 0)
|
||||
.GroupBy(c => c.CurrentCdkey.Id)
|
||||
.ToDictionary(c => c.Key, d => (ulong)d.Sum(d => (decimal)d.Sendt)),
|
||||
UpdateIds = trafficDict.Values.SelectMany(c => c.Cache.Cdkey).Select(c => c.Id).Distinct().ToList(),
|
||||
Dic = trafficDict.Values.Where(c => c.CurrentCdkey != null && c.Sendt > 0).GroupBy(c => c.CurrentCdkey.CdkeyId).ToDictionary(c => c.Key, d => d.Sum(d => d.Sendt)),
|
||||
Ids = [],
|
||||
SecretKey = relayServerNodeStore.Node.Id == RelayServerNodeInfo.MASTER_NODE_ID
|
||||
? relayServerMasterStore.Master.SecretKey
|
||||
: relayServerNodeStore.Node.MasterSecretKey
|
||||
? relayServerMasterStore.Master.SecretKey
|
||||
: relayServerNodeStore.Node.MasterSecretKey
|
||||
}),
|
||||
Timeout = 4000,
|
||||
|
||||
}).ContinueWith((result) =>
|
||||
{
|
||||
//更新cdkey的剩余流量
|
||||
if (result.Result.Code != MessageResponeCodes.OK || result.Result.Data.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Dictionary<string, ulong> dic = serializer.Deserialize<Dictionary<string, ulong>>(result.Result.Data.Span);
|
||||
foreach (var item in dic)
|
||||
{
|
||||
cdkeyLastBytes.AddOrUpdate(item.Key, item.Value, (a, b) => item.Value);
|
||||
}
|
||||
Timeout = 4000
|
||||
});
|
||||
|
||||
foreach (var cache in trafficDict.Values.Where(c => c.CurrentCdkey != null))
|
||||
if (resp.Code == MessageResponeCodes.OK)
|
||||
{
|
||||
ulong length = cache.Sendt;
|
||||
Interlocked.Add(ref Unsafe.As<ulong, long>(ref cache.Sendt), -(long)length);
|
||||
|
||||
if (cdkeyLastBytes.TryGetValue(cache.CurrentCdkey.Id, out ulong value))
|
||||
try
|
||||
{
|
||||
cache.CurrentCdkey.LastBytes = value;
|
||||
serializer.Deserialize<Dictionary<string, ulong>>(resp.Data.Span);
|
||||
//成功报告了流量,就重新计数
|
||||
foreach (var cache in trafficDict.Values.Where(c => c.CurrentCdkey != null))
|
||||
{
|
||||
Interlocked.Exchange(ref cache.Sendt, 0);
|
||||
//检查一下是不是需要更新剩余流量
|
||||
if (cdkeyLastBytes.TryGetValue(cache.CurrentCdkey.CdkeyId, out long value))
|
||||
{
|
||||
cache.CurrentCdkey.LastBytes = value;
|
||||
}
|
||||
//当前cdkey流量用完了,就重新找找新的cdkey
|
||||
if (cache.CurrentCdkey.LastBytes <= 0)
|
||||
{
|
||||
SetLimit(cache);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cache.CurrentCdkey.LastBytes <= 0)
|
||||
catch (Exception)
|
||||
{
|
||||
SetLimit(cache);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
private void TrafficTask()
|
||||
{
|
||||
TimerHelper.SetIntervalLong(() =>
|
||||
{
|
||||
UploadBytes();
|
||||
DownloadBytes();
|
||||
|
||||
foreach (var cache in trafficDict.Values.Where(c => c.CurrentCdkey == null))
|
||||
{
|
||||
ulong length = cache.Sendt;
|
||||
Interlocked.Add(ref Unsafe.As<ulong, long>(ref cache.Sendt), -(long)length);
|
||||
ResetNodeBytes(length);
|
||||
}
|
||||
await Task.CompletedTask;
|
||||
ResetNodeBytes();
|
||||
|
||||
return true;
|
||||
}, () => 5000);
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
private void ReportTask()
|
||||
{
|
||||
TimerHelper.SetInterval(async () =>
|
||||
TimerHelper.SetIntervalLong(async () =>
|
||||
{
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
{
|
||||
LoggerHelper.Instance.Debug($"relay report : {relayServerNodeStore.Node.ToJson()}");
|
||||
}
|
||||
|
||||
IEnumerable<RelayServerNodeInfo> nodes = new List<RelayServerNodeInfo>
|
||||
{
|
||||
//默认报告给自己,作为本服务器的一个默认中继节点
|
||||
@@ -349,8 +380,7 @@ namespace linker.messenger.relay.server
|
||||
MaxGbTotalLastBytes = node.MaxGbTotalLastBytes,
|
||||
MaxConnection = node.MaxConnection,
|
||||
ConnectionRatio = Math.Round(node.MaxConnection == 0 ? 0 : connectionNum / 2.0 / node.MaxConnection, 2),
|
||||
EndPoint = endPoint,
|
||||
UserIds = node.UserIds
|
||||
EndPoint = endPoint
|
||||
};
|
||||
|
||||
await messengerSender.SendOnly(new MessageRequestWrap
|
||||
@@ -364,17 +394,17 @@ namespace linker.messenger.relay.server
|
||||
{
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
{
|
||||
LoggerHelper.Instance.Debug($"relay report : {ex}");
|
||||
LoggerHelper.Instance.Error($"relay report : {ex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}, () => 5000);
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
private void SignInTask()
|
||||
{
|
||||
TimerHelper.SetInterval(async () =>
|
||||
TimerHelper.SetIntervalLong(async () =>
|
||||
{
|
||||
if ((remoteConnection == null || remoteConnection.Connected == false) && string.IsNullOrWhiteSpace(relayServerNodeStore.Node.MasterHost) == false)
|
||||
{
|
||||
@@ -385,7 +415,7 @@ namespace linker.messenger.relay.server
|
||||
localConnection = await SignIn(new IPEndPoint(IPAddress.Loopback, relayServerNodeStore.ServicePort).ToString(), relayServerMasterStore.Master.SecretKey).ConfigureAwait(false);
|
||||
}
|
||||
return true;
|
||||
}, () => 3000);
|
||||
}, 3000);
|
||||
}
|
||||
private async Task<IConnection> SignIn(string host, string secretKey)
|
||||
{
|
||||
@@ -403,10 +433,14 @@ namespace linker.messenger.relay.server
|
||||
Socket socket = new Socket(remote.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||
socket.KeepAlive();
|
||||
await socket.ConnectAsync(remote).WaitAsync(TimeSpan.FromMilliseconds(5000)).ConfigureAwait(false);
|
||||
return await messengerResolver.BeginReceiveClient(socket, true, (byte)ResolverType.RelayReport, bytes).ConfigureAwait(false);
|
||||
return await messengerResolver.BeginReceiveClient(socket, true, (byte)ResolverType.RelayReport, bytes.AsMemory(0, secretKeyBytes.Length + 1)).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
{
|
||||
LoggerHelper.Instance.Error(ex);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -416,16 +450,16 @@ namespace linker.messenger.relay.server
|
||||
}
|
||||
}
|
||||
|
||||
public sealed partial class RelayTrafficReportInfo
|
||||
public sealed partial class RelayTrafficUpdateInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// cdkey id 和 流量
|
||||
/// </summary>
|
||||
public Dictionary<string, ulong> Id2Bytes { get; set; }
|
||||
public Dictionary<long, long> Dic { get; set; }
|
||||
/// <summary>
|
||||
/// 需要知道哪些cdkey的剩余流量
|
||||
/// </summary>
|
||||
public List<string> UpdateIds { get; set; }
|
||||
public List<long> Ids { get; set; }
|
||||
public string SecretKey { get; set; }
|
||||
}
|
||||
|
||||
|
@@ -24,10 +24,10 @@ namespace linker.messenger.relay.server
|
||||
this.messengerResolver = messengerResolver;
|
||||
}
|
||||
|
||||
public virtual void AddReceive(ulong bytes)
|
||||
public virtual void AddReceive(long bytes)
|
||||
{
|
||||
}
|
||||
public virtual void AddSendt(ulong bytes)
|
||||
public virtual void AddSendt(long bytes)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -36,19 +36,32 @@ namespace linker.messenger.relay.server
|
||||
byte[] buffer = ArrayPool<byte>.Shared.Rent(1024);
|
||||
try
|
||||
{
|
||||
AddReceive((ulong)memory.Length);
|
||||
int length = await socket.ReceiveAsync(buffer.AsMemory(0, 1), SocketFlags.None).ConfigureAwait(false);
|
||||
AddReceive((ulong)length);
|
||||
|
||||
|
||||
AddReceive(memory.Length);
|
||||
await socket.ReceiveAsync(buffer.AsMemory(0, 1), SocketFlags.None).ConfigureAwait(false);
|
||||
int length = buffer[0];
|
||||
AddReceive(length);
|
||||
await socket.ReceiveAsync(buffer.AsMemory(0, length), SocketFlags.None).ConfigureAwait(false);
|
||||
|
||||
string key = buffer.AsMemory(0, length).GetString();
|
||||
|
||||
if (relayServerMasterStore.Master.SecretKey.Md5() == key)
|
||||
{
|
||||
await messengerResolver.BeginReceiveServer(socket, Helper.EmptyArray);
|
||||
}
|
||||
else
|
||||
{
|
||||
socket.SafeClose();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
{
|
||||
LoggerHelper.Instance.Error(ex);
|
||||
}
|
||||
socket.SafeClose();
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@@ -26,16 +26,16 @@ namespace linker.messenger.relay.server
|
||||
|
||||
|
||||
|
||||
public virtual void AddReceive(string key, string from, string to, string groupid, ulong bytes)
|
||||
public virtual void AddReceive(string key, string from, string to, string groupid, long bytes)
|
||||
{
|
||||
}
|
||||
public virtual void AddSendt(string key, string from, string to, string groupid, ulong bytes)
|
||||
public virtual void AddSendt(string key, string from, string to, string groupid, long bytes)
|
||||
{
|
||||
}
|
||||
public virtual void AddReceive(string key, ulong bytes)
|
||||
public virtual void AddReceive(string key, long bytes)
|
||||
{
|
||||
}
|
||||
public virtual void AddSendt(string key, ulong bytes)
|
||||
public virtual void AddSendt(string key, long bytes)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace linker.messenger.relay.server
|
||||
}
|
||||
|
||||
//流量统计
|
||||
AddReceive(relayCache.FromId, relayCache.FromName, relayCache.ToName, relayCache.GroupId, (ulong)length);
|
||||
AddReceive(relayCache.FromId, relayCache.FromName, relayCache.ToName, relayCache.GroupId, length);
|
||||
try
|
||||
{
|
||||
switch (relayMessage.Type)
|
||||
@@ -152,7 +152,7 @@ namespace linker.messenger.relay.server
|
||||
while ((bytesRead = await source.ReceiveAsync(buffer.AsMemory(), SocketFlags.None).ConfigureAwait(false)) != 0)
|
||||
{
|
||||
//流量限制
|
||||
if (relayServerNodeTransfer.AddBytes(trafficCacheInfo, (ulong)bytesRead) == false)
|
||||
if (relayServerNodeTransfer.AddBytes(trafficCacheInfo, bytesRead) == false)
|
||||
{
|
||||
source.SafeClose();
|
||||
break;
|
||||
@@ -181,8 +181,8 @@ namespace linker.messenger.relay.server
|
||||
}
|
||||
}
|
||||
|
||||
AddReceive(cache.FromId, cache.FromName, cache.ToName, cache.GroupId, (ulong)bytesRead);
|
||||
AddSendt(cache.FromId, cache.FromName, cache.ToName, cache.GroupId, (ulong)bytesRead);
|
||||
AddReceive(cache.FromId, cache.FromName, cache.ToName, cache.GroupId, bytesRead);
|
||||
AddSendt(cache.FromId, cache.FromName, cache.ToName, cache.GroupId, bytesRead);
|
||||
await destination.SendAsync(buffer.AsMemory(0, bytesRead), SocketFlags.None).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -263,11 +263,24 @@ namespace linker.messenger.relay.server
|
||||
}
|
||||
public sealed class RelayTrafficCacheInfo
|
||||
{
|
||||
public ulong Sendt;
|
||||
public long Sendt;
|
||||
public RelaySpeedLimit Limit { get; set; }
|
||||
public RelayCacheInfo Cache { get; set; }
|
||||
public RelayServerCdkeyInfo CurrentCdkey { get; set; }
|
||||
}
|
||||
public partial class RelayServerCdkeyInfo
|
||||
{
|
||||
public long CdkeyId { get; set; }
|
||||
/// <summary>
|
||||
/// 带宽Mbps
|
||||
/// </summary>
|
||||
public double Bandwidth { get; set; }
|
||||
/// <summary>
|
||||
/// 剩余流量
|
||||
/// </summary>
|
||||
public long LastBytes { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public sealed class RelayWrapInfo
|
||||
{
|
||||
|
@@ -56,6 +56,7 @@ namespace linker.messenger.serializer.memorypack
|
||||
MemoryPackFormatterProvider.Register(new RelayCacheInfoFormatter());
|
||||
MemoryPackFormatterProvider.Register(new RelayMessageInfoFormatter());
|
||||
MemoryPackFormatterProvider.Register(new RelayServerCdkeyInfoFormatter());
|
||||
MemoryPackFormatterProvider.Register(new RelayServerCdkeyStoreInfoFormatter());
|
||||
MemoryPackFormatterProvider.Register(new RelayServerCdkeyPageRequestInfoFormatter());
|
||||
MemoryPackFormatterProvider.Register(new RelayServerCdkeyPageResultInfoFormatter());
|
||||
MemoryPackFormatterProvider.Register(new RelayServerCdkeyAddInfoFormatter());
|
||||
|
@@ -11,13 +11,13 @@ namespace linker.messenger.serializer.memorypack
|
||||
public readonly FlowItemInfo info;
|
||||
|
||||
[MemoryPackInclude]
|
||||
ulong ReceiveBytes => info.ReceiveBytes;
|
||||
long ReceiveBytes => info.ReceiveBytes;
|
||||
|
||||
[MemoryPackInclude]
|
||||
ulong SendtBytes => info.SendtBytes;
|
||||
long SendtBytes => info.SendtBytes;
|
||||
|
||||
[MemoryPackConstructor]
|
||||
SerializableFlowItemInfo(ulong receiveBytes, ulong sendtBytes)
|
||||
SerializableFlowItemInfo(long receiveBytes, long sendtBytes)
|
||||
{
|
||||
var info = new FlowItemInfo { ReceiveBytes = receiveBytes, SendtBytes = sendtBytes };
|
||||
this.info = info;
|
||||
@@ -181,16 +181,16 @@ namespace linker.messenger.serializer.memorypack
|
||||
public readonly RelayFlowItemInfo info;
|
||||
|
||||
[MemoryPackInclude]
|
||||
ulong ReceiveBytes => info.ReceiveBytes;
|
||||
long ReceiveBytes => info.ReceiveBytes;
|
||||
|
||||
[MemoryPackInclude]
|
||||
ulong SendtBytes => info.SendtBytes;
|
||||
long SendtBytes => info.SendtBytes;
|
||||
|
||||
[MemoryPackInclude]
|
||||
ulong DiffReceiveBytes => info.DiffReceiveBytes;
|
||||
long DiffReceiveBytes => info.DiffReceiveBytes;
|
||||
|
||||
[MemoryPackInclude]
|
||||
ulong DiffSendtBytes => info.DiffSendtBytes;
|
||||
long DiffSendtBytes => info.DiffSendtBytes;
|
||||
|
||||
[MemoryPackInclude]
|
||||
string FromName => info.FromName;
|
||||
@@ -199,7 +199,7 @@ namespace linker.messenger.serializer.memorypack
|
||||
string ToName => info.ToName;
|
||||
|
||||
[MemoryPackConstructor]
|
||||
SerializableRelayFlowItemInfo(ulong receiveBytes, ulong sendtBytes, ulong diffReceiveBytes, ulong diffSendtBytes, string fromName, string toName)
|
||||
SerializableRelayFlowItemInfo(long receiveBytes, long sendtBytes, long diffReceiveBytes, long diffSendtBytes, string fromName, string toName)
|
||||
{
|
||||
var info = new RelayFlowItemInfo
|
||||
{
|
||||
@@ -393,22 +393,22 @@ namespace linker.messenger.serializer.memorypack
|
||||
public readonly SForwardFlowItemInfo info;
|
||||
|
||||
[MemoryPackInclude]
|
||||
ulong ReceiveBytes => info.ReceiveBytes;
|
||||
long ReceiveBytes => info.ReceiveBytes;
|
||||
|
||||
[MemoryPackInclude]
|
||||
ulong SendtBytes => info.SendtBytes;
|
||||
long SendtBytes => info.SendtBytes;
|
||||
|
||||
[MemoryPackInclude]
|
||||
ulong DiffReceiveBytes => info.DiffReceiveBytes;
|
||||
long DiffReceiveBytes => info.DiffReceiveBytes;
|
||||
|
||||
[MemoryPackInclude]
|
||||
ulong DiffSendtBytes => info.DiffSendtBytes;
|
||||
long DiffSendtBytes => info.DiffSendtBytes;
|
||||
|
||||
[MemoryPackInclude]
|
||||
string Key => info.Key;
|
||||
|
||||
[MemoryPackConstructor]
|
||||
SerializableSForwardFlowItemInfo(ulong receiveBytes, ulong sendtBytes, ulong diffReceiveBytes, ulong diffSendtBytes, string key)
|
||||
SerializableSForwardFlowItemInfo(long receiveBytes, long sendtBytes, long diffReceiveBytes, long diffSendtBytes, string key)
|
||||
{
|
||||
var info = new SForwardFlowItemInfo
|
||||
{
|
||||
|
@@ -11,7 +11,7 @@ namespace linker.messenger.serializer.memorypack
|
||||
public readonly ForwardInfo info;
|
||||
|
||||
[MemoryPackInclude]
|
||||
uint Id => info.Id;
|
||||
long Id => info.Id;
|
||||
|
||||
[MemoryPackInclude]
|
||||
string Name => info.Name;
|
||||
@@ -47,7 +47,7 @@ namespace linker.messenger.serializer.memorypack
|
||||
string TargetMsg => info.TargetMsg;
|
||||
|
||||
[MemoryPackConstructor]
|
||||
SerializableForwardInfo(uint id, string name, string machineId, string groupId, string machineName, IPAddress bindIPAddress, int port, IPEndPoint targetEP, bool started, byte bufferSize, string msg, string targetMsg)
|
||||
SerializableForwardInfo(long id, string name, string machineId, string groupId, string machineName, IPAddress bindIPAddress, int port, IPEndPoint targetEP, bool started, byte bufferSize, string msg, string targetMsg)
|
||||
{
|
||||
this.info = new ForwardInfo
|
||||
{
|
||||
@@ -167,10 +167,10 @@ namespace linker.messenger.serializer.memorypack
|
||||
string MachineId => info.MachineId;
|
||||
|
||||
[MemoryPackInclude, MemoryPackAllowSerialize]
|
||||
uint Id => info.Id;
|
||||
long Id => info.Id;
|
||||
|
||||
[MemoryPackConstructor]
|
||||
SerializableForwardRemoveForwardInfo(string machineId, uint id)
|
||||
SerializableForwardRemoveForwardInfo(string machineId, long id)
|
||||
{
|
||||
this.info = new ForwardRemoveForwardInfo
|
||||
{
|
||||
|
@@ -171,7 +171,7 @@ namespace linker.messenger.serializer.memorypack
|
||||
[MemoryPackInclude]
|
||||
double MaxGbTotal => info.MaxGbTotal;
|
||||
[MemoryPackInclude]
|
||||
ulong MaxGbTotalLastBytes => info.MaxGbTotalLastBytes;
|
||||
long MaxGbTotalLastBytes => info.MaxGbTotalLastBytes;
|
||||
[MemoryPackInclude]
|
||||
double ConnectionRatio => info.ConnectionRatio;
|
||||
[MemoryPackInclude]
|
||||
@@ -185,18 +185,15 @@ namespace linker.messenger.serializer.memorypack
|
||||
[MemoryPackInclude]
|
||||
long LastTicks => info.LastTicks;
|
||||
|
||||
[MemoryPackInclude]
|
||||
List<string> UserIds => info.UserIds;
|
||||
|
||||
|
||||
[MemoryPackConstructor]
|
||||
SerializableRelayServerNodeReportInfo(
|
||||
string id, string name,
|
||||
int maxConnection, double maxBandwidth, double maxBandwidthTotal,
|
||||
double maxGbTotal, ulong maxGbTotalLastBytes,
|
||||
double maxGbTotal, long maxGbTotalLastBytes,
|
||||
double connectionRatio, double bandwidthRatio,
|
||||
bool Public, int delay,
|
||||
IPEndPoint endPoint, long lastTicks, List<string> userIds)
|
||||
IPEndPoint endPoint, long lastTicks)
|
||||
{
|
||||
var info = new RelayServerNodeReportInfo
|
||||
{
|
||||
@@ -212,8 +209,7 @@ namespace linker.messenger.serializer.memorypack
|
||||
MaxGbTotal = maxGbTotal,
|
||||
MaxGbTotalLastBytes = maxGbTotalLastBytes,
|
||||
Name = name,
|
||||
Public = Public,
|
||||
UserIds = userIds
|
||||
Public = Public
|
||||
};
|
||||
this.info = info;
|
||||
}
|
||||
@@ -447,7 +443,6 @@ namespace linker.messenger.serializer.memorypack
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[MemoryPackable]
|
||||
public readonly partial struct SerializableRelayServerCdkeyInfo
|
||||
{
|
||||
@@ -455,53 +450,21 @@ namespace linker.messenger.serializer.memorypack
|
||||
public readonly RelayServerCdkeyInfo info;
|
||||
|
||||
[MemoryPackInclude]
|
||||
string Id => info.Id;
|
||||
[MemoryPackInclude]
|
||||
string UserId => info.UserId;
|
||||
long CdkeyId => info.CdkeyId;
|
||||
|
||||
|
||||
[MemoryPackInclude]
|
||||
string CdKey => info.CdKey;
|
||||
[MemoryPackInclude]
|
||||
DateTime AddTime => info.AddTime;
|
||||
[MemoryPackInclude]
|
||||
DateTime StartTime => info.StartTime;
|
||||
[MemoryPackInclude]
|
||||
DateTime EndTime => info.EndTime;
|
||||
[MemoryPackInclude]
|
||||
List<string> Nodes => info.Nodes;
|
||||
[MemoryPackInclude]
|
||||
double Bandwidth => info.Bandwidth;
|
||||
[MemoryPackInclude]
|
||||
ulong MaxBytes => info.MaxBytes;
|
||||
[MemoryPackInclude]
|
||||
ulong LastBytes => info.LastBytes;
|
||||
[MemoryPackInclude]
|
||||
double Memory => info.Memory;
|
||||
[MemoryPackInclude]
|
||||
double PayMemory => info.PayMemory;
|
||||
[MemoryPackInclude]
|
||||
string Remark => info.Remark;
|
||||
long LastBytes => info.LastBytes;
|
||||
|
||||
[MemoryPackConstructor]
|
||||
SerializableRelayServerCdkeyInfo(string id, string userid, string cdKey, DateTime addTime, DateTime startTime, DateTime endTime,
|
||||
List<string> nodes, double bandwidth, ulong maxBytes, ulong lastBytes, double memory, double payMemory, string remark)
|
||||
SerializableRelayServerCdkeyInfo(long cdkeyid, double bandwidth, long lastBytes)
|
||||
{
|
||||
var info = new RelayServerCdkeyInfo
|
||||
{
|
||||
Id = id,
|
||||
UserId = userid,
|
||||
CdKey = cdKey,
|
||||
AddTime = addTime,
|
||||
StartTime = startTime,
|
||||
EndTime = endTime,
|
||||
Nodes = nodes,
|
||||
CdkeyId = cdkeyid,
|
||||
Bandwidth = bandwidth,
|
||||
MaxBytes = maxBytes,
|
||||
LastBytes = lastBytes,
|
||||
Memory = memory,
|
||||
PayMemory = payMemory,
|
||||
Remark = remark
|
||||
LastBytes = lastBytes
|
||||
};
|
||||
this.info = info;
|
||||
}
|
||||
@@ -539,6 +502,103 @@ namespace linker.messenger.serializer.memorypack
|
||||
}
|
||||
|
||||
|
||||
[MemoryPackable]
|
||||
public readonly partial struct SerializableRelayServerCdkeyStoreInfo
|
||||
{
|
||||
[MemoryPackIgnore]
|
||||
public readonly RelayServerCdkeyStoreInfo info;
|
||||
|
||||
[MemoryPackInclude]
|
||||
long CdkeyId => info.CdkeyId;
|
||||
[MemoryPackInclude]
|
||||
string Id => info.Id;
|
||||
[MemoryPackInclude]
|
||||
string UserId => info.UserId;
|
||||
|
||||
|
||||
[MemoryPackInclude]
|
||||
string CdKey => info.CdKey;
|
||||
[MemoryPackInclude]
|
||||
DateTime AddTime => info.AddTime;
|
||||
[MemoryPackInclude]
|
||||
DateTime StartTime => info.StartTime;
|
||||
[MemoryPackInclude]
|
||||
DateTime EndTime => info.EndTime;
|
||||
[MemoryPackInclude]
|
||||
DateTime UseTime => info.UseTime;
|
||||
[MemoryPackInclude]
|
||||
List<string> Nodes => info.Nodes;
|
||||
[MemoryPackInclude]
|
||||
double Bandwidth => info.Bandwidth;
|
||||
[MemoryPackInclude]
|
||||
long MaxBytes => info.MaxBytes;
|
||||
[MemoryPackInclude]
|
||||
long LastBytes => info.LastBytes;
|
||||
[MemoryPackInclude]
|
||||
double Memory => info.Memory;
|
||||
[MemoryPackInclude]
|
||||
double PayMemory => info.PayMemory;
|
||||
[MemoryPackInclude]
|
||||
string Remark => info.Remark;
|
||||
|
||||
[MemoryPackConstructor]
|
||||
SerializableRelayServerCdkeyStoreInfo(long cdkeyid, string id, string userid, string cdKey, DateTime addTime, DateTime startTime, DateTime endTime, DateTime useTime,
|
||||
List<string> nodes, double bandwidth, long maxBytes, long lastBytes, double memory, double payMemory, string remark)
|
||||
{
|
||||
var info = new RelayServerCdkeyStoreInfo
|
||||
{
|
||||
CdkeyId = cdkeyid,
|
||||
Id = id,
|
||||
UserId = userid,
|
||||
CdKey = cdKey,
|
||||
AddTime = addTime,
|
||||
StartTime = startTime,
|
||||
EndTime = endTime,
|
||||
UseTime = useTime,
|
||||
Nodes = nodes,
|
||||
Bandwidth = bandwidth,
|
||||
MaxBytes = maxBytes,
|
||||
LastBytes = lastBytes,
|
||||
Memory = memory,
|
||||
PayMemory = payMemory,
|
||||
Remark = remark
|
||||
};
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public SerializableRelayServerCdkeyStoreInfo(RelayServerCdkeyStoreInfo info)
|
||||
{
|
||||
this.info = info;
|
||||
}
|
||||
}
|
||||
public class RelayServerCdkeyStoreInfoFormatter : MemoryPackFormatter<RelayServerCdkeyStoreInfo>
|
||||
{
|
||||
public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref RelayServerCdkeyStoreInfo value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullObjectHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WritePackable(new SerializableRelayServerCdkeyStoreInfo(value));
|
||||
}
|
||||
|
||||
public override void Deserialize(ref MemoryPackReader reader, scoped ref RelayServerCdkeyStoreInfo value)
|
||||
{
|
||||
if (reader.PeekIsNull())
|
||||
{
|
||||
reader.Advance(1); // skip null block
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
var wrapped = reader.ReadPackable<SerializableRelayServerCdkeyStoreInfo>();
|
||||
value = wrapped.info;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
[MemoryPackable]
|
||||
public readonly partial struct SerializableRelayServerCdkeyAddInfo
|
||||
@@ -549,10 +609,10 @@ namespace linker.messenger.serializer.memorypack
|
||||
[MemoryPackInclude]
|
||||
string SecretKey => info.SecretKey;
|
||||
[MemoryPackInclude, MemoryPackAllowSerialize]
|
||||
RelayServerCdkeyInfo Data => info.Data;
|
||||
RelayServerCdkeyStoreInfo Data => info.Data;
|
||||
|
||||
[MemoryPackConstructor]
|
||||
SerializableRelayServerCdkeyAddInfo(string secretKey, RelayServerCdkeyInfo data)
|
||||
SerializableRelayServerCdkeyAddInfo(string secretKey, RelayServerCdkeyStoreInfo data)
|
||||
{
|
||||
var info = new RelayServerCdkeyAddInfo
|
||||
{
|
||||
@@ -604,15 +664,15 @@ namespace linker.messenger.serializer.memorypack
|
||||
[MemoryPackInclude]
|
||||
string SecretKey => info.SecretKey;
|
||||
[MemoryPackInclude]
|
||||
string Id => info.Id;
|
||||
long CdkeyId => info.CdkeyId;
|
||||
|
||||
[MemoryPackConstructor]
|
||||
SerializableRelayServerCdkeyDelInfo(string secretKey, string id)
|
||||
SerializableRelayServerCdkeyDelInfo(string secretKey, long cdkeyid)
|
||||
{
|
||||
var info = new RelayServerCdkeyDelInfo
|
||||
{
|
||||
SecretKey = secretKey,
|
||||
Id = id
|
||||
CdkeyId = cdkeyid
|
||||
};
|
||||
this.info = info;
|
||||
}
|
||||
@@ -735,10 +795,10 @@ namespace linker.messenger.serializer.memorypack
|
||||
[MemoryPackInclude]
|
||||
int Count => info.Count;
|
||||
[MemoryPackInclude]
|
||||
List<RelayServerCdkeyInfo> List => info.List;
|
||||
List<RelayServerCdkeyStoreInfo> List => info.List;
|
||||
|
||||
[MemoryPackConstructor]
|
||||
SerializableRelayServerCdkeyPageResultInfo(int page, int size, int count, List<RelayServerCdkeyInfo> list)
|
||||
SerializableRelayServerCdkeyPageResultInfo(int page, int size, int count, List<RelayServerCdkeyStoreInfo> list)
|
||||
{
|
||||
var info = new RelayServerCdkeyPageResultInfo
|
||||
{
|
||||
@@ -788,35 +848,35 @@ namespace linker.messenger.serializer.memorypack
|
||||
public readonly partial struct SerializableRelayTrafficReportInfo
|
||||
{
|
||||
[MemoryPackIgnore]
|
||||
public readonly RelayTrafficReportInfo info;
|
||||
public readonly RelayTrafficUpdateInfo info;
|
||||
|
||||
[MemoryPackInclude]
|
||||
Dictionary<string, ulong> Id2Bytes => info.Id2Bytes;
|
||||
Dictionary<long, long> Dic => info.Dic;
|
||||
[MemoryPackInclude]
|
||||
List<string> UpdateIds => info.UpdateIds;
|
||||
List<long> Ids => info.Ids;
|
||||
[MemoryPackInclude]
|
||||
string SecretKey => info.SecretKey;
|
||||
|
||||
[MemoryPackConstructor]
|
||||
SerializableRelayTrafficReportInfo(Dictionary<string, ulong> id2Bytes, List<string> updateIds, string secretKey)
|
||||
SerializableRelayTrafficReportInfo(Dictionary<long, long> dic, List<long> ids, string secretKey)
|
||||
{
|
||||
var info = new RelayTrafficReportInfo
|
||||
var info = new RelayTrafficUpdateInfo
|
||||
{
|
||||
Id2Bytes = id2Bytes,
|
||||
UpdateIds = updateIds,
|
||||
Dic = dic,
|
||||
Ids = ids,
|
||||
SecretKey = secretKey
|
||||
};
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public SerializableRelayTrafficReportInfo(RelayTrafficReportInfo info)
|
||||
public SerializableRelayTrafficReportInfo(RelayTrafficUpdateInfo info)
|
||||
{
|
||||
this.info = info;
|
||||
}
|
||||
}
|
||||
public class RelayTrafficReportInfoFormatter : MemoryPackFormatter<RelayTrafficReportInfo>
|
||||
public class RelayTrafficReportInfoFormatter : MemoryPackFormatter<RelayTrafficUpdateInfo>
|
||||
{
|
||||
public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref RelayTrafficReportInfo value)
|
||||
public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref RelayTrafficUpdateInfo value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
@@ -827,7 +887,7 @@ namespace linker.messenger.serializer.memorypack
|
||||
writer.WritePackable(new SerializableRelayTrafficReportInfo(value));
|
||||
}
|
||||
|
||||
public override void Deserialize(ref MemoryPackReader reader, scoped ref RelayTrafficReportInfo value)
|
||||
public override void Deserialize(ref MemoryPackReader reader, scoped ref RelayTrafficUpdateInfo value)
|
||||
{
|
||||
if (reader.PeekIsNull())
|
||||
{
|
||||
|
@@ -11,7 +11,7 @@ namespace linker.messenger.serializer.memorypack
|
||||
public readonly SForwardInfo info;
|
||||
|
||||
[MemoryPackInclude]
|
||||
uint Id => info.Id;
|
||||
long Id => info.Id;
|
||||
|
||||
[MemoryPackInclude]
|
||||
string Name => info.Name;
|
||||
@@ -44,7 +44,7 @@ namespace linker.messenger.serializer.memorypack
|
||||
int RemotePortMax => info.RemotePortMax;
|
||||
|
||||
[MemoryPackConstructor]
|
||||
SerializableSForwardInfo(uint id, string name, string domain, int remotePort, byte bufferSize, IPEndPoint localEP, bool started, string msg, string localMsg, int remotePortMin, int remotePortMax)
|
||||
SerializableSForwardInfo(long id, string name, string domain, int remotePort, byte bufferSize, IPEndPoint localEP, bool started, string msg, string localMsg, int remotePortMin, int remotePortMax)
|
||||
{
|
||||
this.info = new SForwardInfo
|
||||
{
|
||||
@@ -277,10 +277,10 @@ namespace linker.messenger.serializer.memorypack
|
||||
string MachineId => info.MachineId;
|
||||
|
||||
[MemoryPackInclude, MemoryPackAllowSerialize]
|
||||
uint Id => info.Id;
|
||||
long Id => info.Id;
|
||||
|
||||
[MemoryPackConstructor]
|
||||
SerializableSForwardRemoveForwardInfo(string machineId, uint id)
|
||||
SerializableSForwardRemoveForwardInfo(string machineId, long id)
|
||||
{
|
||||
this.info = new SForwardRemoveForwardInfo
|
||||
{
|
||||
|
@@ -10,7 +10,7 @@ namespace linker.messenger.sforward
|
||||
/// <summary>
|
||||
/// 穿透id
|
||||
/// </summary>
|
||||
public uint Id { get; set; }
|
||||
public long Id { get; set; }
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
@@ -125,7 +125,7 @@ namespace linker.messenger.sforward
|
||||
public sealed partial class SForwardRemoveForwardInfo
|
||||
{
|
||||
public string MachineId { get; set; }
|
||||
public uint Id { get; set; }
|
||||
public long Id { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@@ -30,7 +30,7 @@
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
public SForwardInfo Get(uint id);
|
||||
public SForwardInfo Get(long id);
|
||||
/// <summary>
|
||||
/// 获取穿透
|
||||
/// </summary>
|
||||
@@ -60,7 +60,7 @@
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
public bool Remove(uint id);
|
||||
public bool Remove(long id);
|
||||
/// <summary>
|
||||
/// 提交保存
|
||||
/// </summary>
|
||||
|
@@ -16,9 +16,6 @@ namespace linker.messenger.sforward.client
|
||||
private readonly ISForwardClientStore sForwardClientStore;
|
||||
private readonly ISerializer serializer;
|
||||
|
||||
private readonly NumberSpaceUInt32 ns = new NumberSpaceUInt32();
|
||||
|
||||
|
||||
public SForwardClientTransfer(SignInClientState signInClientState, IMessengerSender messengerSender, ISignInClientStore signInClientStore, ISForwardClientStore sForwardClientStore, ISerializer serializer)
|
||||
{
|
||||
this.signInClientState = signInClientState;
|
||||
@@ -33,8 +30,6 @@ namespace linker.messenger.sforward.client
|
||||
private void Start()
|
||||
{
|
||||
var list = sForwardClientStore.Get();
|
||||
uint maxid = list.Count > 0 ? list.Max(c => c.Id) : 1;
|
||||
ns.Reset(maxid);
|
||||
|
||||
foreach (var item in list)
|
||||
{
|
||||
@@ -167,7 +162,6 @@ namespace linker.messenger.sforward.client
|
||||
}
|
||||
else
|
||||
{
|
||||
forwardInfo.Id = ns.Increment();
|
||||
if (PortRange(forwardInfo.Domain, out int min, out int max))
|
||||
{
|
||||
forwardInfo.RemotePortMin = min;
|
||||
@@ -183,7 +177,7 @@ namespace linker.messenger.sforward.client
|
||||
|
||||
return true;
|
||||
}
|
||||
public bool Remove(uint id)
|
||||
public bool Remove(long id)
|
||||
{
|
||||
//同名或者同端口,但是ID不一样
|
||||
SForwardInfo old = sForwardClientStore.Get(id);
|
||||
|
@@ -14,10 +14,10 @@ namespace linker.plugins.sforward.proxy
|
||||
|
||||
}
|
||||
|
||||
public virtual void AddReceive(string key,string groupid, ulong bytes)
|
||||
public virtual void AddReceive(string key,string groupid, long bytes)
|
||||
{
|
||||
}
|
||||
public virtual void AddSendt(string key,string groupid, ulong bytes)
|
||||
public virtual void AddSendt(string key,string groupid, long bytes)
|
||||
{
|
||||
}
|
||||
|
||||
|
@@ -281,13 +281,13 @@ namespace linker.plugins.sforward.proxy
|
||||
{
|
||||
if (isDomain)
|
||||
{
|
||||
AddReceive(domain, groupid, (ulong)bytesRead);
|
||||
AddSendt(domain, groupid, (ulong)bytesRead);
|
||||
AddReceive(domain, groupid, bytesRead);
|
||||
AddSendt(domain, groupid, bytesRead);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddReceive(portStr, groupid, (ulong)bytesRead);
|
||||
AddSendt(portStr, groupid, (ulong)bytesRead);
|
||||
AddReceive(portStr, groupid, bytesRead);
|
||||
AddSendt(portStr, groupid, bytesRead);
|
||||
}
|
||||
await target.SendAsync(buffer.Slice(0, bytesRead), SocketFlags.None).ConfigureAwait(false);
|
||||
}
|
||||
|
@@ -59,13 +59,13 @@ namespace linker.plugins.sforward.proxy
|
||||
|
||||
Memory<byte> memory = buffer.AsMemory(0, result.ReceivedBytes);
|
||||
|
||||
AddReceive(portStr, token.GroupId, (ulong)memory.Length);
|
||||
AddReceive(portStr, token.GroupId, memory.Length);
|
||||
|
||||
IPEndPoint source = result.RemoteEndPoint as IPEndPoint;
|
||||
//已经连接
|
||||
if (udpConnections.TryGetValue(source, out UdpTargetCache cache) && cache != null)
|
||||
{
|
||||
AddSendt(portStr, token.GroupId, (ulong)memory.Length);
|
||||
AddSendt(portStr, token.GroupId, memory.Length);
|
||||
cache.LastTicks.Update();
|
||||
await token.SourceSocket.SendToAsync(memory, cache.IPEndPoint).ConfigureAwait(false);
|
||||
}
|
||||
@@ -197,8 +197,8 @@ namespace linker.plugins.sforward.proxy
|
||||
cache.LastTicks.Update();
|
||||
|
||||
Memory<byte> memory = buffer.AsMemory(0, result.ReceivedBytes);
|
||||
AddReceive(portStr, string.Empty, (ulong)memory.Length);
|
||||
AddSendt(portStr, string.Empty, (ulong)memory.Length);
|
||||
AddReceive(portStr, string.Empty, memory.Length);
|
||||
AddSendt(portStr, string.Empty, memory.Length);
|
||||
//未连接本地服务的,去连接一下
|
||||
if (serviceUdp == null)
|
||||
{
|
||||
@@ -239,8 +239,8 @@ namespace linker.plugins.sforward.proxy
|
||||
break;
|
||||
}
|
||||
Memory<byte> memory = buffer.AsMemory(0, result.ReceivedBytes);
|
||||
AddReceive(portStr, string.Empty, (ulong)memory.Length);
|
||||
AddSendt(portStr, string.Empty, (ulong)memory.Length);
|
||||
AddReceive(portStr, string.Empty, memory.Length);
|
||||
AddSendt(portStr, string.Empty, memory.Length);
|
||||
|
||||
await serverUdp.SendToAsync(memory, server).ConfigureAwait(false);
|
||||
cache.LastTicks.Update();
|
||||
@@ -261,7 +261,7 @@ namespace linker.plugins.sforward.proxy
|
||||
|
||||
private void UdpTask()
|
||||
{
|
||||
TimerHelper.SetInterval(() =>
|
||||
TimerHelper.SetIntervalLong(() =>
|
||||
{
|
||||
var connections = udpConnections.Where(c => c.Value.Timeout).Select(c => c.Key);
|
||||
foreach (var item in connections)
|
||||
|
@@ -34,7 +34,7 @@ namespace linker.messenger.signin
|
||||
/// </summary>
|
||||
public void SignInTask()
|
||||
{
|
||||
TimerHelper.SetInterval(async () =>
|
||||
TimerHelper.SetIntervalLong(async () =>
|
||||
{
|
||||
if (clientSignInState.Connected == false)
|
||||
{
|
||||
@@ -49,7 +49,7 @@ namespace linker.messenger.signin
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}, () => 10000);
|
||||
}, 10000);
|
||||
}
|
||||
|
||||
public void ReSignIn()
|
||||
|
@@ -121,7 +121,7 @@ namespace linker.messenger.signin
|
||||
|
||||
private void ClearTask()
|
||||
{
|
||||
TimerHelper.SetInterval(() =>
|
||||
TimerHelper.SetIntervalLong(() =>
|
||||
{
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
{
|
||||
|
@@ -73,7 +73,7 @@ namespace linker.messenger.socks5
|
||||
}
|
||||
CloseClientSocket(token);
|
||||
}
|
||||
|
||||
|
||||
private async Task SendToConnection(AsyncUserUdpToken token)
|
||||
{
|
||||
if (token.Connection == null) return;
|
||||
@@ -96,7 +96,7 @@ namespace linker.messenger.socks5
|
||||
token.Proxy.Return(connectData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private async Task SendToConnections(AsyncUserUdpToken token)
|
||||
{
|
||||
byte[] connectData = token.Proxy.ToBytes(out int length);
|
||||
@@ -242,7 +242,7 @@ namespace linker.messenger.socks5
|
||||
|
||||
private void TaskUdp()
|
||||
{
|
||||
TimerHelper.SetInterval(() =>
|
||||
TimerHelper.SetIntervalLong(() =>
|
||||
{
|
||||
var connections = udpConnections.Where(c => c.Value.Timeout).Select(c => c.Key).ToList();
|
||||
foreach (var item in connections)
|
||||
@@ -259,7 +259,7 @@ namespace linker.messenger.socks5
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}, () => 3 * 60 * 1000);
|
||||
}, 3 * 60 * 1000);
|
||||
}
|
||||
|
||||
private void CloseClientSocketUdp(ITunnelConnection connection)
|
||||
|
@@ -32,6 +32,8 @@ using linker.messenger.tuntap.lease;
|
||||
using linker.messenger.updater;
|
||||
using linker.plugins.tunnel;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Yitter.IdGenerator;
|
||||
namespace linker.messenger.store.file
|
||||
{
|
||||
public static class Entry
|
||||
@@ -40,6 +42,8 @@ namespace linker.messenger.store.file
|
||||
{
|
||||
LoggerHelper.Instance.Info("add store file");
|
||||
|
||||
YitIdHelper.SetIdGenerator(new IdGeneratorOptions(1));
|
||||
|
||||
serviceCollection.AddSingleton<Storefactory>();
|
||||
serviceCollection.AddSingleton<FileConfig>();
|
||||
serviceCollection.AddSingleton<RunningConfig>();
|
||||
|
@@ -127,7 +127,7 @@ namespace linker.messenger.store.file
|
||||
}
|
||||
private void SaveTask()
|
||||
{
|
||||
TimerHelper.SetInterval(() =>
|
||||
TimerHelper.SetIntervalLong(() =>
|
||||
{
|
||||
while (Data.Updated > 0)
|
||||
{
|
||||
|
@@ -45,7 +45,7 @@ namespace linker.messenger.store.file
|
||||
}
|
||||
private void SaveTask()
|
||||
{
|
||||
TimerHelper.SetInterval(() =>
|
||||
TimerHelper.SetIntervalLong(() =>
|
||||
{
|
||||
while (Data.Updated > 0)
|
||||
{
|
||||
|
@@ -34,7 +34,7 @@ namespace linker.messenger.store.file
|
||||
|
||||
private void CheckpointTask()
|
||||
{
|
||||
TimerHelper.SetInterval(() =>
|
||||
TimerHelper.SetIntervalLong(() =>
|
||||
{
|
||||
database.Checkpoint();
|
||||
return true;
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using linker.messenger.forward;
|
||||
using Yitter.IdGenerator;
|
||||
|
||||
namespace linker.messenger.store.file.forward
|
||||
{
|
||||
@@ -23,7 +24,7 @@ namespace linker.messenger.store.file.forward
|
||||
return runningConfig.Data.Forwards;
|
||||
}
|
||||
|
||||
public ForwardInfo Get(uint id)
|
||||
public ForwardInfo Get(long id)
|
||||
{
|
||||
return runningConfig.Data.Forwards.FirstOrDefault(x => x.Id == id);
|
||||
}
|
||||
@@ -35,6 +36,11 @@ namespace linker.messenger.store.file.forward
|
||||
|
||||
public bool Add(ForwardInfo info)
|
||||
{
|
||||
if(info.Id == 0)
|
||||
{
|
||||
info.Id = YitIdHelper.NextId();
|
||||
}
|
||||
|
||||
runningConfig.Data.Forwards.Add(info);
|
||||
return true;
|
||||
}
|
||||
@@ -42,7 +48,7 @@ namespace linker.messenger.store.file.forward
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public bool Remove(uint id)
|
||||
public bool Remove(long id)
|
||||
{
|
||||
runningConfig.Data.Forwards.Remove(Get(id));
|
||||
return true;
|
||||
|
@@ -38,6 +38,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="LiteDB" Version="5.0.17" />
|
||||
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\linker.libs\linker.libs.csproj" />
|
||||
|
@@ -8,6 +8,7 @@ namespace linker.messenger.store.file
|
||||
public sealed partial class RunningConfigInfo
|
||||
{
|
||||
public RelayInfo Relay { get; set; } = new RelayInfo();
|
||||
|
||||
}
|
||||
|
||||
public sealed class RelayInfo
|
||||
@@ -43,6 +44,8 @@ namespace linker.messenger.store.file
|
||||
#else
|
||||
public string SecretKey { get; set; } = Guid.NewGuid().ToString().ToUpper();
|
||||
#endif
|
||||
public RelayServerCdkeyConfigInfo Cdkey { get; set; } = new RelayServerCdkeyConfigInfo();
|
||||
|
||||
public DistributedInfo Distributed { get; set; } = new DistributedInfo { };
|
||||
}
|
||||
|
||||
|
@@ -1,23 +1,29 @@
|
||||
using linker.messenger.relay.server;
|
||||
using LiteDB;
|
||||
using Yitter.IdGenerator;
|
||||
|
||||
namespace linker.messenger.store.file.relay
|
||||
{
|
||||
public sealed class RelayServerCdkeyStore : IRelayServerCdkeyStore
|
||||
{
|
||||
private readonly Storefactory dBfactory;
|
||||
private readonly ILiteCollection<RelayServerCdkeyInfo> liteCollection;
|
||||
private readonly ILiteCollection<RelayServerCdkeyStoreInfo> liteCollection;
|
||||
public RelayServerCdkeyStore(Storefactory dBfactory, FileConfig fileConfig)
|
||||
{
|
||||
this.dBfactory = dBfactory;
|
||||
liteCollection = dBfactory.GetCollection<RelayServerCdkeyInfo>("relayCdkey");
|
||||
liteCollection = dBfactory.GetCollection<RelayServerCdkeyStoreInfo>("relayCdkey");
|
||||
}
|
||||
|
||||
public async Task<bool> Add(RelayServerCdkeyInfo info)
|
||||
public async Task<bool> Add(RelayServerCdkeyStoreInfo info)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(info.Id))
|
||||
{
|
||||
info.Id = ObjectId.NewObjectId().ToString();
|
||||
info.CdKey = Guid.NewGuid().ToString().ToUpper();
|
||||
info.AddTime = DateTime.Now;
|
||||
info.UseTime = DateTime.Now;
|
||||
info.LastBytes = info.MaxBytes;
|
||||
info.CdkeyId = YitIdHelper.NextId();
|
||||
liteCollection.Insert(info);
|
||||
}
|
||||
else
|
||||
@@ -26,40 +32,64 @@ namespace linker.messenger.store.file.relay
|
||||
}
|
||||
return await Task.FromResult(true);
|
||||
}
|
||||
public async Task<bool> Del(string id)
|
||||
public async Task<bool> Del(long id)
|
||||
{
|
||||
return await Task.FromResult(liteCollection.Delete(id));
|
||||
return await Task.FromResult(liteCollection.DeleteMany(c => c.CdkeyId == id) > 0);
|
||||
}
|
||||
|
||||
public async Task<List<RelayServerCdkeyInfo>> Get(string userid)
|
||||
public async Task<bool> Traffic(Dictionary<long, long> dic)
|
||||
{
|
||||
foreach (var item in dic)
|
||||
{
|
||||
var info = liteCollection.FindOne(x => x.CdkeyId == item.Key);
|
||||
if (info != null)
|
||||
{
|
||||
long bytes = info.LastBytes >= item.Value ? info.LastBytes - item.Value : 0;
|
||||
liteCollection.UpdateMany(x => new RelayServerCdkeyStoreInfo { LastBytes = bytes, UseTime = DateTime.Now }, c => c.CdkeyId == item.Key);
|
||||
}
|
||||
}
|
||||
return await Task.FromResult(true);
|
||||
}
|
||||
|
||||
public async Task<List<RelayServerCdkeyStoreInfo>> GetAvailable(string userid)
|
||||
{
|
||||
return await Task.FromResult(liteCollection.Find(x => x.UserId == userid && x.LastBytes > 0 && x.StartTime <= DateTime.Now && x.EndTime < DateTime.Now).ToList());
|
||||
}
|
||||
|
||||
public async Task<RelayServerCdkeyPageResultInfo> Get(RelayServerCdkeyPageRequestInfo relayServerCdkeyPageRequestInfo)
|
||||
public async Task<List<RelayServerCdkeyStoreInfo>> Get(List<long> ids)
|
||||
{
|
||||
ILiteQueryable<RelayServerCdkeyInfo> query = liteCollection.Query();
|
||||
return await Task.FromResult(liteCollection.Find(x => ids.Contains(x.CdkeyId)).ToList());
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(relayServerCdkeyPageRequestInfo.Order) == false)
|
||||
public async Task<RelayServerCdkeyPageResultInfo> Get(RelayServerCdkeyPageRequestInfo info)
|
||||
{
|
||||
ILiteQueryable<RelayServerCdkeyStoreInfo> query = liteCollection.Query();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(info.Order) == false)
|
||||
{
|
||||
query = query.OrderBy(relayServerCdkeyPageRequestInfo.Order, relayServerCdkeyPageRequestInfo.Sort == "asc" ? Query.Ascending : Query.Descending);
|
||||
query = query.OrderBy(info.Order, info.Sort == "asc" ? Query.Ascending : Query.Descending);
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(relayServerCdkeyPageRequestInfo.UserId) == false)
|
||||
else
|
||||
{
|
||||
query = query.Where(x => x.UserId == relayServerCdkeyPageRequestInfo.UserId);
|
||||
query = query.OrderBy(c => c.CdkeyId, Query.Descending);
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(relayServerCdkeyPageRequestInfo.Remark) == false)
|
||||
if (string.IsNullOrWhiteSpace(info.UserId) == false)
|
||||
{
|
||||
query = query.Where(x => x.Remark.Contains(relayServerCdkeyPageRequestInfo.Remark));
|
||||
query = query.Where(x => x.UserId == info.UserId);
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(info.Remark) == false)
|
||||
{
|
||||
query = query.Where(x => x.Remark.Contains(info.Remark));
|
||||
}
|
||||
|
||||
return await Task.FromResult(new RelayServerCdkeyPageResultInfo
|
||||
{
|
||||
Page = relayServerCdkeyPageRequestInfo.Page,
|
||||
Size = relayServerCdkeyPageRequestInfo.Size,
|
||||
Page = info.Page,
|
||||
Size = info.Size,
|
||||
Count = query.Count(),
|
||||
List = query.Skip((relayServerCdkeyPageRequestInfo.Page - 1) * relayServerCdkeyPageRequestInfo.Size).Limit(relayServerCdkeyPageRequestInfo.Size).ToList()
|
||||
List = query.Skip((info.Page - 1) * info.Size).Limit(info.Size).ToList()
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -22,7 +22,7 @@ namespace linker.messenger.store.file.relay
|
||||
{
|
||||
config.Data.Server.Relay.Distributed.Node = node;
|
||||
}
|
||||
public void SetMaxGbTotalLastBytes(ulong value)
|
||||
public void SetMaxGbTotalLastBytes(long value)
|
||||
{
|
||||
config.Data.Server.Relay.Distributed.Node.MaxGbTotalLastBytes=value;
|
||||
}
|
||||
|
@@ -1,5 +1,6 @@
|
||||
using linker.messenger.sforward;
|
||||
using linker.messenger.sforward.client;
|
||||
using Yitter.IdGenerator;
|
||||
|
||||
namespace linker.messenger.store.file.sforward
|
||||
{
|
||||
@@ -36,7 +37,7 @@ namespace linker.messenger.store.file.sforward
|
||||
return runningConfig.Data.SForwards;
|
||||
}
|
||||
|
||||
public SForwardInfo Get(uint id)
|
||||
public SForwardInfo Get(long id)
|
||||
{
|
||||
return runningConfig.Data.SForwards.FirstOrDefault(x => x.Id == id);
|
||||
}
|
||||
@@ -53,6 +54,10 @@ namespace linker.messenger.store.file.sforward
|
||||
|
||||
public bool Add(SForwardInfo info)
|
||||
{
|
||||
if (info.Id == 0)
|
||||
{
|
||||
info.Id = YitIdHelper.NextId();
|
||||
}
|
||||
runningConfig.Data.SForwards.Add(info);
|
||||
return true;
|
||||
}
|
||||
@@ -60,7 +65,7 @@ namespace linker.messenger.store.file.sforward
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public bool Remove(uint id)
|
||||
public bool Remove(long id)
|
||||
{
|
||||
runningConfig.Data.SForwards.Remove(Get(id));
|
||||
return true;
|
||||
|
@@ -14,8 +14,8 @@ namespace linker.messenger.tunnel
|
||||
{
|
||||
public byte Type => (byte)ResolverType.External;
|
||||
|
||||
public virtual void AddReceive( ulong bytes) { }
|
||||
public virtual void AddSendt(ulong bytes) { }
|
||||
public virtual void AddReceive( long bytes) { }
|
||||
public virtual void AddSendt(long bytes) { }
|
||||
|
||||
/// <summary>
|
||||
/// UDP
|
||||
@@ -28,12 +28,12 @@ namespace linker.messenger.tunnel
|
||||
{
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Debug($"{ep} get udp external port");
|
||||
|
||||
AddReceive((ulong)memory.Length);
|
||||
AddReceive(memory.Length);
|
||||
byte[] sendData = ArrayPool<byte>.Shared.Rent(1024);
|
||||
try
|
||||
{
|
||||
var send = BuildSendData(sendData, ep);
|
||||
AddSendt((ulong)send.Length);
|
||||
AddSendt(send.Length);
|
||||
await socket.SendToAsync(send, SocketFlags.None, ep).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -57,7 +57,7 @@ namespace linker.messenger.tunnel
|
||||
try
|
||||
{
|
||||
memory = BuildSendData(sendData, socket.RemoteEndPoint as IPEndPoint);
|
||||
AddSendt((ulong)memory.Length);
|
||||
AddSendt(memory.Length);
|
||||
await socket.SendAsync(memory, SocketFlags.None).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@@ -80,11 +80,11 @@ namespace linker.messenger.tuntap
|
||||
private OperatingManager checking = new OperatingManager();
|
||||
private void CheckDeviceTask()
|
||||
{
|
||||
TimerHelper.SetInterval(async () =>
|
||||
TimerHelper.SetIntervalLong(async () =>
|
||||
{
|
||||
await CheckDevice();
|
||||
return true;
|
||||
}, () => 30000);
|
||||
}, 30000);
|
||||
}
|
||||
private async Task CheckDevice()
|
||||
{
|
||||
|
@@ -35,7 +35,7 @@ namespace linker.messenger.tuntap
|
||||
}
|
||||
private void PingTask()
|
||||
{
|
||||
TimerHelper.SetInterval(async () =>
|
||||
TimerHelper.SetIntervalLong(async () =>
|
||||
{
|
||||
if (tuntapTransfer.Status == TuntapStatus.Running)
|
||||
{
|
||||
|
@@ -73,7 +73,7 @@ namespace linker.messenger.tuntap.lease
|
||||
|
||||
private void LeaseExpTask()
|
||||
{
|
||||
TimerHelper.SetInterval(async () =>
|
||||
TimerHelper.SetIntervalLong(async () =>
|
||||
{
|
||||
await messengerSender.SendReply(new MessageRequestWrap
|
||||
{
|
||||
@@ -82,7 +82,7 @@ namespace linker.messenger.tuntap.lease
|
||||
});
|
||||
|
||||
return true;
|
||||
}, () => 60000);
|
||||
}, 60000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -219,7 +219,7 @@ namespace linker.messenger.tuntap.lease
|
||||
|
||||
private void ClearTask()
|
||||
{
|
||||
TimerHelper.SetInterval(() =>
|
||||
TimerHelper.SetIntervalLong(() =>
|
||||
{
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
{
|
||||
|
@@ -89,7 +89,7 @@ namespace linker.messenger.updater
|
||||
}
|
||||
private void UpdateTask()
|
||||
{
|
||||
TimerHelper.SetInterval(async () =>
|
||||
TimerHelper.SetIntervalLong(async () =>
|
||||
{
|
||||
await GetUpdateInfo();
|
||||
if (updateInfo.Updated)
|
||||
|
@@ -15,7 +15,7 @@ namespace linker.messenger
|
||||
public interface IMessengerResolver
|
||||
{
|
||||
public Task<IConnection> BeginReceiveClient(Socket socket);
|
||||
public Task<IConnection> BeginReceiveClient(Socket socket, bool sendFlag, byte flag, byte[] data);
|
||||
public Task<IConnection> BeginReceiveClient(Socket socket, bool sendFlag, byte flag, Memory<byte> data);
|
||||
public void AddMessenger(List<IMessenger> list);
|
||||
public Task BeginReceiveServer(Socket socket, Memory<byte> memory);
|
||||
public Task BeginReceiveServer(Socket socket, IPEndPoint ep, Memory<byte> memory);
|
||||
@@ -59,8 +59,8 @@ namespace linker.messenger
|
||||
}
|
||||
|
||||
|
||||
public virtual void AddReceive(ushort id, ulong bytes) { }
|
||||
public virtual void AddSendt(ushort id, ulong bytes) { }
|
||||
public virtual void AddReceive(ushort id, long bytes) { }
|
||||
public virtual void AddSendt(ushort id, long bytes) { }
|
||||
|
||||
/// <summary>
|
||||
/// 以服务器模式接收数据 TCP
|
||||
@@ -113,7 +113,7 @@ namespace linker.messenger
|
||||
/// <param name="sendFlag"></param>
|
||||
/// <param name="flag"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<IConnection> BeginReceiveClient(Socket socket, bool sendFlag, byte flag, byte[] data)
|
||||
public async Task<IConnection> BeginReceiveClient(Socket socket, bool sendFlag, byte flag, Memory<byte> data)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -230,7 +230,7 @@ namespace linker.messenger
|
||||
|
||||
//新的请求
|
||||
requestWrap.FromArray(data);
|
||||
AddReceive(requestWrap.MessengerId, (ulong)data.Length);
|
||||
AddReceive(requestWrap.MessengerId, data.Length);
|
||||
//404,没这个插件
|
||||
if (messengers.TryGetValue(requestWrap.MessengerId, out MessengerCacheInfo plugin) == false)
|
||||
{
|
||||
|
@@ -47,8 +47,8 @@ namespace linker.messenger
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void AddReceive(ushort id, ulong bytes) { }
|
||||
public virtual void AddSendt(ushort id, ulong bytes) { }
|
||||
public virtual void AddReceive(ushort id, long bytes) { }
|
||||
public virtual void AddSendt(ushort id, long bytes) { }
|
||||
public async Task<MessageResponeInfo> SendReply(MessageRequestWrap msg)
|
||||
{
|
||||
if (msg.Connection == null || msg.Connection.Connected == false)
|
||||
@@ -105,7 +105,7 @@ namespace linker.messenger
|
||||
|
||||
byte[] bytes = msg.ToArray(out int length);
|
||||
|
||||
AddSendt(msg.MessengerId, (ulong)bytes.Length);
|
||||
AddSendt(msg.MessengerId, bytes.Length);
|
||||
|
||||
bool res = await msg.Connection.SendAsync(bytes.AsMemory(0, length)).ConfigureAwait(false);
|
||||
msg.Return(bytes);
|
||||
@@ -130,7 +130,7 @@ namespace linker.messenger
|
||||
|
||||
byte[] bytes = msg.ToArray(out int length);
|
||||
|
||||
AddSendt(messengerId, (ulong)length);
|
||||
AddSendt(messengerId, length);
|
||||
|
||||
bool res = await msg.Connection.SendAsync(bytes.AsMemory(0, length)).ConfigureAwait(false);
|
||||
msg.Return(bytes);
|
||||
@@ -151,7 +151,7 @@ namespace linker.messenger
|
||||
byte[] bytes = new byte[wrap.Payload.Length];
|
||||
wrap.Payload.CopyTo(bytes);
|
||||
|
||||
AddReceive(info.MessengerId, (ulong)bytes.Length);
|
||||
AddReceive(info.MessengerId, bytes.Length);
|
||||
info.Tcs.SetResult(new MessageResponeInfo { Code = wrap.Code, Data = bytes, Connection = wrap.Connection });
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<project ver="10" name="linker.tray.win" libEmbed="true" icon="..\linker\favicon.ico" ui="win" output="linker.tray.win.exe" CompanyName="snltty" FileDescription="linker.tray.win" LegalCopyright="Copyright (C) snltty 2024" ProductName="linker.tray.win" InternalName="linker.install.win" FileVersion="0.0.0.213" ProductVersion="0.0.0.213" publishDir="/dist/" dstrip="false" local="false" ignored="false">
|
||||
<project ver="10" name="linker.tray.win" libEmbed="true" icon="..\linker\favicon.ico" ui="win" output="linker.tray.win.exe" CompanyName="snltty" FileDescription="linker.tray.win" LegalCopyright="Copyright (C) snltty 2024" ProductName="linker.tray.win" InternalName="linker.install.win" FileVersion="0.0.0.214" ProductVersion="0.0.0.214" publishDir="/dist/" dstrip="false" local="false" ignored="false">
|
||||
<file name="main.aardio" path="main.aardio" comment="main.aardio"/>
|
||||
<folder name="资源文件" path="res" embed="true" local="false" ignored="false">
|
||||
<file name="favicon.ico" path="res\favicon.ico" comment="res\favicon.ico"/>
|
||||
|
BIN
src/linker.tray.win/dist/linker.tray.win.exe
vendored
BIN
src/linker.tray.win/dist/linker.tray.win.exe
vendored
Binary file not shown.
@@ -34,7 +34,7 @@ namespace linker.tunnel
|
||||
|
||||
private void LoopDiscovery()
|
||||
{
|
||||
TimerHelper.SetInterval(() =>
|
||||
TimerHelper.SetIntervalLong(() =>
|
||||
{
|
||||
NatUtility.StopDiscovery();
|
||||
NatUtility.StartDiscovery();
|
||||
|
@@ -164,7 +164,8 @@ namespace linker.tunnel.transport
|
||||
{
|
||||
|
||||
targetSocket.KeepAlive();
|
||||
targetSocket.ReuseBind(new IPEndPoint(ep.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, tunnelTransportInfo.Local.Local.Port));
|
||||
targetSocket.IPv6Only(ep.AddressFamily, false);
|
||||
targetSocket.ReuseBind(new IPEndPoint(ep.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, tunnelTransportInfo.Local.Local.Port));
|
||||
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
{
|
||||
@@ -218,7 +219,8 @@ namespace linker.tunnel.transport
|
||||
try
|
||||
{
|
||||
targetSocket.Ttl = ip.Address.AddressFamily == AddressFamily.InterNetworkV6 ? (short)2 : (short)(tunnelTransportInfo.Local.RouteLevel);
|
||||
targetSocket.ReuseBind(new IPEndPoint(ip.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, tunnelTransportInfo.Local.Local.Port));
|
||||
targetSocket.IPv6Only(IPAddress.IPv6Any.AddressFamily, false);
|
||||
targetSocket.ReuseBind(new IPEndPoint(IPAddress.IPv6Any, tunnelTransportInfo.Local.Local.Port));
|
||||
_ = targetSocket.ConnectAsync(ip);
|
||||
return targetSocket;
|
||||
}
|
||||
@@ -315,15 +317,10 @@ namespace linker.tunnel.transport
|
||||
|
||||
private async Task StartListen(IPEndPoint local, TunnelTransportInfo tunnelTransportInfo)
|
||||
{
|
||||
IPAddress localIP = tunnelTransportInfo.Local.LocalIps.Any(c => c.AddressFamily == AddressFamily.InterNetworkV6)
|
||||
&& tunnelTransportInfo.Remote.LocalIps.Any(c => c.AddressFamily == AddressFamily.InterNetworkV6)
|
||||
? IPAddress.IPv6Any : IPAddress.Any;
|
||||
|
||||
IPAddress localIP = IPAddress.IPv6Any;
|
||||
Socket socket = new Socket(localIP.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
|
||||
//socket.ReceiveBufferSize = 5 * 1024 * 1024;
|
||||
|
||||
//socket.IPv6Only(localIP.AddressFamily, false);
|
||||
socket.Bind(new IPEndPoint(localIP, local.Port));
|
||||
socket.IPv6Only(localIP.AddressFamily, false);
|
||||
socket.ReuseBind(new IPEndPoint(localIP, local.Port));
|
||||
socket.Listen(int.MaxValue);
|
||||
|
||||
try
|
||||
|
@@ -119,15 +119,16 @@ namespace linker.tunnel.transport
|
||||
LoggerHelper.Instance.Warning($"{Name} connect to {tunnelTransportInfo.Remote.MachineId}->{tunnelTransportInfo.Remote.MachineName} {string.Join("\r\n", tunnelTransportInfo.RemoteEndPoints.Select(c => c.ToString()))}");
|
||||
}
|
||||
|
||||
IPEndPoint ep = tunnelTransportInfo.Remote.LocalIps.Any(c=>c.AddressFamily == AddressFamily.InterNetworkV6)
|
||||
IPEndPoint ep = tunnelTransportInfo.Remote.LocalIps.Any(c => c.AddressFamily == AddressFamily.InterNetworkV6)
|
||||
&& tunnelTransportInfo.Local.LocalIps.Any(c => c.AddressFamily == AddressFamily.InterNetworkV6)
|
||||
? new IPEndPoint(tunnelTransportInfo.Remote.LocalIps.FirstOrDefault(c=>c.AddressFamily == AddressFamily.InterNetworkV6), tunnelTransportInfo.Remote.Remote.Port)
|
||||
: tunnelTransportInfo.Remote.Remote;
|
||||
? new IPEndPoint(tunnelTransportInfo.Remote.LocalIps.FirstOrDefault(c => c.AddressFamily == AddressFamily.InterNetworkV6), tunnelTransportInfo.Remote.Remote.Port)
|
||||
: tunnelTransportInfo.Remote.Remote;
|
||||
Socket targetSocket = new(ep.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
|
||||
try
|
||||
{
|
||||
targetSocket.KeepAlive();
|
||||
targetSocket.ReuseBind(new IPEndPoint(ep.AddressFamily == AddressFamily.InterNetwork ? tunnelTransportInfo.Local.Local.Address : IPAddress.IPv6Any, tunnelTransportInfo.Local.Local.Port));
|
||||
targetSocket.IPv6Only(ep.AddressFamily, false);
|
||||
targetSocket.ReuseBind(new IPEndPoint(ep.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, tunnelTransportInfo.Local.Local.Port));
|
||||
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
{
|
||||
|
@@ -314,7 +314,8 @@ namespace linker.tunnel.transport
|
||||
try
|
||||
{
|
||||
targetSocket.KeepAlive();
|
||||
targetSocket.ReuseBind(new IPEndPoint(ep.AddressFamily == AddressFamily.InterNetwork ? tunnelTransportInfo.Local.Local.Address : IPAddress.IPv6Any, tunnelTransportInfo.Local.Local.Port));
|
||||
targetSocket.IPv6Only(ep.AddressFamily, false);
|
||||
targetSocket.ReuseBind(new IPEndPoint(ep.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, tunnelTransportInfo.Local.Local.Port));
|
||||
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
{
|
||||
|
@@ -147,10 +147,9 @@ namespace linker.tunnel.transport
|
||||
LoggerHelper.Instance.Warning($"{Name} connect to {tunnelTransportInfo.Remote.MachineId}->{tunnelTransportInfo.Remote.MachineName} {string.Join("\r\n", tunnelTransportInfo.RemoteEndPoints.Select(c => c.ToString()))}");
|
||||
}
|
||||
|
||||
IPEndPoint local = new IPEndPoint(tunnelTransportInfo.Local.Local.Address, tunnelTransportInfo.Local.Local.Port);
|
||||
TaskCompletionSource<IPEndPoint> taskCompletionSource = new TaskCompletionSource<IPEndPoint>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
//监听连接
|
||||
Socket remoteUdp = BindListen(local, taskCompletionSource);
|
||||
Socket remoteUdp = BindListen(tunnelTransportInfo.Local.Local, taskCompletionSource);
|
||||
|
||||
//给对方发送简单消息
|
||||
foreach (IPEndPoint ep in tunnelTransportInfo.RemoteEndPoints)
|
||||
@@ -216,7 +215,9 @@ namespace linker.tunnel.transport
|
||||
/// <returns></returns>
|
||||
private Socket BindListen(IPEndPoint local, TaskCompletionSource<IPEndPoint> tcs)
|
||||
{
|
||||
local = new IPEndPoint(IPAddress.IPv6Any, local.Port);
|
||||
Socket socket = new Socket(local.AddressFamily, SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp);
|
||||
socket.IPv6Only(local.AddressFamily, false);
|
||||
socket.WindowsUdpBug();
|
||||
socket.ReuseBind(local);
|
||||
|
||||
@@ -238,9 +239,11 @@ namespace linker.tunnel.transport
|
||||
/// <returns></returns>
|
||||
private async Task BindListen(IPEndPoint local, TunnelTransportInfo state)
|
||||
{
|
||||
local = new IPEndPoint(IPAddress.IPv6Any,local.Port);
|
||||
Socket socket = new Socket(local.AddressFamily, SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp);
|
||||
try
|
||||
{
|
||||
socket.IPv6Only(local.AddressFamily,false);
|
||||
socket.ReuseBind(local);
|
||||
socket.WindowsUdpBug();
|
||||
ListenAsyncToken token = new ListenAsyncToken
|
||||
@@ -267,7 +270,7 @@ namespace linker.tunnel.transport
|
||||
try
|
||||
{
|
||||
byte[] buffer = new byte[8 * 1024];
|
||||
IPEndPoint ep = new IPEndPoint(IPAddress.Any, 0);
|
||||
IPEndPoint ep = new IPEndPoint(IPAddress.IPv6Any, 0);
|
||||
while (true)
|
||||
{
|
||||
SocketReceiveFromResult result = await token.LocalUdp.ReceiveFromAsync(buffer, ep).ConfigureAwait(false);
|
||||
@@ -306,7 +309,7 @@ namespace linker.tunnel.transport
|
||||
/// <param name="tunnelTransportInfo"></param>
|
||||
private void BindAndTTL(TunnelTransportInfo tunnelTransportInfo)
|
||||
{
|
||||
IPEndPoint local = new IPEndPoint(tunnelTransportInfo.Local.Local.Address, tunnelTransportInfo.Local.Local.Port);
|
||||
IPEndPoint local = new IPEndPoint(IPAddress.IPv6Any, tunnelTransportInfo.Local.Local.Port);
|
||||
foreach (var ip in tunnelTransportInfo.RemoteEndPoints)
|
||||
{
|
||||
try
|
||||
@@ -316,15 +319,13 @@ namespace linker.tunnel.transport
|
||||
LoggerHelper.Instance.Warning($"{Name} ttl to {tunnelTransportInfo.Remote.MachineId}->{tunnelTransportInfo.Remote.MachineName} {ip}");
|
||||
}
|
||||
|
||||
if (ip.AddressFamily == AddressFamily.InterNetwork)
|
||||
{
|
||||
Socket socket = new Socket(local.AddressFamily, SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp);
|
||||
socket.WindowsUdpBug();
|
||||
socket.ReuseBind(local);
|
||||
socket.Ttl = (short)(tunnelTransportInfo.Local.RouteLevel);
|
||||
_ = socket.SendToAsync(new byte[0], SocketFlags.None, ip);
|
||||
socket.SafeClose();
|
||||
}
|
||||
Socket socket = new Socket(local.AddressFamily, SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp);
|
||||
socket.IPv6Only(local.AddressFamily, false);
|
||||
socket.WindowsUdpBug();
|
||||
socket.ReuseBind(local);
|
||||
socket.Ttl = (short)(tunnelTransportInfo.Local.RouteLevel);
|
||||
_ = socket.SendToAsync(new byte[0], SocketFlags.None, ip);
|
||||
socket.SafeClose();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@@ -314,7 +314,8 @@ namespace linker.tunnel.transport
|
||||
try
|
||||
{
|
||||
targetSocket.WindowsUdpBug();
|
||||
targetSocket.ReuseBind(new IPEndPoint(ep.AddressFamily == AddressFamily.InterNetwork ? tunnelTransportInfo.Local.Local.Address : IPAddress.IPv6Any, tunnelTransportInfo.Local.Local.Port));
|
||||
targetSocket.IPv6Only(ep.AddressFamily, false);
|
||||
targetSocket.ReuseBind(new IPEndPoint(ep.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, tunnelTransportInfo.Local.Local.Port));
|
||||
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
{
|
||||
@@ -322,7 +323,7 @@ namespace linker.tunnel.transport
|
||||
}
|
||||
|
||||
await targetSocket.SendToAsync($"{flagTexts}-{tunnelTransportInfo.Local.MachineId}-{tunnelTransportInfo.FlowId}".ToBytes(), ep).ConfigureAwait(false);
|
||||
await targetSocket.ReceiveFromAsync(new byte[1024], new IPEndPoint(ep.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any: IPAddress.IPv6Any, 0)).WaitAsync(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false);
|
||||
await targetSocket.ReceiveFromAsync(new byte[1024], new IPEndPoint(IPAddress.IPv6Any, 0)).WaitAsync(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false);
|
||||
|
||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
LoggerHelper.Instance.Debug($"{Name} connect to {tunnelTransportInfo.Remote.MachineId}->{tunnelTransportInfo.Remote.MachineName} {ep} success");
|
||||
@@ -365,7 +366,7 @@ namespace linker.tunnel.transport
|
||||
|
||||
private void CleanTask()
|
||||
{
|
||||
TimerHelper.SetInterval(() =>
|
||||
TimerHelper.SetIntervalLong(() =>
|
||||
{
|
||||
var keys = connectionsDic.Where(c => (c.Value.Connection == null && c.Value.LastTicks.DiffGreater(5000)) || (c.Value.Connection != null && c.Value.Connection.Connected == false)).Select(c => c.Key).ToList();
|
||||
foreach (var item in keys)
|
||||
|
9
src/linker.web/package-lock.json
generated
9
src/linker.web/package-lock.json
generated
@@ -11,6 +11,7 @@
|
||||
"@element-plus/icons-vue": "^2.3.1",
|
||||
"core-js": "^3.38.0",
|
||||
"element-plus": "^2.8.0",
|
||||
"moment": "^2.30.1",
|
||||
"vue": "^3.4.38",
|
||||
"vue-i18n": "^11.0.1",
|
||||
"vue-router": "^4.4.3"
|
||||
@@ -6792,6 +6793,14 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/moment": {
|
||||
"version": "2.30.1",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
|
||||
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/mrmime": {
|
||||
"version": "2.0.0",
|
||||
"dev": true,
|
||||
|
@@ -10,6 +10,7 @@
|
||||
"@element-plus/icons-vue": "^2.3.1",
|
||||
"core-js": "^3.38.0",
|
||||
"element-plus": "^2.8.0",
|
||||
"moment": "^2.30.1",
|
||||
"vue": "^3.4.38",
|
||||
"vue-i18n": "^11.0.1",
|
||||
"vue-router": "^4.4.3"
|
||||
|
1
src/linker.web/public/aliyun.svg
Normal file
1
src/linker.web/public/aliyun.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1741182934817" class="icon" viewBox="0 0 1653 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9416" xmlns:xlink="http://www.w3.org/1999/xlink" width="322.8515625" height="200"><path d="M344.8620198 721.82988526a57.857089 57.857089 0 0 1-46.13274501-56.07295017v-308.4012244a59.89610558 59.89610558 0 0 1 46.13274501-56.07295017l286.35436058-62.06256065 30.07549089-122.72329718H328.80476645A210.78331632 210.78331632 0 0 0 116.61962599 327.28021902v364.47417458a213.71440233 213.71440233 0 0 0 212.18514046 212.31257895h332.48710482l-30.07549089-122.21354321zM1178.05508073 116.49690269H843.01920461l30.58524561 122.72329718 286.35436059 62.06256065a57.98452749 57.98452749 0 0 1 46.132745 56.07295017v308.4012244a60.15098257 60.15098257 0 0 1-46.13274502 56.07295017l-286.35436057 62.06256066-30.58524561 122.72329716H1178.05508073a212.44001744 212.44001744 0 0 0 212.94977139-212.82233291V327.28021902A213.33208686 213.33208686 0 0 0 1178.05508073 116.49690269z" fill="#F76E05" p-id="9417"></path><path d="M631.21638038 495.49906876h244.29964793v30.07549166H631.21638038z" fill="#F76E05" p-id="9418"></path></svg>
|
After Width: | Height: | Size: 1.2 KiB |
1
src/linker.web/public/amazon.svg
Normal file
1
src/linker.web/public/amazon.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1741182827482" class="icon" viewBox="0 0 1126 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7578" xmlns:xlink="http://www.w3.org/1999/xlink" width="219.921875" height="200"><path d="M344.73911 382.012725a206.3919 206.3919 0 0 0-34.79709 120.77158 181.777165 181.777165 0 0 0 50.646146 137.638871 179.607881 179.607881 0 0 0 129.448717 48.698218 305.691993 305.691993 0 0 0 86.01876-10.270897 251.504158 251.504158 0 0 0 112.581425-77.784335c2.744809 3.497417 7.481817 10.093812 14.432381 20.054812a230.519654 230.519654 0 0 0 14.78655 20.01054c3.010435 3.364604 8.145884 8.854221 15.317803 16.291768a326.587956 326.587956 0 0 0 25.057446 23.552228 28.289237 28.289237 0 0 0 29.705913-2.125013l92.128173-79.687992a17.708443 17.708443 0 0 0 8.145884-14.255297 30.547064 30.547064 0 0 0-6.153684-16.42458l-23.463686-31.211131a119.886158 119.886158 0 0 1-14.78655-31.786654 143.349844 143.349844 0 0 1-7.747444-48.698218V209.178324c0-2.656266-0.265627-11.377674-0.973964-26.031411a144.810791 144.810791 0 0 0-3.098978-28.687677q-3.320333-11.908928-6.197955-23.906398a101.159479 101.159479 0 0 0-9.164119-26.562664 175.092228 175.092228 0 0 0-13.812585-20.984505 208.428371 208.428371 0 0 0-18.859492-22.135553A258.897433 258.897433 0 0 0 601.777156 0.484326h-25.544428a320.257187 320.257187 0 0 0-159.110359 49.096657 196.38663 196.38663 0 0 0-85.398965 135.026877 30.989775 30.989775 0 0 0-1.018235 7.171919c0 9.518288 5.843786 15.671972 17.354274 18.461051l117.672602 14.343839a26.208495 26.208495 0 0 0 20.541793-23.552229 83.451037 83.451037 0 0 1 31.653842-51.177399 111.828816 111.828816 0 0 1 58.39359-21.515758h7.924528a76.589015 76.589015 0 0 1 67.557709 30.989775 182.219876 182.219876 0 0 1 14.432381 87.966689v17.354274q-45.067987 3.453146-90.047431 8.145884a515.050058 515.050058 0 0 0-136.000841 33.778854 215.069037 215.069037 0 0 0-95.18288 75.747864z m161.058287 164.245807a97.396435 97.396435 0 0 1-19.877727-64.060292 109.57099 109.57099 0 0 1 90.00316-113.511118 373.072618 373.072618 0 0 1 90.047431-8.234426v25.500158q0 32.760619-0.486982 47.148729a196.38663 196.38663 0 0 1-6.109413 37.276272 166.857802 166.857802 0 0 1-16.867291 42.455991 104.125643 104.125643 0 0 1-66.406661 55.206071 50.77896 50.77896 0 0 0-7.747443 1.062506 56.534204 56.534204 0 0 1-8.854222 0.929693 66.40666 66.40666 0 0 1-53.700852-23.729313z" fill="#221F1F" p-id="7579"></path><path d="M915.570762 811.663818a36.302308 36.302308 0 0 1 6.109413-8.190155 161.766625 161.766625 0 0 1 49.273742-23.463686 336.460413 336.460413 0 0 1 75.615051-11.244862 61.448296 61.448296 0 0 1 19.435016 1.018236c30.724148 2.833351 49.229471 7.880257 55.294612 15.494887a32.096553 32.096553 0 0 1 4.072942 18.283967v7.17192a233.264462 233.264462 0 0 1-19.435016 84.38073 198.37883 198.37883 0 0 1-54.143564 78.315588 15.317803 15.317803 0 0 1-9.296932 4.117213 8.854221 8.854221 0 0 1-4.072942-1.018236c-4.427111-2.125013-5.135448-5.843786-3.098978-11.244861a387.682083 387.682083 0 0 0 37.807526-123.959099 26.562664 26.562664 0 0 0-4.072942-16.424581c-6.81775-8.101613-25.898598-12.218826-57.331084-12.218826-11.554759 0-25.19026 0.708338-40.773689 2.125014-17.177189 2.125013-32.849161 4.117213-47.148729 6.153683a11.510488 11.510488 0 0 1-8.190155-2.125013 3.18752 3.18752 0 0 1-0.973964-4.072942 6.950564 6.950564 0 0 1 0.973964-3.054706z" fill="#FF9900" p-id="7580"></path><path d="M2.125013 794.353815q5.046906-8.190155 16.336039-1.062506a1090.043195 1090.043195 0 0 0 556.576356 148.39675 1102.350562 1102.350562 0 0 0 396.005051-74.729628l14.78655-6.153684a392.242007 392.242007 0 0 0 13.812585-6.109413 18.328238 18.328238 0 0 1 24.127754 6.109413c5.755244 8.145884 3.851586 15.716243-5.622431 22.489722-12.351639 8.854221-28.023611 19.125118-47.148729 30.679877a764.252119 764.252119 0 0 1-196.38663 80.883312 829.419188 829.419188 0 0 1-211.748705 28.643407 820.033713 820.033713 0 0 1-301.751864-55.737324 830.216068 830.216068 0 0 1-254.824492-157.073887 13.901128 13.901128 0 0 1-6.242226-10.182355 10.580795 10.580795 0 0 1 2.125013-6.153684z" fill="#FF9900" p-id="7581"></path></svg>
|
After Width: | Height: | Size: 4.1 KiB |
1
src/linker.web/public/huawei.svg
Normal file
1
src/linker.web/public/huawei.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 5.0 KiB |
@@ -11,4 +11,13 @@ export const relayConnect = (data) => {
|
||||
}
|
||||
export const relayCdkeyAccess = () => {
|
||||
return sendWebsocketMsg('relay/AccessCdkey');
|
||||
}
|
||||
export const relayCdkeyPage = (data) => {
|
||||
return sendWebsocketMsg('relay/PageCdkey', data);
|
||||
}
|
||||
export const relayCdkeyAdd = (data) => {
|
||||
return sendWebsocketMsg('relay/AddCdkey', data);
|
||||
}
|
||||
export const relayCdkeyDel = (data) => {
|
||||
return sendWebsocketMsg('relay/DelCdkey', data);
|
||||
}
|
@@ -11,7 +11,6 @@ export default {
|
||||
|
||||
'head.home': 'Home',
|
||||
'head.server': 'Server',
|
||||
'head.group': 'Group',
|
||||
'head.protocol': 'P2P Protocol',
|
||||
'head.action': 'Action',
|
||||
'head.logger': 'Logs',
|
||||
@@ -38,13 +37,19 @@ export default {
|
||||
'server.messengerSecretKey': 'Messenger SecretKey',
|
||||
'server.messengerSecretKeyText': 'Messenger SecretKey',
|
||||
'server.messengerUserId': 'User Id',
|
||||
'server.messengerUserIdText': 'Your unique identifier,for card key (CDKEY).',
|
||||
'server.messengerUserIdText': 'Your unique identifier,used to unlock something.',
|
||||
|
||||
'permission.closed': 'Closed',
|
||||
'permission.simple': 'Simple',
|
||||
'permission.full': 'Full',
|
||||
'permission.clear': 'Clear connection',
|
||||
|
||||
'status.group': 'Group manager',
|
||||
'status.groupName': 'Name',
|
||||
'status.groupPassword': 'Password',
|
||||
'status.groupOper': 'Oper',
|
||||
'status.groupDelConfirm': 'Are you sure to delete?',
|
||||
|
||||
'status.support': 'Support',
|
||||
'status.export': 'Export',
|
||||
'status.exportText': 'Export the configuration to run elsewhere',
|
||||
@@ -126,6 +131,24 @@ export default {
|
||||
'server.relayMyCdkey': 'My CDKEY',
|
||||
'server.relayCdkey': 'Manager CDKEY',
|
||||
|
||||
'server.relayCdkeyUserId': 'UserId',
|
||||
'server.relayCdkeyBandwidth': 'Bandwidth',
|
||||
'server.relayCdkeyMaxBytes': 'Total',
|
||||
'server.relayCdkeyLastBytes': 'Surplus',
|
||||
'server.relayCdkeyMemory': 'Price',
|
||||
'server.relayCdkeyPayMemory': 'Pay',
|
||||
'server.relayCdkeyAddTime': 'Add',
|
||||
'server.relayCdkeyStartTime': 'Start',
|
||||
'server.relayCdkeyDuration': 'Duration',
|
||||
'server.relayCdkeyStartTimeY': 'Year',
|
||||
'server.relayCdkeyStartTimeM': 'Month',
|
||||
'server.relayCdkeyEndTime': 'End',
|
||||
'server.relayCdkeyUseTime': 'Use',
|
||||
'server.relayCdkeyRemark': 'Remark',
|
||||
'server.relayCdkeyOper': 'Oper',
|
||||
'server.relayCdkeyDelConfirm': 'Are you sure to delete?',
|
||||
|
||||
|
||||
'server.sforwardSecretKey': 'Server forward secretKey',
|
||||
'server.sforwardText': 'The server forward can be used when the key is correct',
|
||||
|
||||
@@ -139,11 +162,6 @@ export default {
|
||||
'server.updaterMM': 'Minute',
|
||||
'server.updaterS': 'Second',
|
||||
|
||||
'server.groupName': 'Name',
|
||||
'server.groupPassword': 'Password',
|
||||
'server.groupOper': 'Oper',
|
||||
'server.groupDelConfirm': 'Are you sure to delete?',
|
||||
|
||||
'server.asyncText': 'Synchronize to all clients',
|
||||
'server.asyncSelect': 'Please select',
|
||||
'server.asyncCheckAll': 'Check all',
|
||||
|
@@ -37,13 +37,19 @@ export default {
|
||||
'server.messengerSecretKey': '信标密钥',
|
||||
'server.messengerSecretKeyText': '密钥正确时可连接服务器',
|
||||
'server.messengerUserId': '用户id',
|
||||
'server.messengerUserIdText': '你的唯一标识,用于流量卡密CDKEY',
|
||||
'server.messengerUserIdText': '你的唯一标识,用于解锁一些限制',
|
||||
|
||||
'permission.closed': '禁止通行',
|
||||
'permission.simple': '简单管理',
|
||||
'permission.full': '专业管理',
|
||||
'permission.clear': '清除连接',
|
||||
|
||||
'status.group': '管理分组',
|
||||
'status.groupName': '名称',
|
||||
'status.groupPassword': '密码',
|
||||
'status.groupOper': '操作',
|
||||
'status.groupDelConfirm': '确认删除吗?',
|
||||
|
||||
'status.support': '赞助',
|
||||
|
||||
'status.export': '导出配置',
|
||||
@@ -128,6 +134,23 @@ export default {
|
||||
'server.relayMyCdkey': '我的CDKEY',
|
||||
'server.relayCdkey': '管理CDKEY',
|
||||
|
||||
'server.relayCdkeyUserId': '用户标识',
|
||||
'server.relayCdkeyBandwidth': '最大带宽',
|
||||
'server.relayCdkeyMaxBytes': '总流量',
|
||||
'server.relayCdkeyLastBytes': '剩余流量',
|
||||
'server.relayCdkeyMemory': '原价',
|
||||
'server.relayCdkeyPayMemory': '支付',
|
||||
'server.relayCdkeyAddTime': '添加',
|
||||
'server.relayCdkeyStartTime': '开始',
|
||||
'server.relayCdkeyDuration': '持续时间',
|
||||
'server.relayCdkeyStartTimeY': '年',
|
||||
'server.relayCdkeyStartTimeM': '月',
|
||||
'server.relayCdkeyEndTime': '结束',
|
||||
'server.relayCdkeyUseTime': '使用',
|
||||
'server.relayCdkeyRemark': '备注',
|
||||
'server.relayCdkeyOper': '操作',
|
||||
'server.relayCdkeyDelConfirm': '确认删除吗?',
|
||||
|
||||
'server.sforwardSecretKey': '服务器穿透密钥',
|
||||
'server.sforwardText': '当密钥正确是可用',
|
||||
|
||||
@@ -141,10 +164,7 @@ export default {
|
||||
'server.updaterMM': '分',
|
||||
'server.updaterS': '秒',
|
||||
|
||||
'server.groupName': '名称',
|
||||
'server.groupPassword': '密码',
|
||||
'server.groupOper': '操作',
|
||||
'server.groupDelConfirm': '确认删除吗?',
|
||||
|
||||
|
||||
'server.asyncText': '同步到所有客户端',
|
||||
'server.asyncSelect': '请选择',
|
||||
|
@@ -16,11 +16,6 @@ const routes = [
|
||||
name: 'FullServers',
|
||||
component: () => import('@/views/full/server/Index.vue')
|
||||
},
|
||||
{
|
||||
path: '/full/group.html',
|
||||
name: 'FullGroup',
|
||||
component: () => import('@/views/full/group/Index.vue')
|
||||
},
|
||||
{
|
||||
path: '/full/transport.html',
|
||||
name: 'FullTransport',
|
||||
|
@@ -14,9 +14,6 @@
|
||||
<li v-if="hasConfig">
|
||||
<router-link :to="{name:'FullServers'}"><img src="@/assets/fuwuqi.svg"/> {{$t('head.server')}}</router-link>
|
||||
</li>
|
||||
<li v-if="hasGroup">
|
||||
<router-link :to="{name:'FullGroup'}"><img src="@/assets/group.svg"/> {{$t('head.group')}}</router-link>
|
||||
</li>
|
||||
<li v-if="hasTransport">
|
||||
<router-link :to="{name:'FullTransport'}"><img src="@/assets/dadong.svg"/> {{$t('head.protocol')}}</router-link>
|
||||
</li>
|
||||
|
@@ -9,11 +9,17 @@
|
||||
class="system"
|
||||
:src="`https://unpkg.com/flag-icons@7.2.3/flags/4x3/${tunnel.list[scope.row.MachineId].Net.CountryCode.toLowerCase()}.svg`" />
|
||||
</template>
|
||||
<template v-else>
|
||||
<img title="?" class="system" src="/system.svg" />
|
||||
</template>
|
||||
<template v-if="tunnel.list[scope.row.MachineId].Net.Isp">
|
||||
<img
|
||||
:title="`${tunnel.list[scope.row.MachineId].Net.Isp}、${tunnel.list[scope.row.MachineId].Net.Org}、${tunnel.list[scope.row.MachineId].Net.As}`"
|
||||
class="system" :src="netImg(tunnel.list[scope.row.MachineId].Net)" />
|
||||
</template>
|
||||
<template v-else>
|
||||
<img title="?" class="system" src="/system.svg" />
|
||||
</template>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<a href="javascript:;" class="a-line"
|
||||
@@ -67,11 +73,16 @@ export default {
|
||||
'china telecom':'chinanet.svg',
|
||||
'china unicom':'chinaunicom.svg',
|
||||
'china mobile':'chinamobile.svg',
|
||||
'huawei':'huawei.svg',
|
||||
'amazon':'amazon.svg',
|
||||
'aliyun':'aliyun.svg',
|
||||
}
|
||||
const netImg = (item)=>{
|
||||
const isp = item.Isp.toLowerCase();
|
||||
const org = item.Org.toLowerCase();
|
||||
const as = item.As.toLowerCase();
|
||||
for(let j in imgMap){
|
||||
if(as.indexOf(j) > -1){
|
||||
if(isp.indexOf(j) > -1 || org.indexOf(j) > -1 || as.indexOf(j) > -1){
|
||||
return `./${imgMap[j]}`;
|
||||
}
|
||||
}
|
||||
@@ -121,7 +132,7 @@ export default {
|
||||
|
||||
img.system{
|
||||
height:1.4rem;
|
||||
vertical-align:middle;
|
||||
margin-right:.4rem
|
||||
border: 1px solid #eee;
|
||||
}
|
||||
</style>
|
@@ -10,7 +10,7 @@
|
||||
<a href="javascript:;" @click="state.show=true" class="mgl-1 delay a-line" :class="{red:state.nodes.length==0,green:state.nodes.length>0}">
|
||||
{{$t('server.relayNodes')}} : {{state.nodes.length}}
|
||||
</a>
|
||||
<Relay></Relay>
|
||||
<RelayCdkey></RelayCdkey>
|
||||
</div>
|
||||
|
||||
</el-form-item>
|
||||
@@ -68,9 +68,9 @@ import { ElMessage } from 'element-plus';
|
||||
import { onMounted, onUnmounted, reactive, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import Sync from '../sync/Index.vue'
|
||||
import Relay from './relay/Index.vue'
|
||||
import RelayCdkey from './relayCdkey/Index.vue'
|
||||
export default {
|
||||
components:{Sync,Relay},
|
||||
components:{Sync,RelayCdkey},
|
||||
setup(props) {
|
||||
const {t} = useI18n();
|
||||
const globalData = injectGlobalData();
|
||||
|
@@ -1,25 +1,29 @@
|
||||
<template>
|
||||
<a href="javascript:;" class="mgl-1 a-line">{{$t('server.relayMyCdkey')}}</a>
|
||||
<a v-if="state.showManager && hasRelayCdkey" href="javascript:;" class="mgl-1 a-line">{{$t('server.relayCdkey')}}</a>
|
||||
<a v-if="state.hasRelayCdkey && hasRelayCdkey" @click="state.showManager = true" href="javascript:;" class="mgl-1 a-line">{{$t('server.relayCdkey')}}</a>
|
||||
<Manager v-if="state.showManager" v-model="state.showManager" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { relayCdkeyAccess } from '@/apis/relay';
|
||||
import { injectGlobalData } from '@/provide';
|
||||
import { computed, onMounted, reactive } from 'vue';
|
||||
|
||||
import Manager from './Manager.vue'
|
||||
export default {
|
||||
components:{Manager},
|
||||
setup () {
|
||||
|
||||
const globalData = injectGlobalData();
|
||||
const hasRelayCdkey = computed(()=>globalData.value.hasAccess('RelayCdkey'));
|
||||
const state = reactive({
|
||||
showManager:false
|
||||
hasRelayCdkey:false,
|
||||
showManager:false,
|
||||
showList:false,
|
||||
});
|
||||
|
||||
onMounted(()=>{
|
||||
relayCdkeyAccess().then(res=>{
|
||||
state.showManager = res;
|
||||
state.hasRelayCdkey = res;
|
||||
}).catch(()=>{})
|
||||
})
|
||||
|
233
src/linker.web/src/views/full/server/relayCdkey/Manager.vue
Normal file
233
src/linker.web/src/views/full/server/relayCdkey/Manager.vue
Normal file
@@ -0,0 +1,233 @@
|
||||
<template>
|
||||
<el-dialog class="options-center" :title="$t('server.relayCdkey')" destroy-on-close v-model="state.show" width="77rem" top="2vh">
|
||||
<div class="group-wrap">
|
||||
<div class="head flex">
|
||||
<div><span>用户id</span> <el-input v-model="state.page.UserId" style="width:10rem" size="small" clearable @change="handleSearch" /></div>
|
||||
<div><span>备注</span> <el-input v-model="state.page.Remark" style="width:10rem" size="small" clearable @change="handleSearch" /></div>
|
||||
<div>
|
||||
<el-button size="small" @click="handleSearch()">
|
||||
<el-icon><Search /></el-icon>
|
||||
</el-button>
|
||||
</div>
|
||||
<div>
|
||||
<el-button size="small" type="success" @click="handleAdd()">
|
||||
<el-icon><Plus /></el-icon>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-table stripe :data="state.list.List" border size="small" width="100%" @cell-dblclick="handleCellClick">
|
||||
<el-table-column prop="Bandwidth" :label="$t('server.relayCdkeyBandwidth')" width="110" sortable="custom">
|
||||
<template #default="scope">{{ scope.row.Bandwidth }}Mbps</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="LastBytes" :label="`${$t('server.relayCdkeyLastBytes')}/${$t('server.relayCdkeyMaxBytes')}`" width="160" sortable="custom">
|
||||
<template #default="scope">{{ parseSpeed(scope.row.LastBytes) }}/{{ parseSpeed(scope.row.MaxBytes) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="PayMemory" :label="`${$t('server.relayCdkeyPayMemory')}/${$t('server.relayCdkeyMemory')}`" width="120" sortable="custom">
|
||||
<template #default="scope">{{ scope.row.PayMemory }}/{{ scope.row.Memory }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="Remark" :label="$t('server.relayCdkeyRemark')">
|
||||
</el-table-column>
|
||||
<el-table-column prop="EndTime" :label="`${$t('server.relayCdkeyEndTime')}`" width="140" sortable="custom">
|
||||
</el-table-column>
|
||||
<el-table-column prop="UseTime" :label="`${$t('server.relayCdkeyUseTime')}`" width="140" sortable="custom">
|
||||
</el-table-column>
|
||||
<el-table-column prop="StartTime" :label="`${$t('server.relayCdkeyStartTime')}`" width="140" sortable="custom">
|
||||
</el-table-column>
|
||||
<el-table-column prop="AddTime" :label="`${$t('server.relayCdkeyAddTime')}`" width="140" sortable="custom">
|
||||
</el-table-column>
|
||||
<el-table-column fixed="right" prop="Oper" :label="$t('server.relayCdkeyOper')" width="60">
|
||||
<template #default="scope">
|
||||
<div>
|
||||
<el-popconfirm :title="$t('server.relayCdkeyDelConfirm')" @confirm="handleDel(scope.row)">
|
||||
<template #reference>
|
||||
<el-button type="danger" size="small">
|
||||
<el-icon><Delete /></el-icon>
|
||||
</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="t-c">
|
||||
<div class="page">
|
||||
<el-pagination small background layout="prev, pager, next"
|
||||
:page-size="state.page.Size"
|
||||
:total="state.list.Count"
|
||||
:pager-count="5"
|
||||
:current-page="state.page.Page" @current-change="handlePageChange" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<el-dialog class="options-center" :title="$t('server.relayCdkey')" destroy-on-close v-model="state.showAdd" width="42rem" top="2vh">
|
||||
<div>
|
||||
<el-form ref="ruleFormRef" :model="state.ruleForm" :rules="state.rules" label-width="auto">
|
||||
<el-form-item :label="$t('server.relayCdkeyUserId')" prop="UserId">
|
||||
<el-input maxlength="32" show-word-limit v-model="state.ruleForm.UserId" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('server.relayCdkeyBandwidth')" prop="Bandwidth">
|
||||
<el-input-number size="small" v-model="state.ruleForm.Bandwidth" :min="1" :max="102400" />Mbps
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('server.relayCdkeyMaxBytes')" prop="MaxBytes">
|
||||
<el-input-number size="small" v-model="state.ruleForm.G" :min="0" :max="102400" />GB
|
||||
<el-input-number size="small" v-model="state.ruleForm.M" :min="0" :max="1024" />MB
|
||||
<el-input-number size="small" v-model="state.ruleForm.K" :min="0" :max="1024" />KB
|
||||
<el-input-number size="small" v-model="state.ruleForm.B" :min="0" :max="1024" />B
|
||||
</el-form-item>
|
||||
<el-form-item></el-form-item>
|
||||
<el-form-item :label="$t('server.relayCdkeyStartTime')" prop="StartTime">
|
||||
<el-date-picker v-model="state.ruleForm.StartTime" type="datetime" placeholder="Select date and time"/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('server.relayCdkeyEndTime')" prop="EndTime">
|
||||
<el-date-picker v-model="state.ruleForm.EndTime" type="datetime" placeholder="Select date and time"/>
|
||||
</el-form-item>
|
||||
<el-form-item></el-form-item>
|
||||
<el-form-item :label="$t('server.relayCdkeyMemory')" prop="Memory">
|
||||
<el-input-number size="small" v-model="state.ruleForm.Memory" :min="0" />
|
||||
{{ $t('server.relayCdkeyPayMemory') }}
|
||||
<el-input-number size="small" v-model="state.ruleForm.PayMemory" :min="0" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('server.relayCdkeyRemark')" prop="Remark">
|
||||
<el-input v-model="state.ruleForm.Remark" />
|
||||
</el-form-item>
|
||||
<el-form-item></el-form-item>
|
||||
<el-form-item label="" prop="Btns">
|
||||
<div class="t-c w-100">
|
||||
<el-button @click="state.showAdd = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleSave">确认</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { injectGlobalData } from '@/provide';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { onMounted, reactive, ref, watch } from 'vue'
|
||||
import { Delete,Plus,Search } from '@element-plus/icons-vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import moment from "moment";
|
||||
import { relayCdkeyAdd,relayCdkeyDel,relayCdkeyPage } from '@/apis/relay';
|
||||
export default {
|
||||
props: ['modelValue'],
|
||||
emits: ['update:modelValue'],
|
||||
components:{Delete,Plus,Search },
|
||||
setup(props,{emit}) {
|
||||
const {t} = useI18n();
|
||||
const globalData = injectGlobalData();
|
||||
const defaultJson = {
|
||||
UserId:'',
|
||||
Bandwidth:1,
|
||||
G:1,
|
||||
M:0,
|
||||
K:0,
|
||||
B:0,
|
||||
StartTime:new Date(),
|
||||
EndTime:new Date(new Date().getFullYear() + 1,new Date().getMonth(),new Date().getDay(),new Date().getHours(),new Date().getMinutes(),new Date().getSeconds()),
|
||||
Memory:0,
|
||||
PayMemory:0,
|
||||
Remark:'',
|
||||
};
|
||||
const state = reactive({
|
||||
page:{
|
||||
Page:1,
|
||||
Size:15,
|
||||
Order:'',
|
||||
Sort:'',
|
||||
Userid:'',
|
||||
Remark:'',
|
||||
},
|
||||
list:{
|
||||
Page:1,
|
||||
Size:15,
|
||||
Count:0,
|
||||
List:[]
|
||||
},
|
||||
show:true,
|
||||
showAdd:false,
|
||||
ruleForm:JSON.parse(JSON.stringify(defaultJson)),
|
||||
rules:{
|
||||
UserId: [{ required: true, message: "required", trigger: "blur" }],
|
||||
Remark: [{ required: true, message: "required", trigger: "blur" }],
|
||||
}
|
||||
});
|
||||
watch(() => state.show, (val) => {
|
||||
if (!val) {
|
||||
setTimeout(() => {
|
||||
emit('update:modelValue', val);
|
||||
}, 300);
|
||||
}
|
||||
});
|
||||
const parseSpeed = (num) => {
|
||||
let index = 0;
|
||||
while (num >= 1024) {
|
||||
num /= 1024;
|
||||
index++;
|
||||
}
|
||||
return `${(num*1.0).toFixed(2)}${['B', 'KB', 'MB', 'GB', 'TB'][index]}`;
|
||||
}
|
||||
|
||||
const handleSearch = ()=>{
|
||||
relayCdkeyPage(state.page).then((res)=>{
|
||||
state.list = res;
|
||||
}).catch(()=>{})
|
||||
}
|
||||
const handlePageChange = (p)=>{
|
||||
state.page.Page = p;
|
||||
handleSearch();
|
||||
}
|
||||
|
||||
const handleAdd = (row)=>{
|
||||
state.ruleForm = JSON.parse(JSON.stringify(defaultJson));
|
||||
state.showAdd = true;
|
||||
}
|
||||
const handleDel = (row)=>{
|
||||
relayCdkeyDel(row.CdkeyId).then((res)=>{
|
||||
handleSearch();
|
||||
}).catch(()=>{})
|
||||
}
|
||||
const ruleFormRef = ref(null);
|
||||
const handleSave = ()=>{
|
||||
|
||||
ruleFormRef.value.validate((valid) => {
|
||||
if (!valid) return;
|
||||
|
||||
const json = JSON.parse(JSON.stringify(state.ruleForm));
|
||||
json.StartTime = moment(json.StartTime).format("YYYY-MM-DD HH:mm:ss");
|
||||
json.MaxBytes = json.G*1024*1024*1024 + json.M*1024*1024 + json.K*1024 + json.B;
|
||||
|
||||
relayCdkeyAdd(json).then(()=>{
|
||||
ElMessage.success(t('common.oper'));
|
||||
state.showAdd = false;
|
||||
handleSearch();
|
||||
}).catch(()=>{
|
||||
ElMessage.error(t('common.operFail'));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
onMounted(()=>{
|
||||
handleSearch();
|
||||
})
|
||||
|
||||
return {state,ruleFormRef,parseSpeed,handleSearch,handlePageChange,handleAdd,handleDel,handleSave}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="stylus" scoped>
|
||||
.head{
|
||||
&>div{
|
||||
margin-right:1rem;
|
||||
}
|
||||
}
|
||||
.page{
|
||||
padding:2rem 0;
|
||||
display:inline-block;
|
||||
}
|
||||
.el-form-item{margin-bottom:1rem}
|
||||
.el-input-number--small{width:10rem !important}
|
||||
</style>
|
@@ -1,7 +1,8 @@
|
||||
<template>
|
||||
<div class="group-wrap">
|
||||
<el-table stripe :data="state.list" border size="small" width="100%" :height="`${state.height}px`" @cell-dblclick="handleCellClick">
|
||||
<el-table-column prop="Name" :label="$t('server.groupName')" width="100">
|
||||
<el-dialog class="options-center" :title="$t('status.group')" destroy-on-close v-model="state.show" width="77rem" top="2vh">
|
||||
<div class="group-wrap">
|
||||
<el-table stripe :data="state.list" border size="small" width="100%" height="70vh" @cell-dblclick="handleCellClick">
|
||||
<el-table-column prop="Name" :label="$t('status.groupName')" width="100">
|
||||
<template #default="scope">
|
||||
<template v-if="scope.row.NameEditing">
|
||||
<el-input autofocus size="small" v-model="scope.row.Name"
|
||||
@@ -23,7 +24,7 @@
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="Password" :label="$t('server.groupPassword')" >
|
||||
<el-table-column prop="Password" :label="$t('status.groupPassword')" >
|
||||
<template #default="scope">
|
||||
<template v-if="scope.row.PasswordEditing">
|
||||
<el-input type="password" show-password size="small" v-model="scope.row.Password" @blur="handleEditBlur(scope.row, 'Password')"></el-input>
|
||||
@@ -31,15 +32,15 @@
|
||||
<template v-else>{{ scope.row.Password.replace(/.{1}/g,'*') }}</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="Oper" :label="$t('server.groupOper')" width="160">
|
||||
<el-table-column prop="Oper" :label="$t('status.groupOper')" width="110">
|
||||
<template #header>
|
||||
<div class="flex">
|
||||
<strong>{{ $t('server.groupOper') }}</strong><span class="flex-1"></span><Sync name="GroupSecretKey"></Sync>
|
||||
<strong>{{ $t('status.groupOper') }}</strong><span class="flex-1"></span><Sync name="GroupSecretKey"></Sync>
|
||||
</div>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<div>
|
||||
<el-popconfirm :title="$t('server.groupDelConfirm')" @confirm="handleDel(scope.$index)">
|
||||
<el-popconfirm :title="$t('status.groupDelConfirm')" @confirm="handleDel(scope.$index)">
|
||||
<template #reference>
|
||||
<el-button type="danger" size="small">
|
||||
<el-icon><Delete /></el-icon>
|
||||
@@ -49,15 +50,17 @@
|
||||
<el-button size="small" @click="handleAdd(scope.$index)">
|
||||
<el-icon><Plus /></el-icon>
|
||||
</el-button>
|
||||
<el-button v-if="scope.$index > 0" type="primary" size="small" @click="handleUse(scope.$index)">
|
||||
<!-- <el-button v-if="scope.$index > 0" type="primary" size="small" @click="handleUse(scope.$index)">
|
||||
<el-icon><Select /></el-icon>
|
||||
</el-button>
|
||||
</el-button> -->
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { setSignIn, setSignInGroups } from '@/apis/signin';
|
||||
import { injectGlobalData } from '@/provide';
|
||||
@@ -65,21 +68,30 @@ import { ElMessage } from 'element-plus';
|
||||
import { computed, reactive, watch } from 'vue'
|
||||
import { Delete,Plus,Select } from '@element-plus/icons-vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import Sync from '../sync/Index.vue'
|
||||
import Sync from '../../sync/Index.vue'
|
||||
export default {
|
||||
props: ['modelValue'],
|
||||
emits: ['update:modelValue'],
|
||||
components:{Delete,Plus,Select,Sync },
|
||||
setup(props) {
|
||||
setup(props,{emit}) {
|
||||
const {t} = useI18n();
|
||||
const globalData = injectGlobalData();
|
||||
const state = reactive({
|
||||
list:globalData.value.config.Client.Groups || [],
|
||||
height: computed(()=>globalData.value.height-70),
|
||||
show:true
|
||||
});
|
||||
watch(()=>globalData.value.config.Client.Groups,()=>{
|
||||
if(state.list.filter(c=>c['__editing']).length == 0){
|
||||
state.list = globalData.value.config.Client.Groups;
|
||||
}
|
||||
})
|
||||
});
|
||||
watch(() => state.show, (val) => {
|
||||
if (!val) {
|
||||
setTimeout(() => {
|
||||
emit('update:modelValue', val);
|
||||
}, 300);
|
||||
}
|
||||
});
|
||||
|
||||
const handleCellClick = (row, column) => {
|
||||
handleEdit(row, column.property);
|
||||
@@ -143,5 +155,4 @@ export default {
|
||||
}
|
||||
</script>
|
||||
<style lang="stylus" scoped>
|
||||
.group-wrap{padding:1rem}
|
||||
</style>
|
@@ -1,78 +1,59 @@
|
||||
<template>
|
||||
<a href="javascript:;" :class="{connected:state.connected}" :title="$t('status.messengerChange')" @click="handleConfig">
|
||||
<el-icon size="16"><Promotion /></el-icon> <span>{{$t('status.messenger')}}</span>
|
||||
</a>
|
||||
<el-dialog v-model="state.show" :title="$t('common.setting')" width="300" append-to-body>
|
||||
<div>
|
||||
<el-form :model="state.form" :rules="state.rules" label-width="6rem">
|
||||
<el-form-item :label="$t('status.messengerName')" prop="name" v-if="hasRenameSelf">
|
||||
<el-input v-model="state.form.name" maxlength="32" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('status.messengerGroup')" prop="groupid" v-if="hasGroup">
|
||||
<el-select v-model="state.groupid" @change="handleGroupChange">
|
||||
<el-option v-for="item in state.form.groups" :key="item.Id" :label="item.Name" :value="item.Id"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer t-c">
|
||||
<el-button @click="state.show = false" :loading="state.loading">{{$t('common.cancel')}}</el-button>
|
||||
<el-button type="primary" @click="handleSave" :loading="state.loading">{{$t('common.confirm')}}</el-button>
|
||||
</div>
|
||||
<el-dropdown>
|
||||
<span class="el-dropdown-link" :class="{connected:state.connected}">
|
||||
<el-icon><Avatar /></el-icon>
|
||||
{{state.groupName}}
|
||||
<el-icon><ArrowDown /></el-icon>
|
||||
</span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu v-if="hasGroup">
|
||||
<el-dropdown-item v-for="item in state.groups" @click="handleGroupChange(item.Id)">{{item.Name}}</el-dropdown-item>
|
||||
<el-dropdown-item @click="state.showGroups = true">{{$t('status.group')}}</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</el-dropdown>
|
||||
<Groups v-if="state.showGroups" v-model="state.showGroups"></Groups>
|
||||
</template>
|
||||
<script>
|
||||
import { setSignIn } from '@/apis/signin';
|
||||
import { injectGlobalData } from '@/provide';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { computed, reactive, ref } from 'vue';
|
||||
import {Promotion,CirclePlus} from '@element-plus/icons-vue'
|
||||
import {ArrowDown,Avatar} from '@element-plus/icons-vue'
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import Groups from './Groups.vue';
|
||||
export default {
|
||||
components:{Promotion,CirclePlus},
|
||||
components:{ArrowDown,Avatar,Groups},
|
||||
props:['config'],
|
||||
setup(props) {
|
||||
const { t } = useI18n();
|
||||
const globalData = injectGlobalData();
|
||||
const hasRenameSelf = computed(()=>globalData.value.hasAccess('RenameSelf'));
|
||||
const hasGroup = computed(()=>globalData.value.hasAccess('Group'));
|
||||
const state = reactive({
|
||||
show: false,
|
||||
loading: false,
|
||||
connected: computed(() => globalData.value.signin.Connected),
|
||||
groupid: globalData.value.config.Client.Group.Id,
|
||||
form: {
|
||||
name: globalData.value.config.Client.Name,
|
||||
groups: globalData.value.config.Client.Groups,
|
||||
},
|
||||
rules: {},
|
||||
groupName: globalData.value.config.Client.Group.Name,
|
||||
groups: globalData.value.config.Client.Groups.slice(),
|
||||
showGroups:false
|
||||
});
|
||||
|
||||
const handleConfig = () => {
|
||||
if(!props.config || (!hasGroup.value && !hasRenameSelf.value)){
|
||||
return;
|
||||
}
|
||||
state.form.name = globalData.value.config.Client.Name;
|
||||
state.form.groups = globalData.value.config.Client.Groups;
|
||||
|
||||
state.groupid = globalData.value.config.Client.Group.Id;
|
||||
state.show = true;
|
||||
}
|
||||
|
||||
const handleGroupChange = (value)=>{
|
||||
const index = state.form.groups.map((item,index)=>{
|
||||
|
||||
const index = state.groups.map((item,index)=>{
|
||||
item.$index = index;
|
||||
return item;
|
||||
}).filter(c=>c.Id == value)[0].$index;
|
||||
const temp = state.form.groups[index];
|
||||
state.form.groups[index] = state.form.groups[0];
|
||||
state.form.groups[0] = temp;
|
||||
const temp = state.groups[index];
|
||||
state.groups[index] = state.groups[0];
|
||||
state.groups[0] = temp;
|
||||
handleSave();
|
||||
}
|
||||
const handleSave = () => {
|
||||
state.loading = true;
|
||||
setSignIn(state.form).then(() => {
|
||||
setSignIn({
|
||||
Name:globalData.value.config.Client.Name,
|
||||
Groups:state.groups,
|
||||
}).then(() => {
|
||||
state.loading = false;
|
||||
state.show = false;
|
||||
ElMessage.success(t('common.oper'));
|
||||
@@ -86,21 +67,17 @@ export default {
|
||||
});
|
||||
}
|
||||
return {
|
||||
config:props.config,hasRenameSelf,hasGroup, state, handleConfig, handleSave,handleGroupChange
|
||||
config:props.config,hasGroup, state,handleGroupChange
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="stylus" scoped>
|
||||
a{
|
||||
a{color:#333;}
|
||||
a{margin-left:.6rem;}
|
||||
|
||||
&.connected {
|
||||
.el-dropdown{vertical-align: inherit;margin-right:1rem}
|
||||
.connected {
|
||||
color:green;font-weight:bold;
|
||||
}
|
||||
.el-icon{
|
||||
vertical-align:text-bottom;
|
||||
vertical-align:bottom;
|
||||
}
|
||||
}
|
||||
</style>
|
@@ -23,11 +23,12 @@
|
||||
<Description>1. 优化linux下路由跟踪问题
|
||||
2. 优化linux下获取本机IP问题
|
||||
3. 增加ICS,让win7+、win server2008+支持NAT
|
||||
4. 增加中继卡密
|
||||
4. 增加中继cdkey,使用cdkey解锁公开中继节点的带宽、流量、连接数限制
|
||||
5. 增加内外穿透定时开关功能
|
||||
6. 优化管理页面连接接口的体验
|
||||
7. 优化一些UI体验,去除同步页面,将同步功能放置各个实际的位置
|
||||
8. 其它一些修复优化</Description>
|
||||
7. 优化一些UI体验,去除同步页面,将同步功能放至各个实际的位置
|
||||
8. 优化端口转发,让不同分组间可以使用相同端口
|
||||
9. 其它一些修复优化</Description>
|
||||
<Copyright>snltty</Copyright>
|
||||
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
|
||||
|
@@ -1,10 +1,11 @@
|
||||
v1.6.9
|
||||
2025-03-03 17:44:29
|
||||
2025-03-06 21:15:19
|
||||
1. 优化linux下路由跟踪问题
|
||||
2. 优化linux下获取本机IP问题
|
||||
3. 增加ICS,让win7+、win server2008+支持NAT
|
||||
4. 增加中继卡密
|
||||
4. 增加中继cdkey,使用cdkey解锁公开中继节点的带宽、流量、连接数限制
|
||||
5. 增加内外穿透定时开关功能
|
||||
6. 优化管理页面连接接口的体验
|
||||
7. 优化一些UI体验,去除同步页面,将同步功能放置各个实际的位置
|
||||
8. 其它一些修复优化
|
||||
7. 优化一些UI体验,去除同步页面,将同步功能放至各个实际的位置
|
||||
8. 优化端口转发,让不同分组间可以使用相同端口
|
||||
9. 其它一些修复优化
|
Reference in New Issue
Block a user