This commit is contained in:
snltty
2025-03-06 21:15:19 +08:00
parent 303581a8b3
commit c6eeab74b9
86 changed files with 1091 additions and 557 deletions

View File

@@ -35,7 +35,7 @@ jobs:
release_name: v1.6.9.${{ steps.date.outputs.today }} release_name: v1.6.9.${{ steps.date.outputs.today }}
draft: false draft: false
prerelease: 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 - name: publish projects
run: ./publish.bat run: ./publish.bat
- name: upload-win-x86-oss - name: upload-win-x86-oss

View File

@@ -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] Distributed architecture: Multiple relay nodes for massive scalability
- [x] SOCKS5 proxy: Dynamic port forwarding without specifying ports - [x] SOCKS5 proxy: Dynamic port forwarding without specifying ports
- [x] Easy integration: Use `linker.messenger.entry` to embed into your projects - [x] Easy integration: Use `linker.messenger.entry` to embed into your projects
- [x] CDKEYIt can temporarily lift certain restrictions
## Quick Integration ## Quick Integration
In a .NET 8+ project, install the NuGet package `linker.messenger.entry` In a .NET 8+ project, install the NuGet package `linker.messenger.entry`

View File

@@ -58,6 +58,7 @@
- [x] 分布式,多中继服务器节点,承载海量设备 - [x] 分布式,多中继服务器节点,承载海量设备
- [x] socks5代理端口转发需要指定端口而socks5代理可以代理所有端口 - [x] socks5代理端口转发需要指定端口而socks5代理可以代理所有端口
- [x] 集成linker使用`linker.messenger.entry`入口库,轻松集成到你的项目中 - [x] 集成linker使用`linker.messenger.entry`入口库,轻松集成到你的项目中
- [x] CDKEY可以临时解锁一些限制中继内外穿透什么的
## 轻松集成 ## 轻松集成
在.NET8+项目中nuget 安装 `linker.messenger.entry` 在.NET8+项目中nuget 安装 `linker.messenger.entry`

View File

@@ -44,7 +44,7 @@ sidebar_position: 1
- [x] 分布式,多中继服务器节点,承载海量设备 - [x] 分布式,多中继服务器节点,承载海量设备
- [x] socks5代理端口转发需要指定端口而socks5代理可以代理所有端口 - [x] socks5代理端口转发需要指定端口而socks5代理可以代理所有端口
- [x] 集成linker使用`linker.messenger.entry`入口库,轻松集成到你的项目中 - [x] 集成linker使用`linker.messenger.entry`入口库,轻松集成到你的项目中
- [x] CDKEY可以临时解锁一些限制中继内外穿透什么的
#### 1.4、加入组织 #### 1.4、加入组织
<a href="https://jq.qq.com/?_wv=1027&k=ucoIVfz4" target="_blank">你可以加入QQ群1121552990</a> <a href="https://jq.qq.com/?_wv=1027&k=ucoIVfz4" target="_blank">你可以加入QQ群1121552990</a>

View File

@@ -13,48 +13,87 @@ namespace linker.libs
action(); action();
}); });
} }
public static void SetInterval(Func<bool> action, int delayMs) public static void SetInterval(Func<bool> action, int delayMs)
{ {
Task.Run(async () => Task.Run(async () =>
{ {
while (true) while (action())
{ {
if (action() == false)
{
break;
}
await Task.Delay(delayMs).ConfigureAwait(false); 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) public static void SetInterval(Func<bool> action, Func<int> delay)
{ {
Task.Run(async () => Task.Run(async () =>
{ {
while (true) while (action())
{ {
if (action() == false)
{
break;
}
await Task.Delay(delay()).ConfigureAwait(false); 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) public static void SetInterval(Func<Task<bool>> action, Func<int> delay)
{ {
Task.Run(async () => Task.Run(async () =>
{ {
while (true) while (await action())
{ {
if (await action() == false)
{
break;
}
await Task.Delay(delay()).ConfigureAwait(false); 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) public static void Async(Action action)
{ {
@@ -68,5 +107,6 @@ namespace linker.libs
{ {
Task.Factory.StartNew(action,TaskCreationOptions.LongRunning); Task.Factory.StartNew(action,TaskCreationOptions.LongRunning);
} }
} }
} }

View File

@@ -53,7 +53,7 @@ namespace linker.messenger.decenter
private void SyncTask() private void SyncTask()
{ {
TimerHelper.SetInterval(async () => TimerHelper.SetIntervalLong(async () =>
{ {
try try
{ {
@@ -100,7 +100,7 @@ namespace linker.messenger.decenter
} }
} }
return true; return true;
}, () => 300); }, 300);
} }
class DecenterSyncTaskInfo class DecenterSyncTaskInfo

View File

@@ -4,8 +4,8 @@ namespace linker.messenger.flow
{ {
public sealed class ExternalFlow : IFlow public sealed class ExternalFlow : IFlow
{ {
public ulong ReceiveBytes { get; private set; } public long ReceiveBytes { get; private set; }
public ulong SendtBytes { get; private set; } public long SendtBytes { get; private set; }
public string FlowName => "External"; public string FlowName => "External";
public VersionManager Version { get; } = new VersionManager(); public VersionManager Version { get; } = new VersionManager();
@@ -16,11 +16,11 @@ namespace linker.messenger.flow
public string GetItems() => string.Empty; public string GetItems() => string.Empty;
public void SetItems(string json) { } 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 Clear() { ReceiveBytes = 0; SendtBytes = 0;}
public void AddReceive(ulong bytes) { ReceiveBytes += bytes; Version.Add(); } public void AddReceive(long bytes) { ReceiveBytes += bytes; Version.Add(); }
public void AddSendt(ulong bytes) { SendtBytes += bytes; Version.Add(); } public void AddSendt(long bytes) { SendtBytes += bytes; Version.Add(); }
} }
@@ -35,8 +35,8 @@ namespace linker.messenger.flow
this.externalFlow = externalFlow; this.externalFlow = externalFlow;
} }
public override void AddReceive(ulong bytes) { externalFlow.AddReceive(bytes); } public override void AddReceive(long bytes) { externalFlow.AddReceive(bytes); }
public override void AddSendt(ulong bytes) { externalFlow.AddSendt(bytes); } public override void AddSendt(long bytes) { externalFlow.AddSendt(bytes); }
} }

View File

@@ -18,11 +18,11 @@ namespace linker.messenger.flow
/// <summary> /// <summary>
/// 在线 | 总数 /// 在线 | 总数
/// </summary> /// </summary>
public ulong ReceiveBytes { get; private set; } public long ReceiveBytes { get; private set; }
/// <summary> /// <summary>
/// 服务器数 /// 服务器数
/// </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()); 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 string GetItems() => string.Empty;
public void SetItems(string json) { } public void SetItems(string json) { }
public void SetBytes(ulong receiveBytes, ulong sendtBytes) { } public void SetBytes(long receiveBytes, long sendtBytes) { }
public void Clear() { } public void Clear() { }
@@ -86,7 +86,7 @@ namespace linker.messenger.flow
private void OnlineTask() private void OnlineTask()
{ {
TimerHelper.SetInterval(() => TimerHelper.SetIntervalLong(() =>
{ {
try try
{ {
@@ -110,11 +110,11 @@ namespace linker.messenger.flow
servers.TryRemove(key, out _); servers.TryRemove(key, out _);
} }
ulong online = (ulong)servers.Sum(c => c.Value.Online) << 32; long online = servers.Sum(c => c.Value.Online) << 32;
ulong total = (ulong)servers.Sum(c => c.Value.Total); long total = servers.Sum(c => c.Value.Total);
ReceiveBytes = online | total; ReceiveBytes = online | total;
SendtBytes = (ulong)servers.Count; SendtBytes = servers.Count;
Version.Add(); Version.Add();
} }
private void Report() private void Report()

View File

@@ -5,21 +5,21 @@ namespace linker.messenger.flow
{ {
public interface IFlow public interface IFlow
{ {
public ulong ReceiveBytes { get; } public long ReceiveBytes { get; }
public ulong SendtBytes { get; } public long SendtBytes { get; }
public string FlowName { get; } public string FlowName { get; }
public VersionManager Version { get; } public VersionManager Version { get; }
public string GetItems(); public string GetItems();
public void SetItems(string json); public void SetItems(string json);
public void SetBytes(ulong receiveBytes,ulong sendtBytes); public void SetBytes(long receiveBytes,long sendtBytes);
public void Clear(); public void Clear();
} }
public partial class FlowItemInfo public partial class FlowItemInfo
{ {
public ulong ReceiveBytes { get; set; } public long ReceiveBytes { get; set; }
public ulong SendtBytes { get; set; } public long SendtBytes { get; set; }
[JsonIgnore] [JsonIgnore]
public string FlowName { get; set; } public string FlowName { get; set; }

View File

@@ -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
{
}
}

View File

@@ -12,11 +12,11 @@ namespace linker.messenger.flow
this.messengerFlow = messengerFlow; this.messengerFlow = messengerFlow;
} }
public override void AddReceive(ushort id, ulong bytes) public override void AddReceive(ushort id, long bytes)
{ {
messengerFlow.AddReceive(id, 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); messengerFlow.AddSendt(id, bytes);
} }
@@ -29,11 +29,11 @@ namespace linker.messenger.flow
this.messengerFlow = messengerFlow; this.messengerFlow = messengerFlow;
} }
public override void AddReceive(ushort id, ulong bytes) public override void AddReceive(ushort id, long bytes)
{ {
messengerFlow.AddReceive(id, 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); messengerFlow.AddSendt(id, bytes);
} }
@@ -43,8 +43,8 @@ namespace linker.messenger.flow
public sealed class MessengerFlow : IFlow public sealed class MessengerFlow : IFlow
{ {
public ulong ReceiveBytes { get; private set; } public long ReceiveBytes { get; private set; }
public ulong SendtBytes { get; private set; } public long SendtBytes { get; private set; }
public string FlowName => "Messenger"; public string FlowName => "Messenger";
public VersionManager Version { get; } = new VersionManager(); public VersionManager Version { get; } = new VersionManager();
@@ -56,10 +56,10 @@ namespace linker.messenger.flow
public string GetItems() => flows.ToJson(); public string GetItems() => flows.ToJson();
public void SetItems(string json) { flows = json.DeJson<Dictionary<ushort, FlowItemInfo>>(); } 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 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) if (flows.TryGetValue(id, out FlowItemInfo messengerFlowItemInfo) == false)
{ {
@@ -70,7 +70,7 @@ namespace linker.messenger.flow
messengerFlowItemInfo.ReceiveBytes += bytes; messengerFlowItemInfo.ReceiveBytes += bytes;
Version.Add(); Version.Add();
} }
public void AddSendt(ushort id, ulong bytes) public void AddSendt(ushort id, long bytes)
{ {
if (flows.TryGetValue(id, out FlowItemInfo messengerFlowItemInfo) == false) if (flows.TryGetValue(id, out FlowItemInfo messengerFlowItemInfo) == false)
{ {

View File

@@ -7,8 +7,8 @@ namespace linker.messenger.flow
{ {
public sealed class RelayReportFlow : IFlow public sealed class RelayReportFlow : IFlow
{ {
public ulong ReceiveBytes { get; private set; } public long ReceiveBytes { get; private set; }
public ulong SendtBytes { get; private set; } public long SendtBytes { get; private set; }
public string FlowName => "RelayReport"; public string FlowName => "RelayReport";
public VersionManager Version { get; } = new VersionManager(); public VersionManager Version { get; } = new VersionManager();
public RelayReportFlow() public RelayReportFlow()
@@ -16,11 +16,11 @@ namespace linker.messenger.flow
} }
public string GetItems() => string.Empty; public string GetItems() => string.Empty;
public void SetItems(string json) { } 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 Clear() { ReceiveBytes = 0; SendtBytes = 0; }
public void AddReceive(ulong bytes) { ReceiveBytes += bytes; Version.Add(); } public void AddReceive(long bytes) { ReceiveBytes += bytes; Version.Add(); }
public void AddSendt(ulong bytes) { SendtBytes += bytes; Version.Add(); } public void AddSendt(long bytes) { SendtBytes += bytes; Version.Add(); }
} }
@@ -32,8 +32,8 @@ namespace linker.messenger.flow
this.relayReportFlow = relayReportFlow; this.relayReportFlow = relayReportFlow;
} }
public override void AddReceive(ulong bytes) { relayReportFlow.AddReceive(bytes); } public override void AddReceive(long bytes) { relayReportFlow.AddReceive(bytes); }
public override void AddSendt(ulong bytes) { relayReportFlow.AddSendt(bytes); } public override void AddSendt(long bytes) { relayReportFlow.AddSendt(bytes); }
} }
@@ -47,19 +47,19 @@ namespace linker.messenger.flow
this.relayFlow = relayFlow; 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); 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); 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); relayFlow.AddReceive(key, bytes);
} }
public override void AddSendt(string key, ulong bytes) public override void AddSendt(string key, long bytes)
{ {
relayFlow.AddSendt(key, bytes); relayFlow.AddSendt(key, bytes);
} }
@@ -68,8 +68,8 @@ namespace linker.messenger.flow
public sealed class RelayFlow : IFlow public sealed class RelayFlow : IFlow
{ {
public ulong ReceiveBytes { get; private set; } public long ReceiveBytes { get; private set; }
public ulong SendtBytes { get; private set; } public long SendtBytes { get; private set; }
public string FlowName => "Relay"; public string FlowName => "Relay";
public VersionManager Version { get; } = new VersionManager(); public VersionManager Version { get; } = new VersionManager();
@@ -79,7 +79,7 @@ namespace linker.messenger.flow
public RelayFlow() public RelayFlow()
{ {
TimerHelper.SetInterval(() => TimerHelper.SetIntervalLong(() =>
{ {
if (lastTicksManager.DiffLessEqual(5000)) if (lastTicksManager.DiffLessEqual(5000))
{ {
@@ -103,10 +103,10 @@ namespace linker.messenger.flow
public string GetItems() => flows.ToJson(); public string GetItems() => flows.ToJson();
public void SetItems(string json) { flows = json.DeJson<Dictionary<string, RelayFlowItemInfo>>(); } 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 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) if (flows.TryGetValue(key, out RelayFlowItemInfo messengerFlowItemInfo) == false)
{ {
@@ -117,7 +117,7 @@ namespace linker.messenger.flow
messengerFlowItemInfo.ReceiveBytes += bytes; messengerFlowItemInfo.ReceiveBytes += bytes;
Version.Add(); 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) if (flows.TryGetValue(key, out RelayFlowItemInfo messengerFlowItemInfo) == false)
{ {
@@ -129,7 +129,7 @@ namespace linker.messenger.flow
Version.Add(); Version.Add();
} }
public void AddReceive(string key, ulong bytes) public void AddReceive(string key, long bytes)
{ {
if (flows.TryGetValue(key, out RelayFlowItemInfo messengerFlowItemInfo)) 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)) if (flows.TryGetValue(key, out RelayFlowItemInfo messengerFlowItemInfo))
{ {
@@ -201,17 +201,17 @@ namespace linker.messenger.flow
public sealed partial class RelayFlowItemInfo : FlowItemInfo public sealed partial class RelayFlowItemInfo : FlowItemInfo
{ {
public ulong DiffReceiveBytes { get; set; } public long DiffReceiveBytes { get; set; }
public ulong DiffSendtBytes { get; set; } public long DiffSendtBytes { get; set; }
public string FromName { get; set; } public string FromName { get; set; }
public string ToName { get; set; } public string ToName { get; set; }
public string GroupId { get; set; } public string GroupId { get; set; }
[JsonIgnore] [JsonIgnore]
public ulong OldReceiveBytes { get; set; } public long OldReceiveBytes { get; set; }
[JsonIgnore] [JsonIgnore]
public ulong OldSendtBytes { get; set; } public long OldSendtBytes { get; set; }
} }
public sealed partial class RelayFlowRequestInfo public sealed partial class RelayFlowRequestInfo

View File

@@ -12,11 +12,11 @@ namespace linker.messenger.flow
{ {
this.sForwardFlow = sForwardFlow; 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); 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); sForwardFlow.AddSendt(key, groupid, bytes);
} }
@@ -24,8 +24,8 @@ namespace linker.messenger.flow
public sealed class SForwardFlow : IFlow public sealed class SForwardFlow : IFlow
{ {
public ulong ReceiveBytes { get; private set; } public long ReceiveBytes { get; private set; }
public ulong SendtBytes { get; private set; } public long SendtBytes { get; private set; }
public string FlowName => "SForward"; public string FlowName => "SForward";
public VersionManager Version { get; } = new VersionManager(); public VersionManager Version { get; } = new VersionManager();
@@ -35,7 +35,7 @@ namespace linker.messenger.flow
public SForwardFlow() public SForwardFlow()
{ {
TimerHelper.SetInterval(() => TimerHelper.SetIntervalLong(() =>
{ {
if (lastTicksManager.DiffLessEqual(5000)) if (lastTicksManager.DiffLessEqual(5000))
{ {
@@ -54,7 +54,7 @@ namespace linker.messenger.flow
public string GetItems() => flows.ToJson(); public string GetItems() => flows.ToJson();
public void SetItems(string json) { flows = json.DeJson<Dictionary<string, SForwardFlowItemInfo>>(); } 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 Clear() { ReceiveBytes = 0; SendtBytes = 0;flows.Clear(); }
public void Update() public void Update()
@@ -62,7 +62,7 @@ namespace linker.messenger.flow
lastTicksManager.Update(); 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) if (flows.TryGetValue(key, out SForwardFlowItemInfo messengerFlowItemInfo) == false)
{ {
@@ -73,7 +73,7 @@ namespace linker.messenger.flow
messengerFlowItemInfo.ReceiveBytes += bytes; messengerFlowItemInfo.ReceiveBytes += bytes;
Version.Add(); 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) if (flows.TryGetValue(key, out SForwardFlowItemInfo messengerFlowItemInfo) == false)
{ {
@@ -134,16 +134,16 @@ namespace linker.messenger.flow
public sealed partial class SForwardFlowItemInfo : FlowItemInfo public sealed partial class SForwardFlowItemInfo : FlowItemInfo
{ {
public ulong DiffReceiveBytes { get; set; } public long DiffReceiveBytes { get; set; }
public ulong DiffSendtBytes { get; set; } public long DiffSendtBytes { get; set; }
public string Key { get; set; } public string Key { get; set; }
public string GroupId { get; set; } public string GroupId { get; set; }
[JsonIgnore] [JsonIgnore]
public ulong OldReceiveBytes { get; set; } public long OldReceiveBytes { get; set; }
[JsonIgnore] [JsonIgnore]
public ulong OldSendtBytes { get; set; } public long OldSendtBytes { get; set; }
} }
public sealed partial class SForwardFlowRequestInfo public sealed partial class SForwardFlowRequestInfo

View File

@@ -38,7 +38,7 @@ namespace linker.messenger.flow.messenger
Dictionary<string, FlowItemInfo> dic = flowTransfer.GetFlows(); Dictionary<string, FlowItemInfo> dic = flowTransfer.GetFlows();
signCaching.GetOnline(out int all, out int online); 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 FlowInfo serverFlowInfo = new FlowInfo
{ {

View File

@@ -7,7 +7,7 @@ namespace linker.messenger.forward
public sealed partial class ForwardInfo public sealed partial class ForwardInfo
{ {
public ForwardInfo() { } public ForwardInfo() { }
public uint Id { get; set; } public long Id { get; set; }
/// <summary> /// <summary>
/// 名称 /// 名称
/// </summary> /// </summary>
@@ -60,7 +60,7 @@ namespace linker.messenger.forward
public sealed partial class ForwardRemoveForwardInfo public sealed partial class ForwardRemoveForwardInfo
{ {
public string MachineId { get; set; } public string MachineId { get; set; }
public uint Id { get; set; } public long Id { get; set; }
} }
public sealed partial class ForwardCountInfo public sealed partial class ForwardCountInfo
{ {

View File

@@ -18,9 +18,6 @@ namespace linker.messenger.forward
private readonly IMessengerSender messengerSender; private readonly IMessengerSender messengerSender;
private readonly ISignInClientStore signInClientStore; private readonly ISignInClientStore signInClientStore;
private readonly ISerializer serializer; private readonly ISerializer serializer;
private readonly NumberSpaceUInt32 ns = new NumberSpaceUInt32();
public ForwardTransfer(IForwardClientStore forwardClientStore, ForwardProxy forwardProxy, SignInClientState signInClientState, IMessengerSender messengerSender, ISignInClientStore signInClientStore, ISerializer serializer) public ForwardTransfer(IForwardClientStore forwardClientStore, ForwardProxy forwardProxy, SignInClientState signInClientState, IMessengerSender messengerSender, ISignInClientStore signInClientStore, ISerializer serializer)
{ {
this.forwardClientStore = forwardClientStore; this.forwardClientStore = forwardClientStore;
@@ -54,9 +51,6 @@ namespace linker.messenger.forward
{ {
lock (this) 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)) foreach (var item in forwardClientStore.Get(signInClientStore.Group.Id))
{ {
if (item.Started) if (item.Started)
@@ -149,7 +143,7 @@ namespace linker.messenger.forward
public bool Add(ForwardInfo forwardInfo) public bool Add(ForwardInfo forwardInfo)
{ {
//同名或者同端口但是ID不一样 //同名或者同端口但是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 (old != null && old.Id != forwardInfo.Id) return false;
if (forwardInfo.Id != 0) if (forwardInfo.Id != 0)
@@ -169,10 +163,10 @@ namespace linker.messenger.forward
old.Started = forwardInfo.Started; old.Started = forwardInfo.Started;
old.BufferSize = forwardInfo.BufferSize; old.BufferSize = forwardInfo.BufferSize;
old.GroupId = signInClientStore.Group.Id; old.GroupId = signInClientStore.Group.Id;
forwardClientStore.Update(forwardInfo);
} }
else else
{ {
forwardInfo.Id = ns.Increment();
forwardInfo.GroupId = signInClientStore.Group.Id; forwardInfo.GroupId = signInClientStore.Group.Id;
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
@@ -186,7 +180,7 @@ namespace linker.messenger.forward
return true; return true;
} }
public bool Remove(uint id) public bool Remove(long id)
{ {
//同名或者同端口但是ID不一样 //同名或者同端口但是ID不一样
ForwardInfo old = forwardClientStore.Get(id); ForwardInfo old = forwardClientStore.Get(id);

View File

@@ -18,7 +18,7 @@
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id"></param>
/// <returns></returns> /// <returns></returns>
public ForwardInfo Get(uint id); public ForwardInfo Get(long id);
/// <summary> /// <summary>
/// 根据分组获取 /// 根据分组获取
/// </summary> /// </summary>
@@ -42,7 +42,7 @@
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id"></param>
/// <returns></returns> /// <returns></returns>
public bool Remove(uint id); public bool Remove(long id);
/// <summary> /// <summary>
/// 提交更新 /// 提交更新

View File

@@ -270,7 +270,7 @@ namespace linker.messenger.forward.proxy
/// </summary> /// </summary>
private void TaskUdp() private void TaskUdp()
{ {
TimerHelper.SetInterval(() => TimerHelper.SetIntervalLong(() =>
{ {
if(udpConnections.Count > 0) if(udpConnections.Count > 0)
{ {

View File

@@ -69,7 +69,7 @@ namespace linker.messenger.logger
{ {
} }
}; };
TimerHelper.SetInterval(() => TimerHelper.SetIntervalLong(() =>
{ {
string[] files = Directory.GetFiles("logs").OrderBy(c => c).ToArray(); string[] files = Directory.GetFiles("logs").OrderBy(c => c).ToArray();
for (int i = 0; i < files.Length - 180; i++) for (int i = 0; i < files.Length - 180; i++)

View File

@@ -72,7 +72,7 @@ namespace linker.messenger.relay
[Access(AccessValue.RelayCdkey)] [Access(AccessValue.RelayCdkey)]
public async Task<bool> AddCdkey(ApiControllerParamsInfo param) 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 var resp = await messengerSender.SendReply(new MessageRequestWrap
{ {
Connection = signInClientState.Connection, Connection = signInClientState.Connection,
@@ -96,7 +96,7 @@ namespace linker.messenger.relay
MessengerId = (ushort)RelayMessengerIds.DelCdkey, MessengerId = (ushort)RelayMessengerIds.DelCdkey,
Payload = serializer.Serialize(new RelayServerCdkeyDelInfo Payload = serializer.Serialize(new RelayServerCdkeyDelInfo
{ {
Id = param.Content, CdkeyId = long.Parse(param.Content),
SecretKey = relayClientStore.Server.SecretKey SecretKey = relayClientStore.Server.SecretKey
}) })
}); });

View File

@@ -66,14 +66,14 @@ namespace linker.messenger.relay
} }
private void TestTask() private void TestTask()
{ {
TimerHelper.SetInterval(async () => TimerHelper.SetIntervalLong(async () =>
{ {
if (lastTicksManager.DiffLessEqual(3000)) if (lastTicksManager.DiffLessEqual(3000))
{ {
await TaskRelay(); await TaskRelay();
} }
return true; return true;
}, () => 3000); }, 3000);
} }
} }

View File

@@ -5,6 +5,7 @@ using linker.messenger.relay.client;
using linker.messenger.relay.server; using linker.messenger.relay.server;
using linker.messenger.signin; using linker.messenger.signin;
using linker.messenger.relay.server.validator; using linker.messenger.relay.server.validator;
using linker.libs.extends;
namespace linker.messenger.relay.messenger namespace linker.messenger.relay.messenger
{ {
@@ -81,7 +82,7 @@ namespace linker.messenger.relay.messenger
TransportName = "test", TransportName = "test",
}, cache, null); }, cache, null);
var nodes = relayServerTransfer.GetNodes(string.IsNullOrWhiteSpace(result), info.UserId); var nodes = relayServerTransfer.GetNodes(string.IsNullOrWhiteSpace(result));
connection.Write(serializer.Serialize(nodes)); connection.Write(serializer.Serialize(nodes));
} }
@@ -110,11 +111,11 @@ namespace linker.messenger.relay.messenger
bool validated = string.IsNullOrWhiteSpace(error); bool validated = string.IsNullOrWhiteSpace(error);
result.Nodes = relayServerTransfer.GetNodes(validated); 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) 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)); connection.Write(serializer.Serialize(result));
@@ -230,7 +231,7 @@ namespace linker.messenger.relay.messenger
return; return;
} }
await relayServerCdkeyStore.Del(info.Id); await relayServerCdkeyStore.Del(info.CdkeyId);
connection.Write(Helper.TrueArray); connection.Write(Helper.TrueArray);
} }
@@ -266,9 +267,17 @@ namespace linker.messenger.relay.messenger
/// <param name="connection"></param> /// <param name="connection"></param>
/// <returns></returns> /// <returns></returns>
[MessengerId((ushort)RelayMessengerIds.NodeGetCache)] [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> /// <summary>
/// 获取缓存 /// 获取缓存
@@ -276,9 +285,14 @@ namespace linker.messenger.relay.messenger
/// <param name="connection"></param> /// <param name="connection"></param>
/// <returns></returns> /// <returns></returns>
[MessengerId((ushort)RelayMessengerIds.NodeReport)] [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> /// <summary>
/// 消耗流量报告 /// 消耗流量报告
@@ -288,12 +302,14 @@ namespace linker.messenger.relay.messenger
[MessengerId((ushort)RelayMessengerIds.TrafficReport)] [MessengerId((ushort)RelayMessengerIds.TrafficReport)]
public async Task TrafficReport(IConnection connection) public async Task TrafficReport(IConnection connection)
{ {
RelayTrafficReportInfo info = serializer.Deserialize<RelayTrafficReportInfo>(connection.ReceiveRequestWrap.Payload.Span); RelayTrafficUpdateInfo info = serializer.Deserialize<RelayTrafficUpdateInfo>(connection.ReceiveRequestWrap.Payload.Span);
if (relayServerStore.SecretKey != info.SecretKey ) if (relayServerStore.SecretKey != info.SecretKey)
{ {
connection.Write(serializer.Serialize(new Dictionary<string,ulong>())); connection.Write(serializer.Serialize(new Dictionary<string, long>()));
return; return;
} }
Dictionary<long, long> result = await relayServerTransfer.AddTraffic(info);
connection.Write(serializer.Serialize(result));
} }
} }
} }

View File

@@ -2,18 +2,41 @@
{ {
public interface IRelayServerCdkeyStore public interface IRelayServerCdkeyStore
{ {
public Task<bool> Add(RelayServerCdkeyInfo info); public Task<bool> Add(RelayServerCdkeyStoreInfo info);
public Task<bool> Del(string id); public Task<bool> Del(long id);
/// <summary> /// <summary>
/// 获取有效的CDKEY /// 获取有效的CDKEY
/// </summary> /// </summary>
/// <param name="userid"></param> /// <param name="userid"></param>
/// <returns></returns> /// <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 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 sealed partial class RelayServerCdkeyPageRequestInfo
{ {
public int Page { get; set; } public int Page { get; set; }
@@ -29,24 +52,24 @@
public int Page { get; set; } public int Page { get; set; }
public int Size { get; set; } public int Size { get; set; }
public int Count { 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 sealed partial class RelayServerCdkeyAddInfo
{ {
public string SecretKey { get; set; } public string SecretKey { get; set; }
public RelayServerCdkeyInfo Data { get; set; } public RelayServerCdkeyStoreInfo Data { get; set; }
} }
public sealed partial class RelayServerCdkeyDelInfo public sealed partial class RelayServerCdkeyDelInfo
{ {
public string SecretKey { get; set; } public string SecretKey { get; set; }
public string Id { get; set; } public long CdkeyId { get; set; }
} }
/// <summary> /// <summary>
/// 中继CDKEY /// 中继CDKEY存储
/// </summary> /// </summary>
public sealed partial class RelayServerCdkeyInfo public sealed partial class RelayServerCdkeyStoreInfo : RelayServerCdkeyInfo
{ {
public string Id { get; set; } public string Id { get; set; }
@@ -72,21 +95,17 @@
/// </summary> /// </summary>
public DateTime EndTime { get; set; } public DateTime EndTime { get; set; }
/// <summary> /// <summary>
/// 最后使用时间
/// </summary>
public DateTime UseTime { get; set; }
/// <summary>
/// 允许节点 /// 允许节点
/// </summary> /// </summary>
public List<string> Nodes { get; set; } public List<string> Nodes { get; set; }
/// <summary> /// <summary>
/// 带宽Mbps
/// </summary>
public double Bandwidth { get; set; }
/// <summary>
/// 流量 /// 流量
/// </summary> /// </summary>
public ulong MaxBytes { get; set; } public long MaxBytes { get; set; }
/// <summary>
/// 剩余流量
/// </summary>
public ulong LastBytes { get; set; }
/// <summary> /// <summary>
/// 原价 /// 原价

View File

@@ -33,7 +33,7 @@ namespace linker.messenger.relay.server
/// 设置剩余流量 /// 设置剩余流量
/// </summary> /// </summary>
/// <param name="value"></param> /// <param name="value"></param>
public void SetMaxGbTotalLastBytes(ulong value); public void SetMaxGbTotalLastBytes(long value);
/// <summary> /// <summary>
/// 提交保存 /// 提交保存
/// </summary> /// </summary>
@@ -68,7 +68,7 @@ namespace linker.messenger.relay.server
public double MaxBandwidth { get; set; } public double MaxBandwidth { get; set; }
public double MaxBandwidthTotal { get; set; } public double MaxBandwidthTotal { get; set; }
public double MaxGbTotal { get; set; } public double MaxGbTotal { get; set; }
public ulong MaxGbTotalLastBytes { get; set; } public long MaxGbTotalLastBytes { get; set; }
public int MaxGbTotalMonth { get; set; } public int MaxGbTotalMonth { get; set; }
public bool Public { get; set; } public bool Public { get; set; }
@@ -79,8 +79,6 @@ namespace linker.messenger.relay.server
#else #else
public string MasterSecretKey { get; set; } = string.Empty; public string MasterSecretKey { get; set; } = string.Empty;
#endif #endif
public List<string> UserIds { get; set; } = new List<string>();
} }
public sealed partial class RelayServerNodeReportInfo public sealed partial class RelayServerNodeReportInfo
@@ -92,7 +90,7 @@ namespace linker.messenger.relay.server
public double MaxBandwidth { get; set; } public double MaxBandwidth { get; set; }
public double MaxBandwidthTotal { get; set; } public double MaxBandwidthTotal { get; set; }
public double MaxGbTotal { get; set; } public double MaxGbTotal { get; set; }
public ulong MaxGbTotalLastBytes { get; set; } public long MaxGbTotalLastBytes { get; set; }
public double ConnectionRatio { get; set; } public double ConnectionRatio { get; set; }
public double BandwidthRatio { get; set; } public double BandwidthRatio { get; set; }
@@ -104,8 +102,6 @@ namespace linker.messenger.relay.server
public IPEndPoint EndPoint { get; set; } public IPEndPoint EndPoint { get; set; }
public long LastTicks { get; set; } public long LastTicks { get; set; }
public List<string> UserIds { get; set; } = new List<string>();
} }

View File

@@ -13,14 +13,17 @@ namespace linker.messenger.relay.server
private ulong relayFlowingId = 0; private ulong relayFlowingId = 0;
private readonly ConcurrentDictionary<string, RelayServerNodeReportInfo> reports = new ConcurrentDictionary<string, RelayServerNodeReportInfo>(); 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 IRelayServerCaching relayCaching;
private readonly ISerializer serializer; 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.relayCaching = relayCaching;
this.serializer = serializer; this.serializer = serializer;
this.relayServerCdkeyStore = relayServerCdkeyStore;
TrafficTask();
} }
@@ -82,10 +85,10 @@ namespace linker.messenger.relay.server
/// </summary> /// </summary>
/// <param name="validated">是否已认证</param> /// <param name="validated">是否已认证</param>
/// <returns></returns> /// <returns></returns>
public List<RelayServerNodeReportInfo> GetNodes(bool validated, string userid) public List<RelayServerNodeReportInfo> GetNodes(bool validated)
{ {
var result = reports.Values 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 => Environment.TickCount64 - c.LastTicks < 15000)
.Where(c => c.ConnectionRatio < 100 && (c.MaxGbTotal == 0 || (c.MaxGbTotal > 0 && c.MaxGbTotalLastBytes > 0))) .Where(c => c.ConnectionRatio < 100 && (c.MaxGbTotal == 0 || (c.MaxGbTotal > 0 && c.MaxGbTotalLastBytes > 0)))
.OrderByDescending(c => c.LastTicks); .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.MaxBandwidth == 0 ? double.MaxValue : x.MaxBandwidth)
.ThenByDescending(x => x.MaxBandwidthTotal == 0 ? double.MaxValue : x.MaxBandwidthTotal) .ThenByDescending(x => x.MaxBandwidthTotal == 0 ? double.MaxValue : x.MaxBandwidthTotal)
.ThenByDescending(x => x.MaxGbTotal == 0 ? double.MaxValue : x.MaxGbTotal) .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(); .ToList();
} }
@@ -109,7 +112,29 @@ namespace linker.messenger.relay.server
{ {
return reports.TryGetValue(nodeId, out RelayServerNodeReportInfo relayNodeReportInfo) && relayNodeReportInfo.Public == false; 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);
}
} }
} }

View File

@@ -5,7 +5,6 @@ using System.Buffers;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Runtime.CompilerServices;
namespace linker.messenger.relay.server namespace linker.messenger.relay.server
{ {
@@ -18,11 +17,11 @@ namespace linker.messenger.relay.server
private IConnection localConnection; private IConnection localConnection;
private IConnection remoteConnection; private IConnection remoteConnection;
private ulong bytes = 0; private long bytes = 0;
private ulong lastBytes = 0; private long lastBytes = 0;
RelaySpeedLimit limitTotal = new RelaySpeedLimit(); private RelaySpeedLimit limitTotal = new RelaySpeedLimit();
private readonly ConcurrentDictionary<ulong, RelayTrafficCacheInfo> trafficDict = new ConcurrentDictionary<ulong, RelayTrafficCacheInfo>(); 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 ISerializer serializer;
private readonly IRelayServerNodeStore relayServerNodeStore; private readonly IRelayServerNodeStore relayServerNodeStore;
@@ -50,7 +49,7 @@ namespace linker.messenger.relay.server
{ {
try 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 MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
{ {
@@ -133,6 +132,7 @@ namespace linker.messenger.relay.server
public bool NeedLimit(RelayTrafficCacheInfo relayCache) public bool NeedLimit(RelayTrafficCacheInfo relayCache)
{ {
if (relayCache.Cache.Validated) return false; if (relayCache.Cache.Validated) return false;
//if (relayCache.CurrentCdkey != null) return false;
return limitTotal.NeedLimit(); return limitTotal.NeedLimit();
} }
/// <summary> /// <summary>
@@ -164,7 +164,7 @@ namespace linker.messenger.relay.server
trafficDict.TryRemove(relayCache.Cache.FlowId, out _); trafficDict.TryRemove(relayCache.Cache.FlowId, out _);
foreach (var item in relayCache.Cache.Cdkey) foreach (var item in relayCache.Cache.Cdkey)
{ {
cdkeyLastBytes.TryRemove(item.Id, out _); cdkeyLastBytes.TryRemove(item.CdkeyId, out _);
} }
} }
/// <summary> /// <summary>
@@ -172,7 +172,7 @@ namespace linker.messenger.relay.server
/// </summary> /// </summary>
/// <param name="length"></param> /// <param name="length"></param>
/// <returns></returns> /// <returns></returns>
public bool AddBytes(RelayTrafficCacheInfo cache, ulong length) public bool AddBytes(RelayTrafficCacheInfo cache, long length)
{ {
Interlocked.Add(ref bytes, length); Interlocked.Add(ref bytes, length);
@@ -194,20 +194,13 @@ namespace linker.messenger.relay.server
/// <param name="relayCache"></param> /// <param name="relayCache"></param>
private void SetLimit(RelayTrafficCacheInfo relayCache) private void SetLimit(RelayTrafficCacheInfo relayCache)
{ {
//验证过的,无限制 //无限制
if (relayCache.Cache.Validated) if (relayCache.Cache.Validated || relayServerNodeStore.Node.MaxBandwidth == 0)
{ {
relayCache.Limit.SetLimit(0); relayCache.Limit.SetLimit(0);
return; 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(); RelayServerCdkeyInfo currentCdkey = relayCache.Cache.Cdkey.Where(c => c.LastBytes > 0).OrderByDescending(c => c.Bandwidth).FirstOrDefault();
//有cdkey且带宽大于节点带宽就用cdkey的带宽 //有cdkey且带宽大于节点带宽就用cdkey的带宽
if (currentCdkey != null && (currentCdkey.Bandwidth == 0 || currentCdkey.Bandwidth > relayServerNodeStore.Node.MaxBandwidth)) 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)); 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) foreach (var cache in trafficDict.Values.Where(c => c.CurrentCdkey == null))
relayServerNodeStore.SetMaxGbTotalLastBytes(relayServerNodeStore.Node.MaxGbTotalLastBytes - length); {
else relayServerNodeStore.SetMaxGbTotalLastBytes(0); 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) if (relayServerNodeStore.Node.MaxGbTotalMonth != DateTime.Now.Month)
{ {
relayServerNodeStore.SetMaxGbTotalMonth(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(); relayServerNodeStore.Confirm();
} }
private void TrafficTask() private void DownloadBytes()
{ {
TimerHelper.SetInterval(async () => TimerHelper.Async(async () =>
{ {
//需要报告Cdkey的流量 List<long> ids = trafficDict.Values.SelectMany(c => c.Cache.Cdkey).Select(c => c.CdkeyId).Distinct().ToList();
_ = messengerSender.SendReply(new MessageRequestWrap 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, Connection = relayServerNodeStore.Node.Id == RelayServerNodeInfo.MASTER_NODE_ID ? localConnection : remoteConnection,
MessengerId = (ushort)RelayMessengerIds.TrafficReport, MessengerId = (ushort)RelayMessengerIds.TrafficReport,
Payload = serializer.Serialize(new RelayTrafficReportInfo Payload = serializer.Serialize(new RelayTrafficUpdateInfo
{ {
Id2Bytes = trafficDict.Values 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)),
.Where(c => c.CurrentCdkey != null && c.Sendt > 0) Ids = [],
.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(),
SecretKey = relayServerNodeStore.Node.Id == RelayServerNodeInfo.MASTER_NODE_ID SecretKey = relayServerNodeStore.Node.Id == RelayServerNodeInfo.MASTER_NODE_ID
? relayServerMasterStore.Master.SecretKey ? relayServerMasterStore.Master.SecretKey
: relayServerNodeStore.Node.MasterSecretKey : relayServerNodeStore.Node.MasterSecretKey
}), }),
Timeout = 4000, 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);
}
}); });
foreach (var cache in trafficDict.Values.Where(c => c.CurrentCdkey != null)) if (resp.Code == MessageResponeCodes.OK)
{ {
ulong length = cache.Sendt; try
Interlocked.Add(ref Unsafe.As<ulong, long>(ref cache.Sendt), -(long)length);
if (cdkeyLastBytes.TryGetValue(cache.CurrentCdkey.Id, out ulong value))
{ {
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)) ResetNodeBytes();
{
ulong length = cache.Sendt;
Interlocked.Add(ref Unsafe.As<ulong, long>(ref cache.Sendt), -(long)length);
ResetNodeBytes(length);
}
await Task.CompletedTask;
return true; return true;
}, () => 5000); }, 5000);
} }
private void ReportTask() 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> IEnumerable<RelayServerNodeInfo> nodes = new List<RelayServerNodeInfo>
{ {
//默认报告给自己,作为本服务器的一个默认中继节点 //默认报告给自己,作为本服务器的一个默认中继节点
@@ -349,8 +380,7 @@ namespace linker.messenger.relay.server
MaxGbTotalLastBytes = node.MaxGbTotalLastBytes, MaxGbTotalLastBytes = node.MaxGbTotalLastBytes,
MaxConnection = node.MaxConnection, MaxConnection = node.MaxConnection,
ConnectionRatio = Math.Round(node.MaxConnection == 0 ? 0 : connectionNum / 2.0 / node.MaxConnection, 2), ConnectionRatio = Math.Round(node.MaxConnection == 0 ? 0 : connectionNum / 2.0 / node.MaxConnection, 2),
EndPoint = endPoint, EndPoint = endPoint
UserIds = node.UserIds
}; };
await messengerSender.SendOnly(new MessageRequestWrap await messengerSender.SendOnly(new MessageRequestWrap
@@ -364,17 +394,17 @@ namespace linker.messenger.relay.server
{ {
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{ {
LoggerHelper.Instance.Debug($"relay report : {ex}"); LoggerHelper.Instance.Error($"relay report : {ex}");
} }
} }
} }
return true; return true;
}, () => 5000); }, 5000);
} }
private void SignInTask() private void SignInTask()
{ {
TimerHelper.SetInterval(async () => TimerHelper.SetIntervalLong(async () =>
{ {
if ((remoteConnection == null || remoteConnection.Connected == false) && string.IsNullOrWhiteSpace(relayServerNodeStore.Node.MasterHost) == false) 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); localConnection = await SignIn(new IPEndPoint(IPAddress.Loopback, relayServerNodeStore.ServicePort).ToString(), relayServerMasterStore.Master.SecretKey).ConfigureAwait(false);
} }
return true; return true;
}, () => 3000); }, 3000);
} }
private async Task<IConnection> SignIn(string host, string secretKey) 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 socket = new Socket(remote.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.KeepAlive(); socket.KeepAlive();
await socket.ConnectAsync(remote).WaitAsync(TimeSpan.FromMilliseconds(5000)).ConfigureAwait(false); 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 finally
{ {
@@ -416,16 +450,16 @@ namespace linker.messenger.relay.server
} }
} }
public sealed partial class RelayTrafficReportInfo public sealed partial class RelayTrafficUpdateInfo
{ {
/// <summary> /// <summary>
/// cdkey id 和 流量 /// cdkey id 和 流量
/// </summary> /// </summary>
public Dictionary<string, ulong> Id2Bytes { get; set; } public Dictionary<long, long> Dic { get; set; }
/// <summary> /// <summary>
/// 需要知道哪些cdkey的剩余流量 /// 需要知道哪些cdkey的剩余流量
/// </summary> /// </summary>
public List<string> UpdateIds { get; set; } public List<long> Ids { get; set; }
public string SecretKey { get; set; } public string SecretKey { get; set; }
} }

View File

@@ -24,10 +24,10 @@ namespace linker.messenger.relay.server
this.messengerResolver = messengerResolver; 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); byte[] buffer = ArrayPool<byte>.Shared.Rent(1024);
try 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); await socket.ReceiveAsync(buffer.AsMemory(0, length), SocketFlags.None).ConfigureAwait(false);
string key = buffer.AsMemory(0, length).GetString(); string key = buffer.AsMemory(0, length).GetString();
if (relayServerMasterStore.Master.SecretKey.Md5() == key) if (relayServerMasterStore.Master.SecretKey.Md5() == key)
{ {
await messengerResolver.BeginReceiveServer(socket, Helper.EmptyArray); 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 finally
{ {

View File

@@ -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 try
{ {
switch (relayMessage.Type) switch (relayMessage.Type)
@@ -152,7 +152,7 @@ namespace linker.messenger.relay.server
while ((bytesRead = await source.ReceiveAsync(buffer.AsMemory(), SocketFlags.None).ConfigureAwait(false)) != 0) 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(); source.SafeClose();
break; break;
@@ -181,8 +181,8 @@ namespace linker.messenger.relay.server
} }
} }
AddReceive(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, (ulong)bytesRead); AddSendt(cache.FromId, cache.FromName, cache.ToName, cache.GroupId, bytesRead);
await destination.SendAsync(buffer.AsMemory(0, bytesRead), SocketFlags.None).ConfigureAwait(false); 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 sealed class RelayTrafficCacheInfo
{ {
public ulong Sendt; public long Sendt;
public RelaySpeedLimit Limit { get; set; } public RelaySpeedLimit Limit { get; set; }
public RelayCacheInfo Cache { get; set; } public RelayCacheInfo Cache { get; set; }
public RelayServerCdkeyInfo CurrentCdkey { 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 public sealed class RelayWrapInfo
{ {

View File

@@ -56,6 +56,7 @@ namespace linker.messenger.serializer.memorypack
MemoryPackFormatterProvider.Register(new RelayCacheInfoFormatter()); MemoryPackFormatterProvider.Register(new RelayCacheInfoFormatter());
MemoryPackFormatterProvider.Register(new RelayMessageInfoFormatter()); MemoryPackFormatterProvider.Register(new RelayMessageInfoFormatter());
MemoryPackFormatterProvider.Register(new RelayServerCdkeyInfoFormatter()); MemoryPackFormatterProvider.Register(new RelayServerCdkeyInfoFormatter());
MemoryPackFormatterProvider.Register(new RelayServerCdkeyStoreInfoFormatter());
MemoryPackFormatterProvider.Register(new RelayServerCdkeyPageRequestInfoFormatter()); MemoryPackFormatterProvider.Register(new RelayServerCdkeyPageRequestInfoFormatter());
MemoryPackFormatterProvider.Register(new RelayServerCdkeyPageResultInfoFormatter()); MemoryPackFormatterProvider.Register(new RelayServerCdkeyPageResultInfoFormatter());
MemoryPackFormatterProvider.Register(new RelayServerCdkeyAddInfoFormatter()); MemoryPackFormatterProvider.Register(new RelayServerCdkeyAddInfoFormatter());

View File

@@ -11,13 +11,13 @@ namespace linker.messenger.serializer.memorypack
public readonly FlowItemInfo info; public readonly FlowItemInfo info;
[MemoryPackInclude] [MemoryPackInclude]
ulong ReceiveBytes => info.ReceiveBytes; long ReceiveBytes => info.ReceiveBytes;
[MemoryPackInclude] [MemoryPackInclude]
ulong SendtBytes => info.SendtBytes; long SendtBytes => info.SendtBytes;
[MemoryPackConstructor] [MemoryPackConstructor]
SerializableFlowItemInfo(ulong receiveBytes, ulong sendtBytes) SerializableFlowItemInfo(long receiveBytes, long sendtBytes)
{ {
var info = new FlowItemInfo { ReceiveBytes = receiveBytes, SendtBytes = sendtBytes }; var info = new FlowItemInfo { ReceiveBytes = receiveBytes, SendtBytes = sendtBytes };
this.info = info; this.info = info;
@@ -181,16 +181,16 @@ namespace linker.messenger.serializer.memorypack
public readonly RelayFlowItemInfo info; public readonly RelayFlowItemInfo info;
[MemoryPackInclude] [MemoryPackInclude]
ulong ReceiveBytes => info.ReceiveBytes; long ReceiveBytes => info.ReceiveBytes;
[MemoryPackInclude] [MemoryPackInclude]
ulong SendtBytes => info.SendtBytes; long SendtBytes => info.SendtBytes;
[MemoryPackInclude] [MemoryPackInclude]
ulong DiffReceiveBytes => info.DiffReceiveBytes; long DiffReceiveBytes => info.DiffReceiveBytes;
[MemoryPackInclude] [MemoryPackInclude]
ulong DiffSendtBytes => info.DiffSendtBytes; long DiffSendtBytes => info.DiffSendtBytes;
[MemoryPackInclude] [MemoryPackInclude]
string FromName => info.FromName; string FromName => info.FromName;
@@ -199,7 +199,7 @@ namespace linker.messenger.serializer.memorypack
string ToName => info.ToName; string ToName => info.ToName;
[MemoryPackConstructor] [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 var info = new RelayFlowItemInfo
{ {
@@ -393,22 +393,22 @@ namespace linker.messenger.serializer.memorypack
public readonly SForwardFlowItemInfo info; public readonly SForwardFlowItemInfo info;
[MemoryPackInclude] [MemoryPackInclude]
ulong ReceiveBytes => info.ReceiveBytes; long ReceiveBytes => info.ReceiveBytes;
[MemoryPackInclude] [MemoryPackInclude]
ulong SendtBytes => info.SendtBytes; long SendtBytes => info.SendtBytes;
[MemoryPackInclude] [MemoryPackInclude]
ulong DiffReceiveBytes => info.DiffReceiveBytes; long DiffReceiveBytes => info.DiffReceiveBytes;
[MemoryPackInclude] [MemoryPackInclude]
ulong DiffSendtBytes => info.DiffSendtBytes; long DiffSendtBytes => info.DiffSendtBytes;
[MemoryPackInclude] [MemoryPackInclude]
string Key => info.Key; string Key => info.Key;
[MemoryPackConstructor] [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 var info = new SForwardFlowItemInfo
{ {

View File

@@ -11,7 +11,7 @@ namespace linker.messenger.serializer.memorypack
public readonly ForwardInfo info; public readonly ForwardInfo info;
[MemoryPackInclude] [MemoryPackInclude]
uint Id => info.Id; long Id => info.Id;
[MemoryPackInclude] [MemoryPackInclude]
string Name => info.Name; string Name => info.Name;
@@ -47,7 +47,7 @@ namespace linker.messenger.serializer.memorypack
string TargetMsg => info.TargetMsg; string TargetMsg => info.TargetMsg;
[MemoryPackConstructor] [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 this.info = new ForwardInfo
{ {
@@ -167,10 +167,10 @@ namespace linker.messenger.serializer.memorypack
string MachineId => info.MachineId; string MachineId => info.MachineId;
[MemoryPackInclude, MemoryPackAllowSerialize] [MemoryPackInclude, MemoryPackAllowSerialize]
uint Id => info.Id; long Id => info.Id;
[MemoryPackConstructor] [MemoryPackConstructor]
SerializableForwardRemoveForwardInfo(string machineId, uint id) SerializableForwardRemoveForwardInfo(string machineId, long id)
{ {
this.info = new ForwardRemoveForwardInfo this.info = new ForwardRemoveForwardInfo
{ {

View File

@@ -171,7 +171,7 @@ namespace linker.messenger.serializer.memorypack
[MemoryPackInclude] [MemoryPackInclude]
double MaxGbTotal => info.MaxGbTotal; double MaxGbTotal => info.MaxGbTotal;
[MemoryPackInclude] [MemoryPackInclude]
ulong MaxGbTotalLastBytes => info.MaxGbTotalLastBytes; long MaxGbTotalLastBytes => info.MaxGbTotalLastBytes;
[MemoryPackInclude] [MemoryPackInclude]
double ConnectionRatio => info.ConnectionRatio; double ConnectionRatio => info.ConnectionRatio;
[MemoryPackInclude] [MemoryPackInclude]
@@ -185,18 +185,15 @@ namespace linker.messenger.serializer.memorypack
[MemoryPackInclude] [MemoryPackInclude]
long LastTicks => info.LastTicks; long LastTicks => info.LastTicks;
[MemoryPackInclude]
List<string> UserIds => info.UserIds;
[MemoryPackConstructor] [MemoryPackConstructor]
SerializableRelayServerNodeReportInfo( SerializableRelayServerNodeReportInfo(
string id, string name, string id, string name,
int maxConnection, double maxBandwidth, double maxBandwidthTotal, int maxConnection, double maxBandwidth, double maxBandwidthTotal,
double maxGbTotal, ulong maxGbTotalLastBytes, double maxGbTotal, long maxGbTotalLastBytes,
double connectionRatio, double bandwidthRatio, double connectionRatio, double bandwidthRatio,
bool Public, int delay, bool Public, int delay,
IPEndPoint endPoint, long lastTicks, List<string> userIds) IPEndPoint endPoint, long lastTicks)
{ {
var info = new RelayServerNodeReportInfo var info = new RelayServerNodeReportInfo
{ {
@@ -212,8 +209,7 @@ namespace linker.messenger.serializer.memorypack
MaxGbTotal = maxGbTotal, MaxGbTotal = maxGbTotal,
MaxGbTotalLastBytes = maxGbTotalLastBytes, MaxGbTotalLastBytes = maxGbTotalLastBytes,
Name = name, Name = name,
Public = Public, Public = Public
UserIds = userIds
}; };
this.info = info; this.info = info;
} }
@@ -447,7 +443,6 @@ namespace linker.messenger.serializer.memorypack
} }
} }
[MemoryPackable] [MemoryPackable]
public readonly partial struct SerializableRelayServerCdkeyInfo public readonly partial struct SerializableRelayServerCdkeyInfo
{ {
@@ -455,53 +450,21 @@ namespace linker.messenger.serializer.memorypack
public readonly RelayServerCdkeyInfo info; public readonly RelayServerCdkeyInfo info;
[MemoryPackInclude] [MemoryPackInclude]
string Id => info.Id; long CdkeyId => info.CdkeyId;
[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]
List<string> Nodes => info.Nodes;
[MemoryPackInclude] [MemoryPackInclude]
double Bandwidth => info.Bandwidth; double Bandwidth => info.Bandwidth;
[MemoryPackInclude] [MemoryPackInclude]
ulong MaxBytes => info.MaxBytes; long LastBytes => info.LastBytes;
[MemoryPackInclude]
ulong LastBytes => info.LastBytes;
[MemoryPackInclude]
double Memory => info.Memory;
[MemoryPackInclude]
double PayMemory => info.PayMemory;
[MemoryPackInclude]
string Remark => info.Remark;
[MemoryPackConstructor] [MemoryPackConstructor]
SerializableRelayServerCdkeyInfo(string id, string userid, string cdKey, DateTime addTime, DateTime startTime, DateTime endTime, SerializableRelayServerCdkeyInfo(long cdkeyid, double bandwidth, long lastBytes)
List<string> nodes, double bandwidth, ulong maxBytes, ulong lastBytes, double memory, double payMemory, string remark)
{ {
var info = new RelayServerCdkeyInfo var info = new RelayServerCdkeyInfo
{ {
Id = id, CdkeyId = cdkeyid,
UserId = userid,
CdKey = cdKey,
AddTime = addTime,
StartTime = startTime,
EndTime = endTime,
Nodes = nodes,
Bandwidth = bandwidth, Bandwidth = bandwidth,
MaxBytes = maxBytes, LastBytes = lastBytes
LastBytes = lastBytes,
Memory = memory,
PayMemory = payMemory,
Remark = remark
}; };
this.info = info; 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] [MemoryPackable]
public readonly partial struct SerializableRelayServerCdkeyAddInfo public readonly partial struct SerializableRelayServerCdkeyAddInfo
@@ -549,10 +609,10 @@ namespace linker.messenger.serializer.memorypack
[MemoryPackInclude] [MemoryPackInclude]
string SecretKey => info.SecretKey; string SecretKey => info.SecretKey;
[MemoryPackInclude, MemoryPackAllowSerialize] [MemoryPackInclude, MemoryPackAllowSerialize]
RelayServerCdkeyInfo Data => info.Data; RelayServerCdkeyStoreInfo Data => info.Data;
[MemoryPackConstructor] [MemoryPackConstructor]
SerializableRelayServerCdkeyAddInfo(string secretKey, RelayServerCdkeyInfo data) SerializableRelayServerCdkeyAddInfo(string secretKey, RelayServerCdkeyStoreInfo data)
{ {
var info = new RelayServerCdkeyAddInfo var info = new RelayServerCdkeyAddInfo
{ {
@@ -604,15 +664,15 @@ namespace linker.messenger.serializer.memorypack
[MemoryPackInclude] [MemoryPackInclude]
string SecretKey => info.SecretKey; string SecretKey => info.SecretKey;
[MemoryPackInclude] [MemoryPackInclude]
string Id => info.Id; long CdkeyId => info.CdkeyId;
[MemoryPackConstructor] [MemoryPackConstructor]
SerializableRelayServerCdkeyDelInfo(string secretKey, string id) SerializableRelayServerCdkeyDelInfo(string secretKey, long cdkeyid)
{ {
var info = new RelayServerCdkeyDelInfo var info = new RelayServerCdkeyDelInfo
{ {
SecretKey = secretKey, SecretKey = secretKey,
Id = id CdkeyId = cdkeyid
}; };
this.info = info; this.info = info;
} }
@@ -735,10 +795,10 @@ namespace linker.messenger.serializer.memorypack
[MemoryPackInclude] [MemoryPackInclude]
int Count => info.Count; int Count => info.Count;
[MemoryPackInclude] [MemoryPackInclude]
List<RelayServerCdkeyInfo> List => info.List; List<RelayServerCdkeyStoreInfo> List => info.List;
[MemoryPackConstructor] [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 var info = new RelayServerCdkeyPageResultInfo
{ {
@@ -788,35 +848,35 @@ namespace linker.messenger.serializer.memorypack
public readonly partial struct SerializableRelayTrafficReportInfo public readonly partial struct SerializableRelayTrafficReportInfo
{ {
[MemoryPackIgnore] [MemoryPackIgnore]
public readonly RelayTrafficReportInfo info; public readonly RelayTrafficUpdateInfo info;
[MemoryPackInclude] [MemoryPackInclude]
Dictionary<string, ulong> Id2Bytes => info.Id2Bytes; Dictionary<long, long> Dic => info.Dic;
[MemoryPackInclude] [MemoryPackInclude]
List<string> UpdateIds => info.UpdateIds; List<long> Ids => info.Ids;
[MemoryPackInclude] [MemoryPackInclude]
string SecretKey => info.SecretKey; string SecretKey => info.SecretKey;
[MemoryPackConstructor] [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, Dic = dic,
UpdateIds = updateIds, Ids = ids,
SecretKey = secretKey SecretKey = secretKey
}; };
this.info = info; this.info = info;
} }
public SerializableRelayTrafficReportInfo(RelayTrafficReportInfo info) public SerializableRelayTrafficReportInfo(RelayTrafficUpdateInfo info)
{ {
this.info = 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) if (value == null)
{ {
@@ -827,7 +887,7 @@ namespace linker.messenger.serializer.memorypack
writer.WritePackable(new SerializableRelayTrafficReportInfo(value)); 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()) if (reader.PeekIsNull())
{ {

View File

@@ -11,7 +11,7 @@ namespace linker.messenger.serializer.memorypack
public readonly SForwardInfo info; public readonly SForwardInfo info;
[MemoryPackInclude] [MemoryPackInclude]
uint Id => info.Id; long Id => info.Id;
[MemoryPackInclude] [MemoryPackInclude]
string Name => info.Name; string Name => info.Name;
@@ -44,7 +44,7 @@ namespace linker.messenger.serializer.memorypack
int RemotePortMax => info.RemotePortMax; int RemotePortMax => info.RemotePortMax;
[MemoryPackConstructor] [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 this.info = new SForwardInfo
{ {
@@ -277,10 +277,10 @@ namespace linker.messenger.serializer.memorypack
string MachineId => info.MachineId; string MachineId => info.MachineId;
[MemoryPackInclude, MemoryPackAllowSerialize] [MemoryPackInclude, MemoryPackAllowSerialize]
uint Id => info.Id; long Id => info.Id;
[MemoryPackConstructor] [MemoryPackConstructor]
SerializableSForwardRemoveForwardInfo(string machineId, uint id) SerializableSForwardRemoveForwardInfo(string machineId, long id)
{ {
this.info = new SForwardRemoveForwardInfo this.info = new SForwardRemoveForwardInfo
{ {

View File

@@ -10,7 +10,7 @@ namespace linker.messenger.sforward
/// <summary> /// <summary>
/// 穿透id /// 穿透id
/// </summary> /// </summary>
public uint Id { get; set; } public long Id { get; set; }
/// <summary> /// <summary>
/// 名称 /// 名称
/// </summary> /// </summary>
@@ -125,7 +125,7 @@ namespace linker.messenger.sforward
public sealed partial class SForwardRemoveForwardInfo public sealed partial class SForwardRemoveForwardInfo
{ {
public string MachineId { get; set; } public string MachineId { get; set; }
public uint Id { get; set; } public long Id { get; set; }
} }
/// <summary> /// <summary>

View File

@@ -30,7 +30,7 @@
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id"></param>
/// <returns></returns> /// <returns></returns>
public SForwardInfo Get(uint id); public SForwardInfo Get(long id);
/// <summary> /// <summary>
/// 获取穿透 /// 获取穿透
/// </summary> /// </summary>
@@ -60,7 +60,7 @@
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id"></param>
/// <returns></returns> /// <returns></returns>
public bool Remove(uint id); public bool Remove(long id);
/// <summary> /// <summary>
/// 提交保存 /// 提交保存
/// </summary> /// </summary>

View File

@@ -16,9 +16,6 @@ namespace linker.messenger.sforward.client
private readonly ISForwardClientStore sForwardClientStore; private readonly ISForwardClientStore sForwardClientStore;
private readonly ISerializer serializer; private readonly ISerializer serializer;
private readonly NumberSpaceUInt32 ns = new NumberSpaceUInt32();
public SForwardClientTransfer(SignInClientState signInClientState, IMessengerSender messengerSender, ISignInClientStore signInClientStore, ISForwardClientStore sForwardClientStore, ISerializer serializer) public SForwardClientTransfer(SignInClientState signInClientState, IMessengerSender messengerSender, ISignInClientStore signInClientStore, ISForwardClientStore sForwardClientStore, ISerializer serializer)
{ {
this.signInClientState = signInClientState; this.signInClientState = signInClientState;
@@ -33,8 +30,6 @@ namespace linker.messenger.sforward.client
private void Start() private void Start()
{ {
var list = sForwardClientStore.Get(); var list = sForwardClientStore.Get();
uint maxid = list.Count > 0 ? list.Max(c => c.Id) : 1;
ns.Reset(maxid);
foreach (var item in list) foreach (var item in list)
{ {
@@ -167,7 +162,6 @@ namespace linker.messenger.sforward.client
} }
else else
{ {
forwardInfo.Id = ns.Increment();
if (PortRange(forwardInfo.Domain, out int min, out int max)) if (PortRange(forwardInfo.Domain, out int min, out int max))
{ {
forwardInfo.RemotePortMin = min; forwardInfo.RemotePortMin = min;
@@ -183,7 +177,7 @@ namespace linker.messenger.sforward.client
return true; return true;
} }
public bool Remove(uint id) public bool Remove(long id)
{ {
//同名或者同端口但是ID不一样 //同名或者同端口但是ID不一样
SForwardInfo old = sForwardClientStore.Get(id); SForwardInfo old = sForwardClientStore.Get(id);

View File

@@ -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)
{ {
} }

View File

@@ -281,13 +281,13 @@ namespace linker.plugins.sforward.proxy
{ {
if (isDomain) if (isDomain)
{ {
AddReceive(domain, groupid, (ulong)bytesRead); AddReceive(domain, groupid, bytesRead);
AddSendt(domain, groupid, (ulong)bytesRead); AddSendt(domain, groupid, bytesRead);
} }
else else
{ {
AddReceive(portStr, groupid, (ulong)bytesRead); AddReceive(portStr, groupid, bytesRead);
AddSendt(portStr, groupid, (ulong)bytesRead); AddSendt(portStr, groupid, bytesRead);
} }
await target.SendAsync(buffer.Slice(0, bytesRead), SocketFlags.None).ConfigureAwait(false); await target.SendAsync(buffer.Slice(0, bytesRead), SocketFlags.None).ConfigureAwait(false);
} }

View File

@@ -59,13 +59,13 @@ namespace linker.plugins.sforward.proxy
Memory<byte> memory = buffer.AsMemory(0, result.ReceivedBytes); 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; IPEndPoint source = result.RemoteEndPoint as IPEndPoint;
//已经连接 //已经连接
if (udpConnections.TryGetValue(source, out UdpTargetCache cache) && cache != null) 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(); cache.LastTicks.Update();
await token.SourceSocket.SendToAsync(memory, cache.IPEndPoint).ConfigureAwait(false); await token.SourceSocket.SendToAsync(memory, cache.IPEndPoint).ConfigureAwait(false);
} }
@@ -197,8 +197,8 @@ namespace linker.plugins.sforward.proxy
cache.LastTicks.Update(); cache.LastTicks.Update();
Memory<byte> memory = buffer.AsMemory(0, result.ReceivedBytes); Memory<byte> memory = buffer.AsMemory(0, result.ReceivedBytes);
AddReceive(portStr, string.Empty, (ulong)memory.Length); AddReceive(portStr, string.Empty, memory.Length);
AddSendt(portStr, string.Empty, (ulong)memory.Length); AddSendt(portStr, string.Empty, memory.Length);
//未连接本地服务的,去连接一下 //未连接本地服务的,去连接一下
if (serviceUdp == null) if (serviceUdp == null)
{ {
@@ -239,8 +239,8 @@ namespace linker.plugins.sforward.proxy
break; break;
} }
Memory<byte> memory = buffer.AsMemory(0, result.ReceivedBytes); Memory<byte> memory = buffer.AsMemory(0, result.ReceivedBytes);
AddReceive(portStr, string.Empty, (ulong)memory.Length); AddReceive(portStr, string.Empty, memory.Length);
AddSendt(portStr, string.Empty, (ulong)memory.Length); AddSendt(portStr, string.Empty, memory.Length);
await serverUdp.SendToAsync(memory, server).ConfigureAwait(false); await serverUdp.SendToAsync(memory, server).ConfigureAwait(false);
cache.LastTicks.Update(); cache.LastTicks.Update();
@@ -261,7 +261,7 @@ namespace linker.plugins.sforward.proxy
private void UdpTask() private void UdpTask()
{ {
TimerHelper.SetInterval(() => TimerHelper.SetIntervalLong(() =>
{ {
var connections = udpConnections.Where(c => c.Value.Timeout).Select(c => c.Key); var connections = udpConnections.Where(c => c.Value.Timeout).Select(c => c.Key);
foreach (var item in connections) foreach (var item in connections)

View File

@@ -34,7 +34,7 @@ namespace linker.messenger.signin
/// </summary> /// </summary>
public void SignInTask() public void SignInTask()
{ {
TimerHelper.SetInterval(async () => TimerHelper.SetIntervalLong(async () =>
{ {
if (clientSignInState.Connected == false) if (clientSignInState.Connected == false)
{ {
@@ -49,7 +49,7 @@ namespace linker.messenger.signin
} }
} }
return true; return true;
}, () => 10000); }, 10000);
} }
public void ReSignIn() public void ReSignIn()

View File

@@ -121,7 +121,7 @@ namespace linker.messenger.signin
private void ClearTask() private void ClearTask()
{ {
TimerHelper.SetInterval(() => TimerHelper.SetIntervalLong(() =>
{ {
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{ {

View File

@@ -242,7 +242,7 @@ namespace linker.messenger.socks5
private void TaskUdp() private void TaskUdp()
{ {
TimerHelper.SetInterval(() => TimerHelper.SetIntervalLong(() =>
{ {
var connections = udpConnections.Where(c => c.Value.Timeout).Select(c => c.Key).ToList(); var connections = udpConnections.Where(c => c.Value.Timeout).Select(c => c.Key).ToList();
foreach (var item in connections) foreach (var item in connections)
@@ -259,7 +259,7 @@ namespace linker.messenger.socks5
} }
} }
return true; return true;
}, () => 3 * 60 * 1000); }, 3 * 60 * 1000);
} }
private void CloseClientSocketUdp(ITunnelConnection connection) private void CloseClientSocketUdp(ITunnelConnection connection)

View File

@@ -32,6 +32,8 @@ using linker.messenger.tuntap.lease;
using linker.messenger.updater; using linker.messenger.updater;
using linker.plugins.tunnel; using linker.plugins.tunnel;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Yitter.IdGenerator;
namespace linker.messenger.store.file namespace linker.messenger.store.file
{ {
public static class Entry public static class Entry
@@ -40,6 +42,8 @@ namespace linker.messenger.store.file
{ {
LoggerHelper.Instance.Info("add store file"); LoggerHelper.Instance.Info("add store file");
YitIdHelper.SetIdGenerator(new IdGeneratorOptions(1));
serviceCollection.AddSingleton<Storefactory>(); serviceCollection.AddSingleton<Storefactory>();
serviceCollection.AddSingleton<FileConfig>(); serviceCollection.AddSingleton<FileConfig>();
serviceCollection.AddSingleton<RunningConfig>(); serviceCollection.AddSingleton<RunningConfig>();

View File

@@ -127,7 +127,7 @@ namespace linker.messenger.store.file
} }
private void SaveTask() private void SaveTask()
{ {
TimerHelper.SetInterval(() => TimerHelper.SetIntervalLong(() =>
{ {
while (Data.Updated > 0) while (Data.Updated > 0)
{ {

View File

@@ -45,7 +45,7 @@ namespace linker.messenger.store.file
} }
private void SaveTask() private void SaveTask()
{ {
TimerHelper.SetInterval(() => TimerHelper.SetIntervalLong(() =>
{ {
while (Data.Updated > 0) while (Data.Updated > 0)
{ {

View File

@@ -34,7 +34,7 @@ namespace linker.messenger.store.file
private void CheckpointTask() private void CheckpointTask()
{ {
TimerHelper.SetInterval(() => TimerHelper.SetIntervalLong(() =>
{ {
database.Checkpoint(); database.Checkpoint();
return true; return true;

View File

@@ -1,4 +1,5 @@
using linker.messenger.forward; using linker.messenger.forward;
using Yitter.IdGenerator;
namespace linker.messenger.store.file.forward namespace linker.messenger.store.file.forward
{ {
@@ -23,7 +24,7 @@ namespace linker.messenger.store.file.forward
return runningConfig.Data.Forwards; return runningConfig.Data.Forwards;
} }
public ForwardInfo Get(uint id) public ForwardInfo Get(long id)
{ {
return runningConfig.Data.Forwards.FirstOrDefault(x => x.Id == 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) public bool Add(ForwardInfo info)
{ {
if(info.Id == 0)
{
info.Id = YitIdHelper.NextId();
}
runningConfig.Data.Forwards.Add(info); runningConfig.Data.Forwards.Add(info);
return true; return true;
} }
@@ -42,7 +48,7 @@ namespace linker.messenger.store.file.forward
{ {
return true; return true;
} }
public bool Remove(uint id) public bool Remove(long id)
{ {
runningConfig.Data.Forwards.Remove(Get(id)); runningConfig.Data.Forwards.Remove(Get(id));
return true; return true;

View File

@@ -38,6 +38,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="LiteDB" Version="5.0.17" /> <PackageReference Include="LiteDB" Version="5.0.17" />
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\linker.libs\linker.libs.csproj" /> <ProjectReference Include="..\linker.libs\linker.libs.csproj" />

View File

@@ -8,6 +8,7 @@ namespace linker.messenger.store.file
public sealed partial class RunningConfigInfo public sealed partial class RunningConfigInfo
{ {
public RelayInfo Relay { get; set; } = new RelayInfo(); public RelayInfo Relay { get; set; } = new RelayInfo();
} }
public sealed class RelayInfo public sealed class RelayInfo
@@ -43,6 +44,8 @@ namespace linker.messenger.store.file
#else #else
public string SecretKey { get; set; } = Guid.NewGuid().ToString().ToUpper(); public string SecretKey { get; set; } = Guid.NewGuid().ToString().ToUpper();
#endif #endif
public RelayServerCdkeyConfigInfo Cdkey { get; set; } = new RelayServerCdkeyConfigInfo();
public DistributedInfo Distributed { get; set; } = new DistributedInfo { }; public DistributedInfo Distributed { get; set; } = new DistributedInfo { };
} }

View File

@@ -1,23 +1,29 @@
using linker.messenger.relay.server; using linker.messenger.relay.server;
using LiteDB; using LiteDB;
using Yitter.IdGenerator;
namespace linker.messenger.store.file.relay namespace linker.messenger.store.file.relay
{ {
public sealed class RelayServerCdkeyStore : IRelayServerCdkeyStore public sealed class RelayServerCdkeyStore : IRelayServerCdkeyStore
{ {
private readonly Storefactory dBfactory; private readonly Storefactory dBfactory;
private readonly ILiteCollection<RelayServerCdkeyInfo> liteCollection; private readonly ILiteCollection<RelayServerCdkeyStoreInfo> liteCollection;
public RelayServerCdkeyStore(Storefactory dBfactory, FileConfig fileConfig) public RelayServerCdkeyStore(Storefactory dBfactory, FileConfig fileConfig)
{ {
this.dBfactory = dBfactory; 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)) if (string.IsNullOrWhiteSpace(info.Id))
{ {
info.Id = ObjectId.NewObjectId().ToString(); 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); liteCollection.Insert(info);
} }
else else
@@ -26,40 +32,64 @@ namespace linker.messenger.store.file.relay
} }
return await Task.FromResult(true); 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()); 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<List<RelayServerCdkeyStoreInfo>> Get(List<long> ids)
public async Task<RelayServerCdkeyPageResultInfo> Get(RelayServerCdkeyPageRequestInfo relayServerCdkeyPageRequestInfo)
{ {
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 return await Task.FromResult(new RelayServerCdkeyPageResultInfo
{ {
Page = relayServerCdkeyPageRequestInfo.Page, Page = info.Page,
Size = relayServerCdkeyPageRequestInfo.Size, Size = info.Size,
Count = query.Count(), 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()
}); });
} }
} }
} }

View File

@@ -22,7 +22,7 @@ namespace linker.messenger.store.file.relay
{ {
config.Data.Server.Relay.Distributed.Node = node; 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; config.Data.Server.Relay.Distributed.Node.MaxGbTotalLastBytes=value;
} }

View File

@@ -1,5 +1,6 @@
using linker.messenger.sforward; using linker.messenger.sforward;
using linker.messenger.sforward.client; using linker.messenger.sforward.client;
using Yitter.IdGenerator;
namespace linker.messenger.store.file.sforward namespace linker.messenger.store.file.sforward
{ {
@@ -36,7 +37,7 @@ namespace linker.messenger.store.file.sforward
return runningConfig.Data.SForwards; return runningConfig.Data.SForwards;
} }
public SForwardInfo Get(uint id) public SForwardInfo Get(long id)
{ {
return runningConfig.Data.SForwards.FirstOrDefault(x => x.Id == 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) public bool Add(SForwardInfo info)
{ {
if (info.Id == 0)
{
info.Id = YitIdHelper.NextId();
}
runningConfig.Data.SForwards.Add(info); runningConfig.Data.SForwards.Add(info);
return true; return true;
} }
@@ -60,7 +65,7 @@ namespace linker.messenger.store.file.sforward
{ {
return true; return true;
} }
public bool Remove(uint id) public bool Remove(long id)
{ {
runningConfig.Data.SForwards.Remove(Get(id)); runningConfig.Data.SForwards.Remove(Get(id));
return true; return true;

View File

@@ -14,8 +14,8 @@ namespace linker.messenger.tunnel
{ {
public byte Type => (byte)ResolverType.External; public byte Type => (byte)ResolverType.External;
public virtual void AddReceive( ulong bytes) { } public virtual void AddReceive( long bytes) { }
public virtual void AddSendt(ulong bytes) { } public virtual void AddSendt(long bytes) { }
/// <summary> /// <summary>
/// UDP /// UDP
@@ -28,12 +28,12 @@ namespace linker.messenger.tunnel
{ {
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Debug($"{ep} get udp external port"); 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); byte[] sendData = ArrayPool<byte>.Shared.Rent(1024);
try try
{ {
var send = BuildSendData(sendData, ep); var send = BuildSendData(sendData, ep);
AddSendt((ulong)send.Length); AddSendt(send.Length);
await socket.SendToAsync(send, SocketFlags.None, ep).ConfigureAwait(false); await socket.SendToAsync(send, SocketFlags.None, ep).ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
@@ -57,7 +57,7 @@ namespace linker.messenger.tunnel
try try
{ {
memory = BuildSendData(sendData, socket.RemoteEndPoint as IPEndPoint); memory = BuildSendData(sendData, socket.RemoteEndPoint as IPEndPoint);
AddSendt((ulong)memory.Length); AddSendt(memory.Length);
await socket.SendAsync(memory, SocketFlags.None).ConfigureAwait(false); await socket.SendAsync(memory, SocketFlags.None).ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)

View File

@@ -80,11 +80,11 @@ namespace linker.messenger.tuntap
private OperatingManager checking = new OperatingManager(); private OperatingManager checking = new OperatingManager();
private void CheckDeviceTask() private void CheckDeviceTask()
{ {
TimerHelper.SetInterval(async () => TimerHelper.SetIntervalLong(async () =>
{ {
await CheckDevice(); await CheckDevice();
return true; return true;
}, () => 30000); }, 30000);
} }
private async Task CheckDevice() private async Task CheckDevice()
{ {

View File

@@ -35,7 +35,7 @@ namespace linker.messenger.tuntap
} }
private void PingTask() private void PingTask()
{ {
TimerHelper.SetInterval(async () => TimerHelper.SetIntervalLong(async () =>
{ {
if (tuntapTransfer.Status == TuntapStatus.Running) if (tuntapTransfer.Status == TuntapStatus.Running)
{ {

View File

@@ -73,7 +73,7 @@ namespace linker.messenger.tuntap.lease
private void LeaseExpTask() private void LeaseExpTask()
{ {
TimerHelper.SetInterval(async () => TimerHelper.SetIntervalLong(async () =>
{ {
await messengerSender.SendReply(new MessageRequestWrap await messengerSender.SendReply(new MessageRequestWrap
{ {
@@ -82,7 +82,7 @@ namespace linker.messenger.tuntap.lease
}); });
return true; return true;
}, () => 60000); }, 60000);
} }
} }
} }

View File

@@ -219,7 +219,7 @@ namespace linker.messenger.tuntap.lease
private void ClearTask() private void ClearTask()
{ {
TimerHelper.SetInterval(() => TimerHelper.SetIntervalLong(() =>
{ {
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{ {

View File

@@ -89,7 +89,7 @@ namespace linker.messenger.updater
} }
private void UpdateTask() private void UpdateTask()
{ {
TimerHelper.SetInterval(async () => TimerHelper.SetIntervalLong(async () =>
{ {
await GetUpdateInfo(); await GetUpdateInfo();
if (updateInfo.Updated) if (updateInfo.Updated)

View File

@@ -15,7 +15,7 @@ namespace linker.messenger
public interface IMessengerResolver public interface IMessengerResolver
{ {
public Task<IConnection> BeginReceiveClient(Socket socket); 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 void AddMessenger(List<IMessenger> list);
public Task BeginReceiveServer(Socket socket, Memory<byte> memory); public Task BeginReceiveServer(Socket socket, Memory<byte> memory);
public Task BeginReceiveServer(Socket socket, IPEndPoint ep, 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 AddReceive(ushort id, long bytes) { }
public virtual void AddSendt(ushort id, ulong bytes) { } public virtual void AddSendt(ushort id, long bytes) { }
/// <summary> /// <summary>
/// 以服务器模式接收数据 TCP /// 以服务器模式接收数据 TCP
@@ -113,7 +113,7 @@ namespace linker.messenger
/// <param name="sendFlag"></param> /// <param name="sendFlag"></param>
/// <param name="flag"></param> /// <param name="flag"></param>
/// <returns></returns> /// <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 try
{ {
@@ -230,7 +230,7 @@ namespace linker.messenger
//新的请求 //新的请求
requestWrap.FromArray(data); requestWrap.FromArray(data);
AddReceive(requestWrap.MessengerId, (ulong)data.Length); AddReceive(requestWrap.MessengerId, data.Length);
//404,没这个插件 //404,没这个插件
if (messengers.TryGetValue(requestWrap.MessengerId, out MessengerCacheInfo plugin) == false) if (messengers.TryGetValue(requestWrap.MessengerId, out MessengerCacheInfo plugin) == false)
{ {

View File

@@ -47,8 +47,8 @@ namespace linker.messenger
{ {
} }
public virtual void AddReceive(ushort id, ulong bytes) { } public virtual void AddReceive(ushort id, long bytes) { }
public virtual void AddSendt(ushort id, ulong bytes) { } public virtual void AddSendt(ushort id, long bytes) { }
public async Task<MessageResponeInfo> SendReply(MessageRequestWrap msg) public async Task<MessageResponeInfo> SendReply(MessageRequestWrap msg)
{ {
if (msg.Connection == null || msg.Connection.Connected == false) if (msg.Connection == null || msg.Connection.Connected == false)
@@ -105,7 +105,7 @@ namespace linker.messenger
byte[] bytes = msg.ToArray(out int length); 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); bool res = await msg.Connection.SendAsync(bytes.AsMemory(0, length)).ConfigureAwait(false);
msg.Return(bytes); msg.Return(bytes);
@@ -130,7 +130,7 @@ namespace linker.messenger
byte[] bytes = msg.ToArray(out int length); 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); bool res = await msg.Connection.SendAsync(bytes.AsMemory(0, length)).ConfigureAwait(false);
msg.Return(bytes); msg.Return(bytes);
@@ -151,7 +151,7 @@ namespace linker.messenger
byte[] bytes = new byte[wrap.Payload.Length]; byte[] bytes = new byte[wrap.Payload.Length];
wrap.Payload.CopyTo(bytes); 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 }); info.Tcs.SetResult(new MessageResponeInfo { Code = wrap.Code, Data = bytes, Connection = wrap.Connection });
} }
} }

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?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"/> <file name="main.aardio" path="main.aardio" comment="main.aardio"/>
<folder name="资源文件" path="res" embed="true" local="false" ignored="false"> <folder name="资源文件" path="res" embed="true" local="false" ignored="false">
<file name="favicon.ico" path="res\favicon.ico" comment="res\favicon.ico"/> <file name="favicon.ico" path="res\favicon.ico" comment="res\favicon.ico"/>

Binary file not shown.

View File

@@ -34,7 +34,7 @@ namespace linker.tunnel
private void LoopDiscovery() private void LoopDiscovery()
{ {
TimerHelper.SetInterval(() => TimerHelper.SetIntervalLong(() =>
{ {
NatUtility.StopDiscovery(); NatUtility.StopDiscovery();
NatUtility.StartDiscovery(); NatUtility.StartDiscovery();

View File

@@ -164,7 +164,8 @@ namespace linker.tunnel.transport
{ {
targetSocket.KeepAlive(); 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) if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{ {
@@ -218,7 +219,8 @@ namespace linker.tunnel.transport
try try
{ {
targetSocket.Ttl = ip.Address.AddressFamily == AddressFamily.InterNetworkV6 ? (short)2 : (short)(tunnelTransportInfo.Local.RouteLevel); 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); _ = targetSocket.ConnectAsync(ip);
return targetSocket; return targetSocket;
} }
@@ -315,15 +317,10 @@ namespace linker.tunnel.transport
private async Task StartListen(IPEndPoint local, TunnelTransportInfo tunnelTransportInfo) private async Task StartListen(IPEndPoint local, TunnelTransportInfo tunnelTransportInfo)
{ {
IPAddress localIP = tunnelTransportInfo.Local.LocalIps.Any(c => c.AddressFamily == AddressFamily.InterNetworkV6) IPAddress localIP = IPAddress.IPv6Any;
&& tunnelTransportInfo.Remote.LocalIps.Any(c => c.AddressFamily == AddressFamily.InterNetworkV6)
? IPAddress.IPv6Any : IPAddress.Any;
Socket socket = new Socket(localIP.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); Socket socket = new Socket(localIP.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
//socket.ReceiveBufferSize = 5 * 1024 * 1024; socket.IPv6Only(localIP.AddressFamily, false);
socket.ReuseBind(new IPEndPoint(localIP, local.Port));
//socket.IPv6Only(localIP.AddressFamily, false);
socket.Bind(new IPEndPoint(localIP, local.Port));
socket.Listen(int.MaxValue); socket.Listen(int.MaxValue);
try try

View File

@@ -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()))}"); 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) && tunnelTransportInfo.Local.LocalIps.Any(c => c.AddressFamily == AddressFamily.InterNetworkV6)
? new IPEndPoint(tunnelTransportInfo.Remote.LocalIps.FirstOrDefault(c=>c.AddressFamily == AddressFamily.InterNetworkV6), tunnelTransportInfo.Remote.Remote.Port) ? new IPEndPoint(tunnelTransportInfo.Remote.LocalIps.FirstOrDefault(c => c.AddressFamily == AddressFamily.InterNetworkV6), tunnelTransportInfo.Remote.Remote.Port)
: tunnelTransportInfo.Remote.Remote; : tunnelTransportInfo.Remote.Remote;
Socket targetSocket = new(ep.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); Socket targetSocket = new(ep.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
try try
{ {
targetSocket.KeepAlive(); 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) if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{ {

View File

@@ -314,7 +314,8 @@ namespace linker.tunnel.transport
try try
{ {
targetSocket.KeepAlive(); 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) if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{ {

View File

@@ -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()))}"); 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); 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) foreach (IPEndPoint ep in tunnelTransportInfo.RemoteEndPoints)
@@ -216,7 +215,9 @@ namespace linker.tunnel.transport
/// <returns></returns> /// <returns></returns>
private Socket BindListen(IPEndPoint local, TaskCompletionSource<IPEndPoint> tcs) 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 socket = new Socket(local.AddressFamily, SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp);
socket.IPv6Only(local.AddressFamily, false);
socket.WindowsUdpBug(); socket.WindowsUdpBug();
socket.ReuseBind(local); socket.ReuseBind(local);
@@ -238,9 +239,11 @@ namespace linker.tunnel.transport
/// <returns></returns> /// <returns></returns>
private async Task BindListen(IPEndPoint local, TunnelTransportInfo state) 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); Socket socket = new Socket(local.AddressFamily, SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp);
try try
{ {
socket.IPv6Only(local.AddressFamily,false);
socket.ReuseBind(local); socket.ReuseBind(local);
socket.WindowsUdpBug(); socket.WindowsUdpBug();
ListenAsyncToken token = new ListenAsyncToken ListenAsyncToken token = new ListenAsyncToken
@@ -267,7 +270,7 @@ namespace linker.tunnel.transport
try try
{ {
byte[] buffer = new byte[8 * 1024]; byte[] buffer = new byte[8 * 1024];
IPEndPoint ep = new IPEndPoint(IPAddress.Any, 0); IPEndPoint ep = new IPEndPoint(IPAddress.IPv6Any, 0);
while (true) while (true)
{ {
SocketReceiveFromResult result = await token.LocalUdp.ReceiveFromAsync(buffer, ep).ConfigureAwait(false); SocketReceiveFromResult result = await token.LocalUdp.ReceiveFromAsync(buffer, ep).ConfigureAwait(false);
@@ -306,7 +309,7 @@ namespace linker.tunnel.transport
/// <param name="tunnelTransportInfo"></param> /// <param name="tunnelTransportInfo"></param>
private void BindAndTTL(TunnelTransportInfo tunnelTransportInfo) 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) foreach (var ip in tunnelTransportInfo.RemoteEndPoints)
{ {
try try
@@ -316,15 +319,13 @@ namespace linker.tunnel.transport
LoggerHelper.Instance.Warning($"{Name} ttl to {tunnelTransportInfo.Remote.MachineId}->{tunnelTransportInfo.Remote.MachineName} {ip}"); 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.IPv6Only(local.AddressFamily, false);
Socket socket = new Socket(local.AddressFamily, SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp); socket.WindowsUdpBug();
socket.WindowsUdpBug(); socket.ReuseBind(local);
socket.ReuseBind(local); socket.Ttl = (short)(tunnelTransportInfo.Local.RouteLevel);
socket.Ttl = (short)(tunnelTransportInfo.Local.RouteLevel); _ = socket.SendToAsync(new byte[0], SocketFlags.None, ip);
_ = socket.SendToAsync(new byte[0], SocketFlags.None, ip); socket.SafeClose();
socket.SafeClose();
}
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@@ -314,7 +314,8 @@ namespace linker.tunnel.transport
try try
{ {
targetSocket.WindowsUdpBug(); 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) 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.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) if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Debug($"{Name} connect to {tunnelTransportInfo.Remote.MachineId}->{tunnelTransportInfo.Remote.MachineName} {ep} success"); 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() 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(); 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) foreach (var item in keys)

View File

@@ -11,6 +11,7 @@
"@element-plus/icons-vue": "^2.3.1", "@element-plus/icons-vue": "^2.3.1",
"core-js": "^3.38.0", "core-js": "^3.38.0",
"element-plus": "^2.8.0", "element-plus": "^2.8.0",
"moment": "^2.30.1",
"vue": "^3.4.38", "vue": "^3.4.38",
"vue-i18n": "^11.0.1", "vue-i18n": "^11.0.1",
"vue-router": "^4.4.3" "vue-router": "^4.4.3"
@@ -6792,6 +6793,14 @@
"dev": true, "dev": true,
"license": "MIT" "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": { "node_modules/mrmime": {
"version": "2.0.0", "version": "2.0.0",
"dev": true, "dev": true,

View File

@@ -10,6 +10,7 @@
"@element-plus/icons-vue": "^2.3.1", "@element-plus/icons-vue": "^2.3.1",
"core-js": "^3.38.0", "core-js": "^3.38.0",
"element-plus": "^2.8.0", "element-plus": "^2.8.0",
"moment": "^2.30.1",
"vue": "^3.4.38", "vue": "^3.4.38",
"vue-i18n": "^11.0.1", "vue-i18n": "^11.0.1",
"vue-router": "^4.4.3" "vue-router": "^4.4.3"

View 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

View 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

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@@ -12,3 +12,12 @@ export const relayConnect = (data) => {
export const relayCdkeyAccess = () => { export const relayCdkeyAccess = () => {
return sendWebsocketMsg('relay/AccessCdkey'); 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);
}

View File

@@ -11,7 +11,6 @@ export default {
'head.home': 'Home', 'head.home': 'Home',
'head.server': 'Server', 'head.server': 'Server',
'head.group': 'Group',
'head.protocol': 'P2P Protocol', 'head.protocol': 'P2P Protocol',
'head.action': 'Action', 'head.action': 'Action',
'head.logger': 'Logs', 'head.logger': 'Logs',
@@ -38,13 +37,19 @@ export default {
'server.messengerSecretKey': 'Messenger SecretKey', 'server.messengerSecretKey': 'Messenger SecretKey',
'server.messengerSecretKeyText': 'Messenger SecretKey', 'server.messengerSecretKeyText': 'Messenger SecretKey',
'server.messengerUserId': 'User Id', '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.closed': 'Closed',
'permission.simple': 'Simple', 'permission.simple': 'Simple',
'permission.full': 'Full', 'permission.full': 'Full',
'permission.clear': 'Clear connection', '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.support': 'Support',
'status.export': 'Export', 'status.export': 'Export',
'status.exportText': 'Export the configuration to run elsewhere', 'status.exportText': 'Export the configuration to run elsewhere',
@@ -126,6 +131,24 @@ export default {
'server.relayMyCdkey': 'My CDKEY', 'server.relayMyCdkey': 'My CDKEY',
'server.relayCdkey': 'Manager 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.sforwardSecretKey': 'Server forward secretKey',
'server.sforwardText': 'The server forward can be used when the key is correct', 'server.sforwardText': 'The server forward can be used when the key is correct',
@@ -139,11 +162,6 @@ export default {
'server.updaterMM': 'Minute', 'server.updaterMM': 'Minute',
'server.updaterS': 'Second', '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.asyncText': 'Synchronize to all clients',
'server.asyncSelect': 'Please select', 'server.asyncSelect': 'Please select',
'server.asyncCheckAll': 'Check all', 'server.asyncCheckAll': 'Check all',

View File

@@ -37,13 +37,19 @@ export default {
'server.messengerSecretKey': '信标密钥', 'server.messengerSecretKey': '信标密钥',
'server.messengerSecretKeyText': '密钥正确时可连接服务器', 'server.messengerSecretKeyText': '密钥正确时可连接服务器',
'server.messengerUserId': '用户id', 'server.messengerUserId': '用户id',
'server.messengerUserIdText': '你的唯一标识,用于流量卡密CDKEY', 'server.messengerUserIdText': '你的唯一标识,用于解锁一些限制',
'permission.closed': '禁止通行', 'permission.closed': '禁止通行',
'permission.simple': '简单管理', 'permission.simple': '简单管理',
'permission.full': '专业管理', 'permission.full': '专业管理',
'permission.clear': '清除连接', 'permission.clear': '清除连接',
'status.group': '管理分组',
'status.groupName': '名称',
'status.groupPassword': '密码',
'status.groupOper': '操作',
'status.groupDelConfirm': '确认删除吗?',
'status.support': '赞助', 'status.support': '赞助',
'status.export': '导出配置', 'status.export': '导出配置',
@@ -128,6 +134,23 @@ export default {
'server.relayMyCdkey': '我的CDKEY', 'server.relayMyCdkey': '我的CDKEY',
'server.relayCdkey': '管理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.sforwardSecretKey': '服务器穿透密钥',
'server.sforwardText': '当密钥正确是可用', 'server.sforwardText': '当密钥正确是可用',
@@ -141,10 +164,7 @@ export default {
'server.updaterMM': '分', 'server.updaterMM': '分',
'server.updaterS': '秒', 'server.updaterS': '秒',
'server.groupName': '名称',
'server.groupPassword': '密码',
'server.groupOper': '操作',
'server.groupDelConfirm': '确认删除吗?',
'server.asyncText': '同步到所有客户端', 'server.asyncText': '同步到所有客户端',
'server.asyncSelect': '请选择', 'server.asyncSelect': '请选择',

View File

@@ -16,11 +16,6 @@ const routes = [
name: 'FullServers', name: 'FullServers',
component: () => import('@/views/full/server/Index.vue') component: () => import('@/views/full/server/Index.vue')
}, },
{
path: '/full/group.html',
name: 'FullGroup',
component: () => import('@/views/full/group/Index.vue')
},
{ {
path: '/full/transport.html', path: '/full/transport.html',
name: 'FullTransport', name: 'FullTransport',

View File

@@ -14,9 +14,6 @@
<li v-if="hasConfig"> <li v-if="hasConfig">
<router-link :to="{name:'FullServers'}"><img src="@/assets/fuwuqi.svg"/> {{$t('head.server')}}</router-link> <router-link :to="{name:'FullServers'}"><img src="@/assets/fuwuqi.svg"/> {{$t('head.server')}}</router-link>
</li> </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"> <li v-if="hasTransport">
<router-link :to="{name:'FullTransport'}"><img src="@/assets/dadong.svg"/> {{$t('head.protocol')}}</router-link> <router-link :to="{name:'FullTransport'}"><img src="@/assets/dadong.svg"/> {{$t('head.protocol')}}</router-link>
</li> </li>

View File

@@ -9,11 +9,17 @@
class="system" class="system"
:src="`https://unpkg.com/flag-icons@7.2.3/flags/4x3/${tunnel.list[scope.row.MachineId].Net.CountryCode.toLowerCase()}.svg`" /> :src="`https://unpkg.com/flag-icons@7.2.3/flags/4x3/${tunnel.list[scope.row.MachineId].Net.CountryCode.toLowerCase()}.svg`" />
</template> </template>
<template v-else>
<img title="?" class="system" src="/system.svg" />
</template>
<template v-if="tunnel.list[scope.row.MachineId].Net.Isp"> <template v-if="tunnel.list[scope.row.MachineId].Net.Isp">
<img <img
:title="`${tunnel.list[scope.row.MachineId].Net.Isp}、${tunnel.list[scope.row.MachineId].Net.Org}、${tunnel.list[scope.row.MachineId].Net.As}`" :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)" /> class="system" :src="netImg(tunnel.list[scope.row.MachineId].Net)" />
</template> </template>
<template v-else>
<img title="?" class="system" src="/system.svg" />
</template>
</div> </div>
<div class="flex"> <div class="flex">
<a href="javascript:;" class="a-line" <a href="javascript:;" class="a-line"
@@ -67,11 +73,16 @@ export default {
'china telecom':'chinanet.svg', 'china telecom':'chinanet.svg',
'china unicom':'chinaunicom.svg', 'china unicom':'chinaunicom.svg',
'china mobile':'chinamobile.svg', 'china mobile':'chinamobile.svg',
'huawei':'huawei.svg',
'amazon':'amazon.svg',
'aliyun':'aliyun.svg',
} }
const netImg = (item)=>{ const netImg = (item)=>{
const isp = item.Isp.toLowerCase();
const org = item.Org.toLowerCase();
const as = item.As.toLowerCase(); const as = item.As.toLowerCase();
for(let j in imgMap){ 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]}`; return `./${imgMap[j]}`;
} }
} }
@@ -121,7 +132,7 @@ export default {
img.system{ img.system{
height:1.4rem; height:1.4rem;
vertical-align:middle;
margin-right:.4rem margin-right:.4rem
border: 1px solid #eee;
} }
</style> </style>

View File

@@ -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}"> <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}} {{$t('server.relayNodes')}} : {{state.nodes.length}}
</a> </a>
<Relay></Relay> <RelayCdkey></RelayCdkey>
</div> </div>
</el-form-item> </el-form-item>
@@ -68,9 +68,9 @@ import { ElMessage } from 'element-plus';
import { onMounted, onUnmounted, reactive, watch } from 'vue' import { onMounted, onUnmounted, reactive, watch } from 'vue'
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import Sync from '../sync/Index.vue' import Sync from '../sync/Index.vue'
import Relay from './relay/Index.vue' import RelayCdkey from './relayCdkey/Index.vue'
export default { export default {
components:{Sync,Relay}, components:{Sync,RelayCdkey},
setup(props) { setup(props) {
const {t} = useI18n(); const {t} = useI18n();
const globalData = injectGlobalData(); const globalData = injectGlobalData();

View File

@@ -1,25 +1,29 @@
<template> <template>
<a href="javascript:;" class="mgl-1 a-line">{{$t('server.relayMyCdkey')}}</a> <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> </template>
<script> <script>
import { relayCdkeyAccess } from '@/apis/relay'; import { relayCdkeyAccess } from '@/apis/relay';
import { injectGlobalData } from '@/provide'; import { injectGlobalData } from '@/provide';
import { computed, onMounted, reactive } from 'vue'; import { computed, onMounted, reactive } from 'vue';
import Manager from './Manager.vue'
export default { export default {
components:{Manager},
setup () { setup () {
const globalData = injectGlobalData(); const globalData = injectGlobalData();
const hasRelayCdkey = computed(()=>globalData.value.hasAccess('RelayCdkey')); const hasRelayCdkey = computed(()=>globalData.value.hasAccess('RelayCdkey'));
const state = reactive({ const state = reactive({
showManager:false hasRelayCdkey:false,
showManager:false,
showList:false,
}); });
onMounted(()=>{ onMounted(()=>{
relayCdkeyAccess().then(res=>{ relayCdkeyAccess().then(res=>{
state.showManager = res; state.hasRelayCdkey = res;
}).catch(()=>{}) }).catch(()=>{})
}) })

View 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>

View File

@@ -1,7 +1,8 @@
<template> <template>
<div class="group-wrap"> <el-dialog class="options-center" :title="$t('status.group')" destroy-on-close v-model="state.show" width="77rem" top="2vh">
<el-table stripe :data="state.list" border size="small" width="100%" :height="`${state.height}px`" @cell-dblclick="handleCellClick"> <div class="group-wrap">
<el-table-column prop="Name" :label="$t('server.groupName')" width="100"> <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 #default="scope">
<template v-if="scope.row.NameEditing"> <template v-if="scope.row.NameEditing">
<el-input autofocus size="small" v-model="scope.row.Name" <el-input autofocus size="small" v-model="scope.row.Name"
@@ -23,7 +24,7 @@
</template> </template>
</template> </template>
</el-table-column> </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 #default="scope">
<template v-if="scope.row.PasswordEditing"> <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> <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 v-else>{{ scope.row.Password.replace(/.{1}/g,'*') }}</template>
</template> </template>
</el-table-column> </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> <template #header>
<div class="flex"> <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> </div>
</template> </template>
<template #default="scope"> <template #default="scope">
<div> <div>
<el-popconfirm :title="$t('server.groupDelConfirm')" @confirm="handleDel(scope.$index)"> <el-popconfirm :title="$t('status.groupDelConfirm')" @confirm="handleDel(scope.$index)">
<template #reference> <template #reference>
<el-button type="danger" size="small"> <el-button type="danger" size="small">
<el-icon><Delete /></el-icon> <el-icon><Delete /></el-icon>
@@ -49,15 +50,17 @@
<el-button size="small" @click="handleAdd(scope.$index)"> <el-button size="small" @click="handleAdd(scope.$index)">
<el-icon><Plus /></el-icon> <el-icon><Plus /></el-icon>
</el-button> </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-icon><Select /></el-icon>
</el-button> </el-button> -->
</div> </div>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
</div> </div>
</el-dialog>
</template> </template>
<script> <script>
import { setSignIn, setSignInGroups } from '@/apis/signin'; import { setSignIn, setSignInGroups } from '@/apis/signin';
import { injectGlobalData } from '@/provide'; import { injectGlobalData } from '@/provide';
@@ -65,21 +68,30 @@ import { ElMessage } from 'element-plus';
import { computed, reactive, watch } from 'vue' import { computed, reactive, watch } from 'vue'
import { Delete,Plus,Select } from '@element-plus/icons-vue'; import { Delete,Plus,Select } from '@element-plus/icons-vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import Sync from '../sync/Index.vue' import Sync from '../../sync/Index.vue'
export default { export default {
props: ['modelValue'],
emits: ['update:modelValue'],
components:{Delete,Plus,Select,Sync }, components:{Delete,Plus,Select,Sync },
setup(props) { setup(props,{emit}) {
const {t} = useI18n(); const {t} = useI18n();
const globalData = injectGlobalData(); const globalData = injectGlobalData();
const state = reactive({ const state = reactive({
list:globalData.value.config.Client.Groups || [], list:globalData.value.config.Client.Groups || [],
height: computed(()=>globalData.value.height-70), show:true
}); });
watch(()=>globalData.value.config.Client.Groups,()=>{ watch(()=>globalData.value.config.Client.Groups,()=>{
if(state.list.filter(c=>c['__editing']).length == 0){ if(state.list.filter(c=>c['__editing']).length == 0){
state.list = globalData.value.config.Client.Groups; state.list = globalData.value.config.Client.Groups;
} }
}) });
watch(() => state.show, (val) => {
if (!val) {
setTimeout(() => {
emit('update:modelValue', val);
}, 300);
}
});
const handleCellClick = (row, column) => { const handleCellClick = (row, column) => {
handleEdit(row, column.property); handleEdit(row, column.property);
@@ -143,5 +155,4 @@ export default {
} }
</script> </script>
<style lang="stylus" scoped> <style lang="stylus" scoped>
.group-wrap{padding:1rem}
</style> </style>

View File

@@ -1,78 +1,59 @@
<template> <template>
<a href="javascript:;" :class="{connected:state.connected}" :title="$t('status.messengerChange')" @click="handleConfig"> <el-dropdown>
<el-icon size="16"><Promotion /></el-icon> <span>{{$t('status.messenger')}}</span> <span class="el-dropdown-link" :class="{connected:state.connected}">
</a> <el-icon><Avatar /></el-icon>
<el-dialog v-model="state.show" :title="$t('common.setting')" width="300" append-to-body> {{state.groupName}}
<div> <el-icon><ArrowDown /></el-icon>
<el-form :model="state.form" :rules="state.rules" label-width="6rem"> </span>
<el-form-item :label="$t('status.messengerName')" prop="name" v-if="hasRenameSelf"> <template #dropdown>
<el-input v-model="state.form.name" maxlength="32" show-word-limit /> <el-dropdown-menu v-if="hasGroup">
</el-form-item> <el-dropdown-item v-for="item in state.groups" @click="handleGroupChange(item.Id)">{{item.Name}}</el-dropdown-item>
<el-form-item :label="$t('status.messengerGroup')" prop="groupid" v-if="hasGroup"> <el-dropdown-item @click="state.showGroups = true">{{$t('status.group')}}</el-dropdown-item>
<el-select v-model="state.groupid" @change="handleGroupChange"> </el-dropdown-menu>
<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>
</template> </template>
</el-dialog> </el-dropdown>
<Groups v-if="state.showGroups" v-model="state.showGroups"></Groups>
</template> </template>
<script> <script>
import { setSignIn } from '@/apis/signin'; import { setSignIn } from '@/apis/signin';
import { injectGlobalData } from '@/provide'; import { injectGlobalData } from '@/provide';
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import { computed, reactive, ref } from 'vue'; 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 { useI18n } from 'vue-i18n';
import Groups from './Groups.vue';
export default { export default {
components:{Promotion,CirclePlus}, components:{ArrowDown,Avatar,Groups},
props:['config'], props:['config'],
setup(props) { setup(props) {
const { t } = useI18n(); const { t } = useI18n();
const globalData = injectGlobalData(); const globalData = injectGlobalData();
const hasRenameSelf = computed(()=>globalData.value.hasAccess('RenameSelf'));
const hasGroup = computed(()=>globalData.value.hasAccess('Group')); const hasGroup = computed(()=>globalData.value.hasAccess('Group'));
const state = reactive({ const state = reactive({
show: false,
loading: false, loading: false,
connected: computed(() => globalData.value.signin.Connected), connected: computed(() => globalData.value.signin.Connected),
groupid: globalData.value.config.Client.Group.Id, groupName: globalData.value.config.Client.Group.Name,
form: { groups: globalData.value.config.Client.Groups.slice(),
name: globalData.value.config.Client.Name, showGroups:false
groups: globalData.value.config.Client.Groups,
},
rules: {},
}); });
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 handleGroupChange = (value)=>{
const index = state.form.groups.map((item,index)=>{
const index = state.groups.map((item,index)=>{
item.$index = index; item.$index = index;
return item; return item;
}).filter(c=>c.Id == value)[0].$index; }).filter(c=>c.Id == value)[0].$index;
const temp = state.form.groups[index]; const temp = state.groups[index];
state.form.groups[index] = state.form.groups[0]; state.groups[index] = state.groups[0];
state.form.groups[0] = temp; state.groups[0] = temp;
handleSave();
} }
const handleSave = () => { const handleSave = () => {
state.loading = true; state.loading = true;
setSignIn(state.form).then(() => { setSignIn({
Name:globalData.value.config.Client.Name,
Groups:state.groups,
}).then(() => {
state.loading = false; state.loading = false;
state.show = false; state.show = false;
ElMessage.success(t('common.oper')); ElMessage.success(t('common.oper'));
@@ -86,21 +67,17 @@ export default {
}); });
} }
return { return {
config:props.config,hasRenameSelf,hasGroup, state, handleConfig, handleSave,handleGroupChange config:props.config,hasGroup, state,handleGroupChange
} }
} }
} }
</script> </script>
<style lang="stylus" scoped> <style lang="stylus" scoped>
a{ .el-dropdown{vertical-align: inherit;margin-right:1rem}
a{color:#333;} .connected {
a{margin-left:.6rem;}
&.connected {
color:green;font-weight:bold; color:green;font-weight:bold;
} }
.el-icon{ .el-icon{
vertical-align:text-bottom; vertical-align:bottom;
} }
}
</style> </style>

View File

@@ -23,11 +23,12 @@
<Description>1. 优化linux下路由跟踪问题 <Description>1. 优化linux下路由跟踪问题
2. 优化linux下获取本机IP问题 2. 优化linux下获取本机IP问题
3. 增加ICS让win7+、win server2008+支持NAT 3. 增加ICS让win7+、win server2008+支持NAT
4. 增加中继卡密 4. 增加中继cdkey使用cdkey解锁公开中继节点的带宽、流量、连接数限制
5. 增加内外穿透定时开关功能 5. 增加内外穿透定时开关功能
6. 优化管理页面连接接口的体验 6. 优化管理页面连接接口的体验
7. 优化一些UI体验去除同步页面将同步功能放各个实际的位置 7. 优化一些UI体验去除同步页面将同步功能放各个实际的位置
8. 其它一些修复优化</Description> 8. 优化端口转发,让不同分组间可以使用相同端口
9. 其它一些修复优化</Description>
<Copyright>snltty</Copyright> <Copyright>snltty</Copyright>
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl> <PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl> <RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>

View File

@@ -1,10 +1,11 @@
v1.6.9 v1.6.9
2025-03-03 17:44:29 2025-03-06 21:15:19
1. 优化linux下路由跟踪问题 1. 优化linux下路由跟踪问题
2. 优化linux下获取本机IP问题 2. 优化linux下获取本机IP问题
3. 增加ICS让win7+、win server2008+支持NAT 3. 增加ICS让win7+、win server2008+支持NAT
4. 增加中继卡密 4. 增加中继cdkey使用cdkey解锁公开中继节点的带宽、流量、连接数限制
5. 增加内外穿透定时开关功能 5. 增加内外穿透定时开关功能
6. 优化管理页面连接接口的体验 6. 优化管理页面连接接口的体验
7. 优化一些UI体验去除同步页面将同步功能放各个实际的位置 7. 优化一些UI体验去除同步页面将同步功能放各个实际的位置
8. 其它一些修复优化 8. 优化端口转发,让不同分组间可以使用相同端口
9. 其它一些修复优化