mirror of
https://github.com/snltty/linker.git
synced 2025-12-18 01:16:46 +08:00
重构中继
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
v1.9.6
|
v1.9.6
|
||||||
2025-12-03 21:17:12
|
2025-12-04 17:55:01
|
||||||
1. 一些累计更新,一些BUG修复
|
1. 一些累计更新,一些BUG修复
|
||||||
2. 优化客户端数据同步,减少服务器流量
|
2. 优化客户端数据同步,减少服务器流量
|
||||||
3. 去除cdkey,改为发电解锁中继速度
|
3. 去除cdkey,改为发电解锁中继速度
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ sidebar_position: 1
|
|||||||
|
|
||||||
:::tip[说明]
|
:::tip[说明]
|
||||||
|
|
||||||
#### 1.2、加入组织
|
#### 1.2、一起探讨
|
||||||
|
|
||||||
<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>
|
||||||
|
|
||||||
@@ -16,6 +16,9 @@ sidebar_position: 1
|
|||||||
|
|
||||||
简单视频说明:<a href="https://www.bilibili.com/video/BV1PDpxz9EcW" target="_blank">B站视频</a>
|
简单视频说明:<a href="https://www.bilibili.com/video/BV1PDpxz9EcW" target="_blank">B站视频</a>
|
||||||
|
|
||||||
|
|
||||||
|
<div style={{color:'red',fontSize:'20px'}}>郑重声明:linker的目标是完全自由、受控,不是傻瓜式工具,需要具备一定的入手基础。</div>
|
||||||
|
|
||||||
--
|
--
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|||||||
@@ -162,6 +162,19 @@ namespace linker.messenger.api
|
|||||||
Socks5Flow = 51,
|
Socks5Flow = 51,
|
||||||
[AccessDisplay("查看隧道流量")]
|
[AccessDisplay("查看隧道流量")]
|
||||||
TunnelFlow = 52,
|
TunnelFlow = 52,
|
||||||
|
|
||||||
|
[AccessDisplay("导入中继节点")]
|
||||||
|
ImportRelayNode = 53,
|
||||||
|
[AccessDisplay("删除中继节点")]
|
||||||
|
RemoveRelayNode = 54,
|
||||||
|
[AccessDisplay("修改中继节点")]
|
||||||
|
UpdateRelayNode = 55,
|
||||||
|
[AccessDisplay("分享中继节点")]
|
||||||
|
ShareRelayNode = 56,
|
||||||
|
[AccessDisplay("重启中继节点")]
|
||||||
|
RebootRelayNode = 57,
|
||||||
|
[AccessDisplay("更新中继节点")]
|
||||||
|
UpgradeRelayNode = 58,
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class AccessTextInfo
|
public sealed class AccessTextInfo
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ namespace linker.messenger.relay.client
|
|||||||
{
|
{
|
||||||
relayClientStore.SetDefaultNodeId(info.Data.Key);
|
relayClientStore.SetDefaultNodeId(info.Data.Key);
|
||||||
relayClientStore.SetDefaultProtocol(info.Data.Value);
|
relayClientStore.SetDefaultProtocol(info.Data.Value);
|
||||||
|
relayClientStore.Confirm();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +71,8 @@ namespace linker.messenger.relay.client
|
|||||||
var resp = await messengerSender.SendReply(new MessageRequestWrap
|
var resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||||
{
|
{
|
||||||
Connection = signInClientState.Connection,
|
Connection = signInClientState.Connection,
|
||||||
MessengerId = (ushort)RelayMessengerIds.Share,
|
MessengerId = (ushort)RelayMessengerIds.ShareForward,
|
||||||
|
Payload = serializer.Serialize(param.Content)
|
||||||
});
|
});
|
||||||
return resp.Code == MessageResponeCodes.OK ? serializer.Deserialize<string>(resp.Data.Span) : $"network error:{resp.Code}";
|
return resp.Code == MessageResponeCodes.OK ? serializer.Deserialize<string>(resp.Data.Span) : $"network error:{resp.Code}";
|
||||||
}
|
}
|
||||||
@@ -90,10 +92,44 @@ namespace linker.messenger.relay.client
|
|||||||
{
|
{
|
||||||
Connection = signInClientState.Connection,
|
Connection = signInClientState.Connection,
|
||||||
MessengerId = (ushort)RelayMessengerIds.Remove,
|
MessengerId = (ushort)RelayMessengerIds.Remove,
|
||||||
Payload = serializer.Serialize(int.Parse(param.Content))
|
Payload = serializer.Serialize(param.Content)
|
||||||
});
|
});
|
||||||
return resp.Code == MessageResponeCodes.OK ? serializer.Deserialize<string>(resp.Data.Span) : $"network error:{resp.Code}";
|
return resp.Code == MessageResponeCodes.OK ? serializer.Deserialize<string>(resp.Data.Span) : $"network error:{resp.Code}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<bool> Update(ApiControllerParamsInfo param)
|
||||||
|
{
|
||||||
|
var resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||||
|
{
|
||||||
|
Connection = signInClientState.Connection,
|
||||||
|
MessengerId = (ushort)RelayMessengerIds.UpdateForward,
|
||||||
|
Payload = serializer.Serialize(param.Content.DeJson<RelayServerNodeStoreInfo>())
|
||||||
|
});
|
||||||
|
return resp.Code == MessageResponeCodes.OK && resp.Data.Span.SequenceEqual(Helper.TrueArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> Upgrade(ApiControllerParamsInfo param)
|
||||||
|
{
|
||||||
|
KeyValueInfo<string, string> info = param.Content.DeJson<KeyValueInfo<string, string>>();
|
||||||
|
|
||||||
|
var resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||||
|
{
|
||||||
|
Connection = signInClientState.Connection,
|
||||||
|
MessengerId = (ushort)RelayMessengerIds.UpgradeForward,
|
||||||
|
Payload = serializer.Serialize(new KeyValuePair<string, string>(info.Key, info.Value))
|
||||||
|
});
|
||||||
|
return resp.Code == MessageResponeCodes.OK && resp.Data.Span.SequenceEqual(Helper.TrueArray);
|
||||||
|
}
|
||||||
|
public async Task<bool> Exit(ApiControllerParamsInfo param)
|
||||||
|
{
|
||||||
|
var resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||||
|
{
|
||||||
|
Connection = signInClientState.Connection,
|
||||||
|
MessengerId = (ushort)RelayMessengerIds.ExitForward,
|
||||||
|
Payload = serializer.Serialize(param.Content)
|
||||||
|
});
|
||||||
|
return resp.Code == MessageResponeCodes.OK && resp.Data.Span.SequenceEqual(Helper.TrueArray);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -13,8 +13,39 @@ namespace linker.messenger.relay.messenger
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class RelayClientMessenger : IMessenger
|
public class RelayClientMessenger : IMessenger
|
||||||
{
|
{
|
||||||
public RelayClientMessenger()
|
private readonly ISerializer serializer;
|
||||||
|
private readonly RelayServerNodeReportTransfer relayServerNodeReportTransfer;
|
||||||
|
public RelayClientMessenger(SignInServerCaching signCaching, ISerializer serializer, RelayServerNodeReportTransfer relayServerNodeReportTransfer)
|
||||||
{
|
{
|
||||||
|
this.serializer = serializer;
|
||||||
|
this.relayServerNodeReportTransfer = relayServerNodeReportTransfer;
|
||||||
|
}
|
||||||
|
[MessengerId((ushort)RelayMessengerIds.Share)]
|
||||||
|
public async Task Share(IConnection connection)
|
||||||
|
{
|
||||||
|
string masterKey = serializer.Deserialize<string>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
|
connection.Write(serializer.Serialize(await relayServerNodeReportTransfer.GetShareKey(masterKey)));
|
||||||
|
}
|
||||||
|
|
||||||
|
[MessengerId((ushort)RelayMessengerIds.Update)]
|
||||||
|
public async Task Update(IConnection connection)
|
||||||
|
{
|
||||||
|
RelayServerNodeStoreInfo info = serializer.Deserialize<RelayServerNodeStoreInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
|
await relayServerNodeReportTransfer.Update(info).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MessengerId((ushort)RelayMessengerIds.Upgrade)]
|
||||||
|
public async Task Upgrade(IConnection connection)
|
||||||
|
{
|
||||||
|
KeyValuePair<string, string> info = serializer.Deserialize<KeyValuePair<string, string>>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
|
await relayServerNodeReportTransfer.Upgrade(info.Key, info.Value).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MessengerId((ushort)RelayMessengerIds.Exit)]
|
||||||
|
public async Task Exit(IConnection connection)
|
||||||
|
{
|
||||||
|
string masterKey = serializer.Deserialize<string>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
|
await relayServerNodeReportTransfer.Exit(masterKey).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,15 +154,16 @@ namespace linker.messenger.relay.messenger
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[MessengerId((ushort)RelayMessengerIds.Share)]
|
[MessengerId((ushort)RelayMessengerIds.ShareForward)]
|
||||||
public async Task Share(IConnection connection)
|
public async Task ShareForward(IConnection connection)
|
||||||
{
|
{
|
||||||
|
string id = serializer.Deserialize<string>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
if (signCaching.TryGet(connection.Id, out SignCacheInfo from) == false || from.Super == false)
|
if (signCaching.TryGet(connection.Id, out SignCacheInfo from) == false || from.Super == false)
|
||||||
{
|
{
|
||||||
connection.Write(serializer.Serialize("need super key"));
|
connection.Write(serializer.Serialize("need super key"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
connection.Write(serializer.Serialize(relayServerNodeReportTransfer.Config.ShareKey));
|
connection.Write(serializer.Serialize(await relayServerNodeReportTransfer.GetShareKeyForward(id)));
|
||||||
}
|
}
|
||||||
[MessengerId((ushort)RelayMessengerIds.Import)]
|
[MessengerId((ushort)RelayMessengerIds.Import)]
|
||||||
public async Task Import(IConnection connection)
|
public async Task Import(IConnection connection)
|
||||||
@@ -150,7 +182,7 @@ namespace linker.messenger.relay.messenger
|
|||||||
[MessengerId((ushort)RelayMessengerIds.Remove)]
|
[MessengerId((ushort)RelayMessengerIds.Remove)]
|
||||||
public async Task Remove(IConnection connection)
|
public async Task Remove(IConnection connection)
|
||||||
{
|
{
|
||||||
int id = serializer.Deserialize<int>(connection.ReceiveRequestWrap.Payload.Span);
|
string id = serializer.Deserialize<string>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
if (signCaching.TryGet(connection.Id, out SignCacheInfo from) == false || from.Super == false)
|
if (signCaching.TryGet(connection.Id, out SignCacheInfo from) == false || from.Super == false)
|
||||||
{
|
{
|
||||||
connection.Write(serializer.Serialize("need super key"));
|
connection.Write(serializer.Serialize("need super key"));
|
||||||
@@ -160,7 +192,47 @@ namespace linker.messenger.relay.messenger
|
|||||||
bool result = await relayServerNodeReportTransfer.Remove(id).ConfigureAwait(false);
|
bool result = await relayServerNodeReportTransfer.Remove(id).ConfigureAwait(false);
|
||||||
connection.Write(serializer.Serialize(result ? string.Empty : "remove fail"));
|
connection.Write(serializer.Serialize(result ? string.Empty : "remove fail"));
|
||||||
}
|
}
|
||||||
|
[MessengerId((ushort)RelayMessengerIds.UpdateForward)]
|
||||||
|
public async Task UpdateForward(IConnection connection)
|
||||||
|
{
|
||||||
|
RelayServerNodeStoreInfo info = serializer.Deserialize<RelayServerNodeStoreInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
|
if (signCaching.TryGet(connection.Id, out SignCacheInfo from) == false || from.Super == false)
|
||||||
|
{
|
||||||
|
connection.Write(Helper.FalseArray);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool result = await relayServerNodeReportTransfer.UpdateForward(info).ConfigureAwait(false);
|
||||||
|
connection.Write(result ? Helper.TrueArray : Helper.FalseArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MessengerId((ushort)RelayMessengerIds.UpgradeForward)]
|
||||||
|
public async Task UpgradeForward(IConnection connection)
|
||||||
|
{
|
||||||
|
KeyValuePair<string, string> info = serializer.Deserialize<KeyValuePair<string, string>>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
|
if (signCaching.TryGet(connection.Id, out SignCacheInfo from) == false || from.Super == false)
|
||||||
|
{
|
||||||
|
connection.Write(Helper.FalseArray);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool result = await relayServerNodeReportTransfer.UpgradeForward(info.Key, info.Value).ConfigureAwait(false);
|
||||||
|
connection.Write(result ? Helper.TrueArray : Helper.FalseArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MessengerId((ushort)RelayMessengerIds.ExitForward)]
|
||||||
|
public async Task ExitForward(IConnection connection)
|
||||||
|
{
|
||||||
|
string nodeid = serializer.Deserialize<string>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
|
if (signCaching.TryGet(connection.Id, out SignCacheInfo from) == false || from.Super == false)
|
||||||
|
{
|
||||||
|
connection.Write(Helper.FalseArray);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool result = await relayServerNodeReportTransfer.ExitForward(nodeid).ConfigureAwait(false);
|
||||||
|
connection.Write(result ? Helper.TrueArray : Helper.FalseArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
[MessengerId((ushort)RelayMessengerIds.NodeReport)]
|
[MessengerId((ushort)RelayMessengerIds.NodeReport)]
|
||||||
|
|||||||
@@ -15,9 +15,18 @@
|
|||||||
Report = 2135,
|
Report = 2135,
|
||||||
|
|
||||||
Share = 2136,
|
Share = 2136,
|
||||||
Import = 2137,
|
ShareForward = 2137,
|
||||||
Remove = 2138,
|
Import = 2138,
|
||||||
|
Remove = 2139,
|
||||||
|
|
||||||
|
UpdateForward = 2140,
|
||||||
|
Update = 2141,
|
||||||
|
|
||||||
|
ExitForward = 2142,
|
||||||
|
Exit = 2143,
|
||||||
|
|
||||||
|
UpgradeForward = 2144,
|
||||||
|
Upgrade = 2145,
|
||||||
|
|
||||||
Max = 2199
|
Max = 2199
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,6 +74,8 @@ namespace linker.messenger.relay.server
|
|||||||
public double BandwidthRatio { get; set; }
|
public double BandwidthRatio { get; set; }
|
||||||
|
|
||||||
public IPEndPoint[] Masters { get; set; } = Array.Empty<IPEndPoint>();
|
public IPEndPoint[] Masters { get; set; } = Array.Empty<IPEndPoint>();
|
||||||
|
|
||||||
|
public string Domain { get; set; } = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class RelayServerNodeStoreInfo : RelayServerNodeReportInfo
|
public sealed class RelayServerNodeStoreInfo : RelayServerNodeReportInfo
|
||||||
|
|||||||
@@ -6,7 +6,8 @@
|
|||||||
public Task<RelayServerNodeStoreInfo> GetByNodeId(string nodeId);
|
public Task<RelayServerNodeStoreInfo> GetByNodeId(string nodeId);
|
||||||
public Task<bool> Add(RelayServerNodeStoreInfo info);
|
public Task<bool> Add(RelayServerNodeStoreInfo info);
|
||||||
public Task<bool> Report(RelayServerNodeReportInfo info);
|
public Task<bool> Report(RelayServerNodeReportInfo info);
|
||||||
public Task<bool> Delete(int id);
|
public Task<bool> Delete(string nodeId);
|
||||||
|
public Task<bool> Update(RelayServerNodeStoreInfo info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using linker.libs.extends;
|
using linker.libs.extends;
|
||||||
using linker.libs.timer;
|
using linker.libs.timer;
|
||||||
using linker.messenger.relay.messenger;
|
using linker.messenger.relay.messenger;
|
||||||
|
using System;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
|
||||||
@@ -93,6 +94,32 @@ namespace linker.messenger.relay.server
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<string> GetShareKeyForward(string nodeId)
|
||||||
|
{
|
||||||
|
RelayServerNodeStoreInfo store = await relayServerNodeStore.GetByNodeId(nodeId);
|
||||||
|
|
||||||
|
if (store != null && store.Manageable && relayServerConnectionTransfer.TryGet(ConnectionSideType.Node, nodeId, out var connection))
|
||||||
|
{
|
||||||
|
var resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||||
|
{
|
||||||
|
Connection = connection,
|
||||||
|
MessengerId = (ushort)RelayMessengerIds.Share,
|
||||||
|
Payload = serializer.Serialize(store.MasterKey)
|
||||||
|
});
|
||||||
|
if (resp.Code == MessageResponeCodes.OK)
|
||||||
|
{
|
||||||
|
return serializer.Deserialize<string>(resp.Data.Span);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
public async Task<string> GetShareKey(string masterKey)
|
||||||
|
{
|
||||||
|
if (masterKey != Config.MasterKey) return string.Empty;
|
||||||
|
return Config.ShareKey;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<string> Import(string shareKey)
|
public async Task<string> Import(string shareKey)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -117,16 +144,110 @@ namespace linker.messenger.relay.server
|
|||||||
}
|
}
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
public async Task<bool> Remove(int id)
|
public async Task<bool> Remove(string nodeId)
|
||||||
{
|
{
|
||||||
return await relayServerNodeStore.Delete(id).ConfigureAwait(false);
|
if (nodeId == Config.NodeId) return false;
|
||||||
|
|
||||||
|
return await relayServerNodeStore.Delete(nodeId).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
public async Task<bool> UpdateForward(RelayServerNodeStoreInfo info)
|
||||||
|
{
|
||||||
|
RelayServerNodeStoreInfo store = await relayServerNodeStore.GetByNodeId(info.NodeId);
|
||||||
|
|
||||||
|
if (store != null && store.Manageable && relayServerConnectionTransfer.TryGet(ConnectionSideType.Node, info.NodeId, out var connection))
|
||||||
|
{
|
||||||
|
info.MasterKey = store.MasterKey;
|
||||||
|
await messengerSender.SendOnly(new MessageRequestWrap
|
||||||
|
{
|
||||||
|
Connection = connection,
|
||||||
|
MessengerId = (ushort)RelayMessengerIds.Update,
|
||||||
|
Payload = serializer.Serialize(info)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return await relayServerNodeStore.Update(info).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
public async Task<bool> Update(RelayServerNodeStoreInfo info)
|
||||||
|
{
|
||||||
|
if (info.MasterKey != Config.MasterKey) return false;
|
||||||
|
|
||||||
|
Config.Connections = info.Connections;
|
||||||
|
Config.MasterKey = info.MasterKey;
|
||||||
|
Config.Bandwidth = info.Bandwidth;
|
||||||
|
Config.Protocol = info.Protocol;
|
||||||
|
Config.DataEachMonth = info.DataEachMonth;
|
||||||
|
Config.DataRemain = info.DataRemain;
|
||||||
|
Config.Logo = info.Logo;
|
||||||
|
Config.Name = info.Name;
|
||||||
|
Config.Url = info.Url;
|
||||||
|
Config.Domain = info.Domain;
|
||||||
|
|
||||||
|
relayServerConfigStore.Confirm();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
public async Task<bool> UpgradeForward(string nodeId, string version)
|
||||||
|
{
|
||||||
|
RelayServerNodeStoreInfo store = await relayServerNodeStore.GetByNodeId(nodeId);
|
||||||
|
|
||||||
|
if (store != null && store.Manageable && relayServerConnectionTransfer.TryGet(ConnectionSideType.Node, nodeId, out var connection))
|
||||||
|
{
|
||||||
|
await messengerSender.SendOnly(new MessageRequestWrap
|
||||||
|
{
|
||||||
|
Connection = connection,
|
||||||
|
MessengerId = (ushort)RelayMessengerIds.Update,
|
||||||
|
Payload = serializer.Serialize(new KeyValuePair<string, string>(store.MasterKey, version))
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public async Task<bool> Upgrade(string masterKey, string version)
|
||||||
|
{
|
||||||
|
if (masterKey != Config.MasterKey) return false;
|
||||||
|
|
||||||
|
Helper.AppUpdate(version);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
public async Task<bool> ExitForward(string nodeId)
|
||||||
|
{
|
||||||
|
RelayServerNodeStoreInfo store = await relayServerNodeStore.GetByNodeId(nodeId);
|
||||||
|
|
||||||
|
if (store != null && store.Manageable && relayServerConnectionTransfer.TryGet(ConnectionSideType.Node, nodeId, out var connection))
|
||||||
|
{
|
||||||
|
await messengerSender.SendOnly(new MessageRequestWrap
|
||||||
|
{
|
||||||
|
Connection = connection,
|
||||||
|
MessengerId = (ushort)RelayMessengerIds.Update,
|
||||||
|
Payload = serializer.Serialize(new KeyValuePair<string, string>(store.MasterKey, nodeId))
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public async Task<bool> Exit(string masterKey)
|
||||||
|
{
|
||||||
|
if (masterKey != Config.MasterKey) return false;
|
||||||
|
|
||||||
|
Helper.AppExit(-1);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<RelayServerNodeStoreInfo>> GetNodes(bool validated, string userid, string machineId)
|
public async Task<List<RelayServerNodeStoreInfo>> GetNodes(bool validated, string userid, string machineId)
|
||||||
{
|
{
|
||||||
var nodes = (await relayServerWhiteListStore.GetNodes(userid, machineId)).Where(c => c.Bandwidth >= 0).SelectMany(c => c.Nodes);
|
var nodes = (await relayServerWhiteListStore.GetNodes(userid, machineId)).Where(c => c.Bandwidth >= 0).SelectMany(c => c.Nodes);
|
||||||
|
|
||||||
var result = (await relayServerNodeStore.GetAll())
|
var list = await relayServerNodeStore.GetAll();
|
||||||
|
list.ForEach(c =>
|
||||||
|
{
|
||||||
|
c.MasterKey = string.Empty;
|
||||||
|
});
|
||||||
|
|
||||||
|
var result = list
|
||||||
.Where(c => validated || Environment.TickCount64 - c.LastTicks < 15000)
|
.Where(c => validated || Environment.TickCount64 - c.LastTicks < 15000)
|
||||||
.Where(c =>
|
.Where(c =>
|
||||||
{
|
{
|
||||||
@@ -146,7 +267,13 @@ namespace linker.messenger.relay.server
|
|||||||
}
|
}
|
||||||
public async Task<List<RelayServerNodeStoreInfo>> GetPublicNodes()
|
public async Task<List<RelayServerNodeStoreInfo>> GetPublicNodes()
|
||||||
{
|
{
|
||||||
var result = (await relayServerNodeStore.GetAll())
|
var list = await relayServerNodeStore.GetAll();
|
||||||
|
list.ForEach(c =>
|
||||||
|
{
|
||||||
|
c.MasterKey = string.Empty;
|
||||||
|
});
|
||||||
|
|
||||||
|
var result = list
|
||||||
.Where(c => Environment.TickCount64 - c.LastTicks < 15000)
|
.Where(c => Environment.TickCount64 - c.LastTicks < 15000)
|
||||||
.Where(c => c.Public)
|
.Where(c => c.Public)
|
||||||
.OrderByDescending(c => c.LastTicks);
|
.OrderByDescending(c => c.LastTicks);
|
||||||
@@ -227,7 +354,7 @@ namespace linker.messenger.relay.server
|
|||||||
BandwidthRatio = Math.Round(diff / 5, 2),
|
BandwidthRatio = Math.Round(diff / 5, 2),
|
||||||
Version = VersionHelper.Version,
|
Version = VersionHelper.Version,
|
||||||
Masters = connections.Select(c => c.Address).ToArray(),
|
Masters = connections.Select(c => c.Address).ToArray(),
|
||||||
MasterKey = config.MasterKey,
|
MasterKey = config.MasterKey,
|
||||||
};
|
};
|
||||||
byte[] memory = serializer.Serialize(info);
|
byte[] memory = serializer.Serialize(info);
|
||||||
var tasks = connections.Select(c => messengerSender.SendOnly(new MessageRequestWrap
|
var tasks = connections.Select(c => messengerSender.SendOnly(new MessageRequestWrap
|
||||||
|
|||||||
@@ -63,8 +63,12 @@ namespace linker.messenger.relay.server
|
|||||||
|
|
||||||
return serializer.Deserialize<RelayMessageInfo>(crypto.Decode(buffer, 0, length).Span);
|
return serializer.Deserialize<RelayMessageInfo>(crypto.Decode(buffer, 0, length).Span);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||||
|
{
|
||||||
|
LoggerHelper.Instance.Error(ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -93,7 +97,7 @@ namespace linker.messenger.relay.server
|
|||||||
if (relayCache == null)
|
if (relayCache == null)
|
||||||
{
|
{
|
||||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||||
LoggerHelper.Instance.Error($"relay {relayMessage.Type} get cache fail,flowid:{relayMessage.FlowId}");
|
LoggerHelper.Instance.Error($"relay server {relayMessage.Type} get cache fail,flowid:{relayMessage.FlowId}");
|
||||||
await socket.SendAsync(Helper.FalseArray).ConfigureAwait(false);
|
await socket.SendAsync(Helper.FalseArray).ConfigureAwait(false);
|
||||||
socket.SafeClose();
|
socket.SafeClose();
|
||||||
return;
|
return;
|
||||||
@@ -102,7 +106,7 @@ namespace linker.messenger.relay.server
|
|||||||
if (relayMessage.Type == RelayMessengerType.Ask && relayServerNodeTransfer.Validate(relayCache) == false)
|
if (relayMessage.Type == RelayMessengerType.Ask && relayServerNodeTransfer.Validate(relayCache) == false)
|
||||||
{
|
{
|
||||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||||
LoggerHelper.Instance.Error($"relay {relayMessage.Type} validate false,flowid:{relayMessage.FlowId}");
|
LoggerHelper.Instance.Error($"relay server {relayMessage.Type} validate false,flowid:{relayMessage.FlowId}");
|
||||||
await socket.SendAsync(Helper.FalseArray).ConfigureAwait(false);
|
await socket.SendAsync(Helper.FalseArray).ConfigureAwait(false);
|
||||||
socket.SafeClose();
|
socket.SafeClose();
|
||||||
return;
|
return;
|
||||||
@@ -122,14 +126,17 @@ namespace linker.messenger.relay.server
|
|||||||
}
|
}
|
||||||
|
|
||||||
TaskCompletionSource<Socket> tcs = new TaskCompletionSource<Socket>(TaskCreationOptions.RunContinuationsAsynchronously);
|
TaskCompletionSource<Socket> tcs = new TaskCompletionSource<Socket>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||||
|
Socket answerSocket = null;
|
||||||
|
IPEndPoint fromep = socket.RemoteEndPoint as IPEndPoint,toep = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await socket.SendAsync(Helper.TrueArray).ConfigureAwait(false);
|
await socket.SendAsync(Helper.TrueArray).ConfigureAwait(false);
|
||||||
relayDic.TryAdd(relayCache.FlowId, tcs);
|
relayDic.TryAdd(relayCache.FlowId, tcs);
|
||||||
Socket answerSocket = await tcs.Task.WaitAsync(TimeSpan.FromMilliseconds(15000)).ConfigureAwait(false);
|
answerSocket = await tcs.Task.WaitAsync(TimeSpan.FromMilliseconds(15000)).ConfigureAwait(false);
|
||||||
await answerSocket.SendAsync(Helper.TrueArray).ConfigureAwait(false);
|
await answerSocket.SendAsync(Helper.TrueArray).ConfigureAwait(false);
|
||||||
|
toep = answerSocket.RemoteEndPoint as IPEndPoint;
|
||||||
|
|
||||||
LoggerHelper.Instance.Error($"relay start {socket.RemoteEndPoint} to {answerSocket.RemoteEndPoint}");
|
LoggerHelper.Instance.Info($"relay server start {fromep} to {toep}");
|
||||||
|
|
||||||
string flowKey = relayMessage.Type == RelayMessengerType.Ask ? $"{relayMessage.FromId}->{relayMessage.ToId}" : $"{relayMessage.ToId}->{relayMessage.FromId}";
|
string flowKey = relayMessage.Type == RelayMessengerType.Ask ? $"{relayMessage.FromId}->{relayMessage.ToId}" : $"{relayMessage.ToId}->{relayMessage.FromId}";
|
||||||
RelayTrafficCacheInfo trafficCacheInfo = new RelayTrafficCacheInfo { Cache = relayCache, Sendt = 0, Limit = new RelaySpeedLimit(), Key = flowKey };
|
RelayTrafficCacheInfo trafficCacheInfo = new RelayTrafficCacheInfo { Cache = relayCache, Sendt = 0, Limit = new RelaySpeedLimit(), Key = flowKey };
|
||||||
@@ -138,26 +145,26 @@ namespace linker.messenger.relay.server
|
|||||||
await Task.WhenAll(CopyToAsync(trafficCacheInfo, socket, answerSocket), CopyToAsync(trafficCacheInfo, answerSocket, socket)).ConfigureAwait(false);
|
await Task.WhenAll(CopyToAsync(trafficCacheInfo, socket, answerSocket), CopyToAsync(trafficCacheInfo, answerSocket, socket)).ConfigureAwait(false);
|
||||||
relayServerNodeTransfer.DecrementConnectionNum();
|
relayServerNodeTransfer.DecrementConnectionNum();
|
||||||
relayServerNodeTransfer.RemoveTrafficCache(trafficCacheInfo);
|
relayServerNodeTransfer.RemoveTrafficCache(trafficCacheInfo);
|
||||||
|
|
||||||
LoggerHelper.Instance.Error($"relay end {socket.RemoteEndPoint} to {answerSocket.RemoteEndPoint}");
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
tcs.TrySetResult(null);
|
tcs.TrySetResult(null);
|
||||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||||
LoggerHelper.Instance.Error($"{ex},flowid:{relayMessage.FlowId}");
|
LoggerHelper.Instance.Error($"relay server error {ex},flowid:{relayMessage.FlowId}");
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
LoggerHelper.Instance.Info($"relay server end {fromep} to {toep}");
|
||||||
relayDic.TryRemove(relayCache.FlowId, out _);
|
relayDic.TryRemove(relayCache.FlowId, out _);
|
||||||
socket.SafeClose();
|
socket?.SafeClose();
|
||||||
|
answerSocket?.SafeClose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||||
LoggerHelper.Instance.Error(ex);
|
LoggerHelper.Instance.Error(ex);
|
||||||
socket.SafeClose();
|
socket?.SafeClose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private async Task CopyToAsync(RelayTrafficCacheInfo trafficCacheInfo, Socket source, Socket destination)
|
private async Task CopyToAsync(RelayTrafficCacheInfo trafficCacheInfo, Socket source, Socket destination)
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ namespace linker.tunnel.transport
|
|||||||
|
|
||||||
public bool SSL => true;
|
public bool SSL => true;
|
||||||
|
|
||||||
public bool DisableSSL => false;
|
public bool DisableSSL => true;
|
||||||
|
|
||||||
public byte Order => 0;
|
public byte Order => 0;
|
||||||
|
|
||||||
@@ -70,21 +70,21 @@ namespace linker.tunnel.transport
|
|||||||
List<RelayServerNodeStoreInfo> nodes = ask.Nodes;
|
List<RelayServerNodeStoreInfo> nodes = ask.Nodes;
|
||||||
if (ask.Nodes.Count == 0)
|
if (ask.Nodes.Count == 0)
|
||||||
{
|
{
|
||||||
throw new Exception("relay ask fail,no relay nodes");
|
throw new Exception("relay client ask fail,no relay nodes");
|
||||||
}
|
}
|
||||||
|
|
||||||
//连接中继节点服务器
|
//连接中继节点服务器
|
||||||
Socket socket = await ConnectNodeServer(tunnelTransportInfo, ask).ConfigureAwait(false);
|
Socket socket = await ConnectNodeServer(tunnelTransportInfo, ask).ConfigureAwait(false);
|
||||||
if(socket == null)
|
if(socket == null)
|
||||||
{
|
{
|
||||||
throw new Exception("connect relay node server fail");
|
throw new Exception("relay client connect node server fail");
|
||||||
}
|
}
|
||||||
tunnelTransportInfo.TransactionTag = ask.Info.ToJson();
|
tunnelTransportInfo.TransactionTag = ask.Info.ToJson();
|
||||||
|
|
||||||
//让对方确认中继
|
//让对方确认中继
|
||||||
if (await tunnelMessengerAdapter.SendConnectBegin(tunnelTransportInfo).ConfigureAwait(false) == false)
|
if (await tunnelMessengerAdapter.SendConnectBegin(tunnelTransportInfo).ConfigureAwait(false) == false)
|
||||||
{
|
{
|
||||||
throw new Exception("relay begin fail");
|
throw new Exception("relay client begin fail");
|
||||||
}
|
}
|
||||||
|
|
||||||
//成功建立连接,
|
//成功建立连接,
|
||||||
@@ -182,7 +182,7 @@ namespace linker.tunnel.transport
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||||
LoggerHelper.Instance.Debug($"connect relay server {ep}");
|
LoggerHelper.Instance.Debug($"relay client connect server {ep}");
|
||||||
|
|
||||||
//连接中继服务器
|
//连接中继服务器
|
||||||
Socket socket = new Socket(ep.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
|
Socket socket = new Socket(ep.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
|
||||||
@@ -191,7 +191,7 @@ namespace linker.tunnel.transport
|
|||||||
await socket.ConnectAsync(ep).WaitAsync(TimeSpan.FromMilliseconds(5000)).ConfigureAwait(false);
|
await socket.ConnectAsync(ep).WaitAsync(TimeSpan.FromMilliseconds(5000)).ConfigureAwait(false);
|
||||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||||
{
|
{
|
||||||
LoggerHelper.Instance.Debug($"relay connected {ep}");
|
LoggerHelper.Instance.Debug($"relay client connected {ep}");
|
||||||
}
|
}
|
||||||
|
|
||||||
//建立关联
|
//建立关联
|
||||||
@@ -254,10 +254,15 @@ namespace linker.tunnel.transport
|
|||||||
await socket.SendAsync(buffer.Memory.Slice(0, sendBytes.Length + 5)).ConfigureAwait(false);
|
await socket.SendAsync(buffer.Memory.Slice(0, sendBytes.Length + 5)).ConfigureAwait(false);
|
||||||
|
|
||||||
int length = await socket.ReceiveAsync(buffer.Memory.Slice(0, 1)).AsTask().WaitAsync(TimeSpan.FromMilliseconds(5000)).ConfigureAwait(false);
|
int length = await socket.ReceiveAsync(buffer.Memory.Slice(0, 1)).AsTask().WaitAsync(TimeSpan.FromMilliseconds(5000)).ConfigureAwait(false);
|
||||||
return length == 1 && buffer.Memory.Span[0] == 0;
|
|
||||||
|
return length == 1 && buffer.Memory.Slice(0, 1).Span.SequenceEqual(Helper.TrueArray);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||||
|
{
|
||||||
|
LoggerHelper.Instance.Error(ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -268,7 +273,7 @@ namespace linker.tunnel.transport
|
|||||||
{
|
{
|
||||||
if (tunnelTransportInfo.SSL && certificate == null)
|
if (tunnelTransportInfo.SSL && certificate == null)
|
||||||
{
|
{
|
||||||
LoggerHelper.Instance.Error($"{Name}->ssl Certificate not found");
|
LoggerHelper.Instance.Error($"relay client {Name}->ssl Certificate not found");
|
||||||
await tunnelMessengerAdapter.SendConnectFail(tunnelTransportInfo).ConfigureAwait(false);
|
await tunnelMessengerAdapter.SendConnectFail(tunnelTransportInfo).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -301,7 +306,7 @@ namespace linker.tunnel.transport
|
|||||||
{
|
{
|
||||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||||
{
|
{
|
||||||
LoggerHelper.Instance.Error($"relay connect server {ep} {ex}");
|
LoggerHelper.Instance.Error($"relay client connect server {ep} {ex}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -349,7 +354,7 @@ namespace linker.tunnel.transport
|
|||||||
{
|
{
|
||||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||||
{
|
{
|
||||||
LoggerHelper.Instance.Error($"relay wait ssl {ex}");
|
LoggerHelper.Instance.Error($"relay client wait ssl {ex}");
|
||||||
}
|
}
|
||||||
socket.SafeClose();
|
socket.SafeClose();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ namespace linker.messenger.serializer.memorypack
|
|||||||
value = null;
|
value = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
value = new AccessUpdateInfo() ;
|
value = new AccessUpdateInfo();
|
||||||
reader.TryReadObjectHeader(out byte count);
|
reader.TryReadObjectHeader(out byte count);
|
||||||
value.FromMachineId = reader.ReadValue<string>();
|
value.FromMachineId = reader.ReadValue<string>();
|
||||||
value.ToMachineId = reader.ReadValue<string>();
|
value.ToMachineId = reader.ReadValue<string>();
|
||||||
@@ -74,10 +74,13 @@ namespace linker.messenger.serializer.memorypack
|
|||||||
[MemoryPackInclude]
|
[MemoryPackInclude]
|
||||||
BitArray Access => info.Access;
|
BitArray Access => info.Access;
|
||||||
|
|
||||||
|
[MemoryPackInclude]
|
||||||
|
bool FullAccess => info.FullAccess;
|
||||||
|
|
||||||
[MemoryPackConstructor]
|
[MemoryPackConstructor]
|
||||||
SerializableAccessBitsUpdateInfo(string fromMachineId, string toMachineId, BitArray access)
|
SerializableAccessBitsUpdateInfo(string fromMachineId, string toMachineId, BitArray access, bool fullAccess)
|
||||||
{
|
{
|
||||||
var info = new AccessBitsUpdateInfo { FromMachineId = fromMachineId, ToMachineId = toMachineId, Access = access };
|
var info = new AccessBitsUpdateInfo { FromMachineId = fromMachineId, ToMachineId = toMachineId, Access = access, FullAccess = fullAccess };
|
||||||
this.info = info;
|
this.info = info;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,10 +113,13 @@ namespace linker.messenger.serializer.memorypack
|
|||||||
|
|
||||||
value = new AccessBitsUpdateInfo();
|
value = new AccessBitsUpdateInfo();
|
||||||
reader.TryReadObjectHeader(out byte count);
|
reader.TryReadObjectHeader(out byte count);
|
||||||
value.FromMachineId = reader.ReadValue<string>();
|
value.FromMachineId = reader.ReadValue<string>();
|
||||||
value.ToMachineId = reader.ReadValue<string>();
|
value.ToMachineId = reader.ReadValue<string>();
|
||||||
value.Access = reader.ReadValue<BitArray>();
|
value.Access = reader.ReadValue<BitArray>();
|
||||||
|
if (count > 3)
|
||||||
|
{
|
||||||
|
value.FullAccess = reader.ReadValue<bool>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -251,10 +251,12 @@ namespace linker.messenger.serializer.memorypack
|
|||||||
double BandwidthRatio => info.BandwidthRatio;
|
double BandwidthRatio => info.BandwidthRatio;
|
||||||
[MemoryPackInclude]
|
[MemoryPackInclude]
|
||||||
IPEndPoint[] Masters => info.Masters;
|
IPEndPoint[] Masters => info.Masters;
|
||||||
|
[MemoryPackInclude]
|
||||||
|
string Domain => info.Domain;
|
||||||
|
|
||||||
[MemoryPackConstructor]
|
[MemoryPackConstructor]
|
||||||
SerializableRelayServerNodeReportInfo(string nodeId, string name, TunnelProtocolType protocol, int connections, int bandwidth, int dataEachMonth,
|
SerializableRelayServerNodeReportInfo(string nodeId, string name, TunnelProtocolType protocol, int connections, int bandwidth, int dataEachMonth,
|
||||||
long dataRemain, string url, string logo, string masterKey, string version, int connectionsRatio, double bandwidthRatio, IPEndPoint[] masters)
|
long dataRemain, string url, string logo, string masterKey, string version, int connectionsRatio, double bandwidthRatio, IPEndPoint[] masters, string domain)
|
||||||
{
|
{
|
||||||
var info = new RelayServerNodeReportInfo
|
var info = new RelayServerNodeReportInfo
|
||||||
{
|
{
|
||||||
@@ -271,7 +273,8 @@ namespace linker.messenger.serializer.memorypack
|
|||||||
Version = version,
|
Version = version,
|
||||||
ConnectionsRatio = connectionsRatio,
|
ConnectionsRatio = connectionsRatio,
|
||||||
BandwidthRatio = bandwidthRatio,
|
BandwidthRatio = bandwidthRatio,
|
||||||
Masters = masters
|
Masters = masters,
|
||||||
|
Domain = domain
|
||||||
};
|
};
|
||||||
this.info = info;
|
this.info = info;
|
||||||
}
|
}
|
||||||
@@ -319,6 +322,7 @@ namespace linker.messenger.serializer.memorypack
|
|||||||
value.ConnectionsRatio = reader.ReadValue<int>();
|
value.ConnectionsRatio = reader.ReadValue<int>();
|
||||||
value.BandwidthRatio = reader.ReadValue<double>();
|
value.BandwidthRatio = reader.ReadValue<double>();
|
||||||
value.Masters = reader.ReadValue<IPEndPoint[]>();
|
value.Masters = reader.ReadValue<IPEndPoint[]>();
|
||||||
|
value.Domain = reader.ReadValue<string>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,7 +361,9 @@ namespace linker.messenger.serializer.memorypack
|
|||||||
[MemoryPackInclude]
|
[MemoryPackInclude]
|
||||||
double BandwidthRatio => info.BandwidthRatio;
|
double BandwidthRatio => info.BandwidthRatio;
|
||||||
[MemoryPackInclude]
|
[MemoryPackInclude]
|
||||||
IPEndPoint[] Servers => info.Masters;
|
IPEndPoint[] Masters => info.Masters;
|
||||||
|
[MemoryPackInclude]
|
||||||
|
string Domain => info.Domain;
|
||||||
|
|
||||||
|
|
||||||
[MemoryPackInclude]
|
[MemoryPackInclude]
|
||||||
@@ -376,7 +382,7 @@ namespace linker.messenger.serializer.memorypack
|
|||||||
|
|
||||||
[MemoryPackConstructor]
|
[MemoryPackConstructor]
|
||||||
SerializableRelayServerNodeStoreInfo(string nodeId, string name, TunnelProtocolType protocol, int connections, int bandwidth, int dataEachMonth,
|
SerializableRelayServerNodeStoreInfo(string nodeId, string name, TunnelProtocolType protocol, int connections, int bandwidth, int dataEachMonth,
|
||||||
long dataRemain, string url, string logo, string masterKey, string version, int connectionsRatio, double bandwidthRatio, IPEndPoint[] servers,
|
long dataRemain, string url, string logo, string masterKey, string version, int connectionsRatio, double bandwidthRatio, IPEndPoint[] masters, string domain,
|
||||||
int id, string host, int bandwidthEachConnection, bool Public, long lastTicks, bool manageable)
|
int id, string host, int bandwidthEachConnection, bool Public, long lastTicks, bool manageable)
|
||||||
{
|
{
|
||||||
var info = new RelayServerNodeStoreInfo
|
var info = new RelayServerNodeStoreInfo
|
||||||
@@ -394,7 +400,8 @@ namespace linker.messenger.serializer.memorypack
|
|||||||
Version = version,
|
Version = version,
|
||||||
ConnectionsRatio = connectionsRatio,
|
ConnectionsRatio = connectionsRatio,
|
||||||
BandwidthRatio = bandwidthRatio,
|
BandwidthRatio = bandwidthRatio,
|
||||||
Masters = servers,
|
Masters = masters,
|
||||||
|
Domain = domain,
|
||||||
Id = id,
|
Id = id,
|
||||||
Host = host,
|
Host = host,
|
||||||
BandwidthEach = bandwidthEachConnection,
|
BandwidthEach = bandwidthEachConnection,
|
||||||
@@ -448,6 +455,7 @@ namespace linker.messenger.serializer.memorypack
|
|||||||
value.ConnectionsRatio = reader.ReadValue<int>();
|
value.ConnectionsRatio = reader.ReadValue<int>();
|
||||||
value.BandwidthRatio = reader.ReadValue<double>();
|
value.BandwidthRatio = reader.ReadValue<double>();
|
||||||
value.Masters = reader.ReadValue<IPEndPoint[]>();
|
value.Masters = reader.ReadValue<IPEndPoint[]>();
|
||||||
|
value.Domain = reader.ReadValue<string>();
|
||||||
value.Id = reader.ReadValue<int>();
|
value.Id = reader.ReadValue<int>();
|
||||||
value.Host = reader.ReadValue<string>();
|
value.Host = reader.ReadValue<string>();
|
||||||
value.BandwidthEach = reader.ReadValue<int>();
|
value.BandwidthEach = reader.ReadValue<int>();
|
||||||
|
|||||||
@@ -244,11 +244,12 @@ namespace linker.messenger.serializer.memorypack
|
|||||||
[MemoryPackInclude]
|
[MemoryPackInclude]
|
||||||
uint FlowId => tunnelTransportInfo.FlowId;
|
uint FlowId => tunnelTransportInfo.FlowId;
|
||||||
|
|
||||||
//[MemoryPackInclude]
|
[MemoryPackInclude]
|
||||||
//string TransactionTag => tunnelTransportInfo.TransactionTag;
|
string TransactionTag => tunnelTransportInfo.TransactionTag;
|
||||||
|
|
||||||
[MemoryPackConstructor]
|
[MemoryPackConstructor]
|
||||||
SerializableTunnelTransportInfo(TunnelTransportWanPortInfo local, TunnelTransportWanPortInfo remote, string transactionId, TunnelProtocolType transportType, string transportName, TunnelDirection direction, bool ssl, byte bufferSize, uint flowid/*, string transactionTag*/)
|
SerializableTunnelTransportInfo(TunnelTransportWanPortInfo local, TunnelTransportWanPortInfo remote, string transactionId,
|
||||||
|
TunnelProtocolType transportType, string transportName, TunnelDirection direction, bool ssl, byte bufferSize, uint flowid, string transactionTag)
|
||||||
{
|
{
|
||||||
var tunnelTransportInfo = new TunnelTransportInfo
|
var tunnelTransportInfo = new TunnelTransportInfo
|
||||||
{
|
{
|
||||||
@@ -261,7 +262,7 @@ namespace linker.messenger.serializer.memorypack
|
|||||||
SSL = ssl,
|
SSL = ssl,
|
||||||
BufferSize = bufferSize,
|
BufferSize = bufferSize,
|
||||||
FlowId = flowid,
|
FlowId = flowid,
|
||||||
// TransactionTag = transactionTag
|
TransactionTag = transactionTag
|
||||||
};
|
};
|
||||||
this.tunnelTransportInfo = tunnelTransportInfo;
|
this.tunnelTransportInfo = tunnelTransportInfo;
|
||||||
}
|
}
|
||||||
@@ -293,8 +294,19 @@ namespace linker.messenger.serializer.memorypack
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var wrapped = reader.ReadPackable<SerializableTunnelTransportInfo>();
|
value = new TunnelTransportInfo();
|
||||||
value = wrapped.tunnelTransportInfo;
|
reader.TryReadObjectHeader(out byte count);
|
||||||
|
value.Local = reader.ReadValue<TunnelTransportWanPortInfo>();
|
||||||
|
value.Remote = reader.ReadValue<TunnelTransportWanPortInfo>();
|
||||||
|
value.TransactionId = reader.ReadValue<string>();
|
||||||
|
value.TransportType = reader.ReadValue<TunnelProtocolType>();
|
||||||
|
value.TransportName = reader.ReadValue<string>();
|
||||||
|
value.Direction = reader.ReadValue<TunnelDirection>();
|
||||||
|
value.SSL = reader.ReadValue<bool>();
|
||||||
|
value.BufferSize = reader.ReadValue<byte>();
|
||||||
|
value.FlowId = reader.ReadValue<uint>();
|
||||||
|
if (count > 9)
|
||||||
|
value.TransactionTag = reader.ReadValue<string>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ namespace linker.messenger.store.file.relay
|
|||||||
return await Task.FromResult(true).ConfigureAwait(false);
|
return await Task.FromResult(true).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> Delete(int id)
|
public async Task<bool> Delete(string nodeId)
|
||||||
{
|
{
|
||||||
return await Task.FromResult(liteCollection.Delete(id)).ConfigureAwait(false);
|
return await Task.FromResult(liteCollection.DeleteMany(c => c.NodeId == nodeId) > 0).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<RelayServerNodeStoreInfo>> GetAll()
|
public async Task<List<RelayServerNodeStoreInfo>> GetAll()
|
||||||
@@ -59,7 +59,18 @@ namespace linker.messenger.store.file.relay
|
|||||||
MasterKey = info.MasterKey,
|
MasterKey = info.MasterKey,
|
||||||
Masters = info.Masters,
|
Masters = info.Masters,
|
||||||
//是我初始化的,可以管理
|
//是我初始化的,可以管理
|
||||||
Manageable = false//info.MasterKey == md5
|
Manageable = info.MasterKey == md5
|
||||||
|
}, c => c.NodeId == info.NodeId);
|
||||||
|
|
||||||
|
return await Task.FromResult(length > 0).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> Update(RelayServerNodeStoreInfo info)
|
||||||
|
{
|
||||||
|
int length = liteCollection.UpdateMany(p => new RelayServerNodeStoreInfo
|
||||||
|
{
|
||||||
|
DataEachMonth = info.DataEachMonth,
|
||||||
|
Public = info.Public,
|
||||||
}, c => c.NodeId == info.NodeId);
|
}, c => c.NodeId == info.NodeId);
|
||||||
|
|
||||||
return await Task.FromResult(length > 0).ConfigureAwait(false); ;
|
return await Task.FromResult(length > 0).ConfigureAwait(false); ;
|
||||||
|
|||||||
36
src/linker.web/package-lock.json
generated
36
src/linker.web/package-lock.json
generated
@@ -8,9 +8,9 @@
|
|||||||
"name": "linker.web",
|
"name": "linker.web",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@element-plus/icons-vue": "^2.3.1",
|
"@element-plus/icons-vue": "^2.3.2",
|
||||||
"core-js": "^3.38.0",
|
"core-js": "^3.38.0",
|
||||||
"element-plus": "^2.8.0",
|
"element-plus": "^2.11.9",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"vue": "^3.4.38",
|
"vue": "^3.4.38",
|
||||||
"vue-i18n": "^11.0.1",
|
"vue-i18n": "^11.0.1",
|
||||||
@@ -1710,8 +1710,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@element-plus/icons-vue": {
|
"node_modules/@element-plus/icons-vue": {
|
||||||
"version": "2.3.1",
|
"version": "2.3.2",
|
||||||
"license": "MIT",
|
"resolved": "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-2.3.2.tgz",
|
||||||
|
"integrity": "sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A==",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"vue": "^3.2.0"
|
"vue": "^3.2.0"
|
||||||
}
|
}
|
||||||
@@ -2114,8 +2115,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/lodash": {
|
"node_modules/@types/lodash": {
|
||||||
"version": "4.17.0",
|
"version": "4.17.21",
|
||||||
"license": "MIT"
|
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.21.tgz",
|
||||||
|
"integrity": "sha512-FOvQ0YPD5NOfPgMzJihoT+Za5pdkDJWcbpuj1DjaKZIr/gxodQjY/uWEFlTNqW2ugXHUiL8lRQgw63dzKHZdeQ=="
|
||||||
},
|
},
|
||||||
"node_modules/@types/lodash-es": {
|
"node_modules/@types/lodash-es": {
|
||||||
"version": "4.17.12",
|
"version": "4.17.12",
|
||||||
@@ -4536,8 +4538,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/dayjs": {
|
"node_modules/dayjs": {
|
||||||
"version": "1.11.10",
|
"version": "1.11.19",
|
||||||
"license": "MIT"
|
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz",
|
||||||
|
"integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw=="
|
||||||
},
|
},
|
||||||
"node_modules/debounce": {
|
"node_modules/debounce": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
@@ -4896,22 +4899,22 @@
|
|||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/element-plus": {
|
"node_modules/element-plus": {
|
||||||
"version": "2.8.0",
|
"version": "2.11.9",
|
||||||
"license": "MIT",
|
"resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.11.9.tgz",
|
||||||
|
"integrity": "sha512-yTckX+fMGDGiBHVL1gpwfmjEc8P8OwuyU5ZX3f4FhMy2OdC2Y+OwQYWUXmuB+jFMukuSdnGYXYgHq6muBjSxTg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ctrl/tinycolor": "^3.4.1",
|
"@ctrl/tinycolor": "^3.4.1",
|
||||||
"@element-plus/icons-vue": "^2.3.1",
|
"@element-plus/icons-vue": "^2.3.2",
|
||||||
"@floating-ui/dom": "^1.0.1",
|
"@floating-ui/dom": "^1.0.1",
|
||||||
"@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7",
|
"@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7",
|
||||||
"@types/lodash": "^4.14.182",
|
"@types/lodash": "^4.17.20",
|
||||||
"@types/lodash-es": "^4.17.6",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@vueuse/core": "^9.1.0",
|
"@vueuse/core": "^9.1.0",
|
||||||
"async-validator": "^4.2.5",
|
"async-validator": "^4.2.5",
|
||||||
"dayjs": "^1.11.3",
|
"dayjs": "^1.11.19",
|
||||||
"escape-html": "^1.0.3",
|
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"lodash-unified": "^1.0.2",
|
"lodash-unified": "^1.0.3",
|
||||||
"memoize-one": "^6.0.0",
|
"memoize-one": "^6.0.0",
|
||||||
"normalize-wheel-es": "^1.2.0"
|
"normalize-wheel-es": "^1.2.0"
|
||||||
},
|
},
|
||||||
@@ -5020,6 +5023,7 @@
|
|||||||
},
|
},
|
||||||
"node_modules/escape-html": {
|
"node_modules/escape-html": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/escape-string-regexp": {
|
"node_modules/escape-string-regexp": {
|
||||||
|
|||||||
@@ -7,9 +7,9 @@
|
|||||||
"build": "vue-cli-service build"
|
"build": "vue-cli-service build"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@element-plus/icons-vue": "^2.3.1",
|
"@element-plus/icons-vue": "^2.3.2",
|
||||||
"core-js": "^3.38.0",
|
"core-js": "^3.38.0",
|
||||||
"element-plus": "^2.8.0",
|
"element-plus": "^2.11.9",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"vue": "^3.4.38",
|
"vue": "^3.4.38",
|
||||||
"vue-i18n": "^11.0.1",
|
"vue-i18n": "^11.0.1",
|
||||||
|
|||||||
@@ -12,12 +12,21 @@ export const setRelaySubscribe = () => {
|
|||||||
export const relayConnect = (data) => {
|
export const relayConnect = (data) => {
|
||||||
return sendWebsocketMsg('relay/Connect', data);
|
return sendWebsocketMsg('relay/Connect', data);
|
||||||
}
|
}
|
||||||
export const relayEdit = (data) => {
|
export const relayUpdate= (data) => {
|
||||||
return sendWebsocketMsg('relay/edit', data);
|
return sendWebsocketMsg('relay/update', data);
|
||||||
|
}
|
||||||
|
export const relayUpgrade= (data) => {
|
||||||
|
return sendWebsocketMsg('relay/upgrade', data);
|
||||||
}
|
}
|
||||||
export const relayExit = (id) => {
|
export const relayExit = (id) => {
|
||||||
return sendWebsocketMsg('relay/Exit', id);
|
return sendWebsocketMsg('relay/Exit', id);
|
||||||
}
|
}
|
||||||
export const relayUpdate = (id) => {
|
export const relayRemove = (id) => {
|
||||||
return sendWebsocketMsg('relay/Update', id);
|
return sendWebsocketMsg('relay/Remove', id);
|
||||||
|
}
|
||||||
|
export const relayImport = (data) => {
|
||||||
|
return sendWebsocketMsg('relay/Import', data);
|
||||||
|
}
|
||||||
|
export const relayShare = (id) => {
|
||||||
|
return sendWebsocketMsg('relay/Share', id);
|
||||||
}
|
}
|
||||||
@@ -148,7 +148,9 @@ a.a-line {
|
|||||||
.mgb-0 {
|
.mgb-0 {
|
||||||
margin-bottom: 0 !important;
|
margin-bottom: 0 !important;
|
||||||
}
|
}
|
||||||
|
.mgb-1 {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
.mgb-3 {
|
.mgb-3 {
|
||||||
margin-bottom: 3rem;
|
margin-bottom: 3rem;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -212,6 +212,9 @@ export default {
|
|||||||
'server.relayExit': 'Restart',
|
'server.relayExit': 'Restart',
|
||||||
'server.relayUpdate': 'Update',
|
'server.relayUpdate': 'Update',
|
||||||
'server.relayEdit': 'Edit',
|
'server.relayEdit': 'Edit',
|
||||||
|
'server.relayRemove': 'Remove',
|
||||||
|
'server.relayImport': 'Import relay node',
|
||||||
|
'server.relayShare': 'Share relay node',
|
||||||
|
|
||||||
'server.cdkeySecretKey': 'Cdkey secretKey',
|
'server.cdkeySecretKey': 'Cdkey secretKey',
|
||||||
'server.cdkeyText': 'The cdkey manager can be used when the key is correct',
|
'server.cdkeyText': 'The cdkey manager can be used when the key is correct',
|
||||||
|
|||||||
@@ -290,7 +290,7 @@ export default {
|
|||||||
'server.relayName': '名称',
|
'server.relayName': '名称',
|
||||||
'server.relayFlow': '月流量',
|
'server.relayFlow': '月流量',
|
||||||
'server.relayFlowLast': '剩余流量',
|
'server.relayFlowLast': '剩余流量',
|
||||||
'server.relaySpeed': '带宽',
|
'server.relaySpeed': '单链带宽',
|
||||||
'server.relaySpeed1': '总带宽',
|
'server.relaySpeed1': '总带宽',
|
||||||
'server.relaySpeed2': '速率',
|
'server.relaySpeed2': '速率',
|
||||||
'server.relayConnection': '连接数',
|
'server.relayConnection': '连接数',
|
||||||
@@ -308,6 +308,9 @@ export default {
|
|||||||
'server.relayExit': '重启',
|
'server.relayExit': '重启',
|
||||||
'server.relayUpdate': '更新',
|
'server.relayUpdate': '更新',
|
||||||
'server.relayEdit': '编辑',
|
'server.relayEdit': '编辑',
|
||||||
|
'server.relayRemove': '删除',
|
||||||
|
'server.relayImport': '导入中继节点',
|
||||||
|
'server.relayShare': '分享中继节点',
|
||||||
|
|
||||||
'server.cdkeySecretKey': 'Cdkey密钥',
|
'server.cdkeySecretKey': 'Cdkey密钥',
|
||||||
'server.cdkeyText': '密钥正确时可管理cdkey',
|
'server.cdkeyText': '密钥正确时可管理cdkey',
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ const routes = [
|
|||||||
{
|
{
|
||||||
path: '/full/index.html',
|
path: '/full/index.html',
|
||||||
name: 'FullIndex',
|
name: 'FullIndex',
|
||||||
meta: { title: 'head.home',access:'FullIndex',icon:'home.svg' },
|
meta: { title: 'head.home',access:'FullManager',icon:'home.svg' },
|
||||||
component: () => import('@/views/layout/full/list/Index.vue')
|
component: () => import('@/views/layout/full/list/Index.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
<el-col :span="8" v-if="globalData.config.Client.FullAccess">
|
<el-col :span="8" v-if="globalData.config.Client.FullAccess">
|
||||||
<el-checkbox v-model="state.full" ><span class="red">满权限(顶级管理权)</span></el-checkbox>
|
<el-checkbox v-model="state.full" ><span class="red">满权限(顶级管理权)</span></el-checkbox>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-input size="small" v-model="state.search"></el-input>
|
||||||
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<div class="access-wrap scrollbar" :style="{height:`${state.height}rem`}">
|
<div class="access-wrap scrollbar" :style="{height:`${state.height}rem`}">
|
||||||
<el-checkbox-group v-model="state.checkList" @change="handleCheckedChange">
|
<el-checkbox-group v-model="state.checkList" @change="handleCheckedChange">
|
||||||
@@ -27,16 +30,17 @@ export default {
|
|||||||
setup(props) {
|
setup(props) {
|
||||||
|
|
||||||
const globalData = injectGlobalData();
|
const globalData = injectGlobalData();
|
||||||
|
const exclude = ['ExternalShow','Cdkey']
|
||||||
const access = computed(()=>{
|
const access = computed(()=>{
|
||||||
const json = globalData.value.config.Client.Accesss;
|
const json = globalData.value.config.Client.Accesss;
|
||||||
return Object.keys(json).reduce((arr,key,index)=>{
|
return Object.keys(json).reduce((arr,key,index)=>{
|
||||||
if(globalData.value.hasAccess(key)){
|
if(globalData.value.hasAccess(key) && !exclude.includes(key)){
|
||||||
const value = json[key];
|
const value = json[key];
|
||||||
value.Key = key;
|
value.Key = key;
|
||||||
arr.push(value);
|
arr.push(value);
|
||||||
}
|
}
|
||||||
return arr;
|
return arr;
|
||||||
},[]);
|
},[]).filter(c=>c.Text.includes(state.search));
|
||||||
});
|
});
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
@@ -63,7 +67,9 @@ export default {
|
|||||||
],
|
],
|
||||||
checkAll:false,
|
checkAll:false,
|
||||||
full:false,
|
full:false,
|
||||||
isIndeterminate:false
|
isIndeterminate:false,
|
||||||
|
|
||||||
|
search:''
|
||||||
});
|
});
|
||||||
|
|
||||||
const getValue = ()=>{
|
const getValue = ()=>{
|
||||||
|
|||||||
@@ -88,7 +88,6 @@ export const provideDevices = () => {
|
|||||||
getSignInList(devices.page.Request).then((res) => {
|
getSignInList(devices.page.Request).then((res) => {
|
||||||
devices.page.Request = res.Request;
|
devices.page.Request = res.Request;
|
||||||
devices.page.Count = res.Count;
|
devices.page.Count = res.Count;
|
||||||
console.log(res);
|
|
||||||
for (let j in res.List) {
|
for (let j in res.List) {
|
||||||
Object.assign(res.List[j], {
|
Object.assign(res.List[j], {
|
||||||
showDel: machineId.value != res.List[j].MachineId && res.List[j].Connected == false,
|
showDel: machineId.value != res.List[j].MachineId && res.List[j].Connected == false,
|
||||||
|
|||||||
@@ -106,13 +106,14 @@ export default {
|
|||||||
const handleShowAccess = (row,access)=>{
|
const handleShowAccess = (row,access)=>{
|
||||||
const rowAccess = row.hook_accesss || '';
|
const rowAccess = row.hook_accesss || '';
|
||||||
const myAccess = globalData.value.config.Client.AccessBits;
|
const myAccess = globalData.value.config.Client.AccessBits;
|
||||||
|
|
||||||
let maxLength = Math.max(myAccess.length,rowAccess.length);
|
let maxLength = Math.max(myAccess.length,rowAccess.length);
|
||||||
let myValue = myAccess.padEnd(maxLength,'0').split('');
|
let myValue = myAccess.padEnd(maxLength,'0').split('').map(c=>+c);
|
||||||
let rowValue = rowAccess.padEnd(maxLength,'0').split('');
|
let rowValue = rowAccess.padEnd(maxLength,'0').split('').map(c=>+c);
|
||||||
return row.showAccess && access.Access
|
return row.showAccess && access.Access
|
||||||
&& myValue.map((v,i)=>{
|
&& myValue.map((v,i)=>{
|
||||||
return (rowValue[i] == '1' && v == '1') || rowValue[i] == '0';
|
return (rowValue[i] + v >=1 && v == 1);
|
||||||
}).filter(c=>c).length > 0;
|
}).filter(c=>!c).length == 0;
|
||||||
}
|
}
|
||||||
const handleAccess = (row)=>{
|
const handleAccess = (row)=>{
|
||||||
devices.deviceInfo = row;
|
devices.deviceInfo = row;
|
||||||
|
|||||||
@@ -49,7 +49,7 @@
|
|||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import { reactive, ref, watch } from 'vue'
|
import { reactive, ref, watch } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { relayEdit } from '@/apis/relay';
|
import { relayUpdate } from '@/apis/relay';
|
||||||
import { Refresh } from '@element-plus/icons-vue'
|
import { Refresh } from '@element-plus/icons-vue'
|
||||||
export default {
|
export default {
|
||||||
props: ['data','modelValue'],
|
props: ['data','modelValue'],
|
||||||
@@ -57,22 +57,12 @@ export default {
|
|||||||
components:{Refresh},
|
components:{Refresh},
|
||||||
setup(props,{emit}) {
|
setup(props,{emit}) {
|
||||||
const {t} = useI18n();
|
const {t} = useI18n();
|
||||||
|
const json = JSON.parse(JSON.stringify(props.data));
|
||||||
|
json.AllowTcp = (json.Protocol & 1) == 1;
|
||||||
|
json.AllowUdp = (json.Protocol & 2) == 2;
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
show:true,
|
show:true,
|
||||||
ruleForm:{
|
ruleForm:json,
|
||||||
Id:props.data.Id,
|
|
||||||
Name:props.data.Name,
|
|
||||||
Connections:props.data.Connections,
|
|
||||||
BandwidthEach:props.data.BandwidthEach,
|
|
||||||
Bandwidth:props.data.Bandwidth,
|
|
||||||
DataEachMonth:props.data.DataEachMonth,
|
|
||||||
DataRemain:props.data.DataRemain,
|
|
||||||
Public:props.data.Public,
|
|
||||||
Url:props.data.Url,
|
|
||||||
Logo:props.data.Logo,
|
|
||||||
AllowTcp:(props.data.Protocol & 1) == 1,
|
|
||||||
AllowUdp:(props.data.Protocol & 2) == 2,
|
|
||||||
},
|
|
||||||
rules:{
|
rules:{
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -95,7 +85,7 @@ export default {
|
|||||||
const json = JSON.parse(JSON.stringify(state.ruleForm));
|
const json = JSON.parse(JSON.stringify(state.ruleForm));
|
||||||
json.Protocol = (json.AllowTcp ? 1 : 0) | (json.AllowUdp ? 2 : 0);
|
json.Protocol = (json.AllowTcp ? 1 : 0) | (json.AllowUdp ? 2 : 0);
|
||||||
|
|
||||||
relayEdit(json).then((res)=>{
|
relayUpdate(json).then((res)=>{
|
||||||
if(res){
|
if(res){
|
||||||
ElMessage.success(t('common.oper'));
|
ElMessage.success(t('common.oper'));
|
||||||
state.show = false;
|
state.show = false;
|
||||||
|
|||||||
@@ -2,6 +2,17 @@
|
|||||||
<div>
|
<div>
|
||||||
<el-dialog v-model="state.show" :title="$t('server.relayTitle')" width="98%" top="2vh">
|
<el-dialog v-model="state.show" :title="$t('server.relayTitle')" width="98%" top="2vh">
|
||||||
<div>
|
<div>
|
||||||
|
<AccessShow value="ImportRelayNode">
|
||||||
|
<div class="head mgb-1" v-if="state.super">
|
||||||
|
<div class="flex">
|
||||||
|
<span class="flex-1"></span>
|
||||||
|
<div>
|
||||||
|
<el-button type="success" size="small" @click="handleImport"><el-icon><Plus /></el-icon></el-button>
|
||||||
|
</div>
|
||||||
|
<span class="flex-1"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</AccessShow>
|
||||||
<el-table :data="state.nodes" size="small" border height="500" stripe>
|
<el-table :data="state.nodes" size="small" border height="500" stripe>
|
||||||
<el-table-column property="Name" :label="$t('server.relayName')">
|
<el-table-column property="Name" :label="$t('server.relayName')">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
@@ -25,7 +36,7 @@
|
|||||||
</p>
|
</p>
|
||||||
<p class="flex">
|
<p class="flex">
|
||||||
<div>
|
<div>
|
||||||
<template v-if="state.syncData.Key == scope.row.Id">
|
<template v-if="state.syncData.Key == scope.row.NodeId">
|
||||||
<el-checkbox size="small" disabled checked>{{ $t('server.relayDefault') }}</el-checkbox>
|
<el-checkbox size="small" disabled checked>{{ $t('server.relayDefault') }}</el-checkbox>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
@@ -33,8 +44,12 @@
|
|||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<span class="flex-1"></span>
|
<span class="flex-1"></span>
|
||||||
<a v-if="state.super" href="javascript:;" class="a-line a-edit" @click="handleUpdate(scope.row)"><el-icon><Refresh /></el-icon>{{ scope.row.Version }}</a>
|
<AccessBoolean value="UpgradeRelayNode">
|
||||||
<a v-else href="javascript:;" class="a-line a-edit"><el-icon><Refresh /></el-icon>{{ scope.row.Version }}</a>
|
<template #default="{values}">
|
||||||
|
<a v-if="state.super && values.UpgradeRelayNode" href="javascript:;" class="a-line a-edit" @click="handleUpgrade(scope.row)"><el-icon><Refresh /></el-icon>{{ scope.row.Version }}</a>
|
||||||
|
<a v-else href="javascript:;" class="a-line a-edit"><el-icon><Refresh /></el-icon>{{ scope.row.Version }}</a>
|
||||||
|
</template>
|
||||||
|
</AccessBoolean>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -79,11 +94,21 @@
|
|||||||
<p>{{ scope.row.Delay }}ms</p>
|
<p>{{ scope.row.Delay }}ms</p>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column v-if="state.super" property="Manageable" :label="$t('server.relayOper')" width="110">
|
<el-table-column property="Manageable" :label="$t('server.relayOper')" width="110">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<p>
|
<p>
|
||||||
<el-button v-if="scope.row.Manageable" size="small" @click="handleExit(scope.row)"><el-icon><Refresh /></el-icon></el-button>
|
<AccessBoolean v-if="state.super" value="RemoveRelayNode,UpdateRelayNode,ShareRelayNode,RebootRelayNode">
|
||||||
<el-button size="small" @click="handleEdit(scope.row)"><el-icon><Edit /></el-icon></el-button>
|
<template #default="{values}">
|
||||||
|
<p>
|
||||||
|
<el-button v-if="scope.row.Manageable && values.RebootRelayNode" type="warning" size="small" @click="handleExit(scope.row)"><el-icon><Refresh /></el-icon></el-button>
|
||||||
|
<el-button v-if="values.UpdateRelayNode" size="small" @click="handleEdit(scope.row)"><el-icon><Edit /></el-icon></el-button>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<el-button v-if="values.RemoveRelayNode" type="danger" size="small" @click="handleRemove(scope.row)"><el-icon><CircleClose /></el-icon></el-button>
|
||||||
|
<el-button v-if="scope.row.Manageable && values.ShareRelayNode" type="info" size="small" @click="handleShare(scope.row)"><el-icon><Share /></el-icon></el-button>
|
||||||
|
</p>
|
||||||
|
</template>
|
||||||
|
</AccessBoolean>
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -104,19 +129,19 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { getDefault,relayEdit,relayExit,relayUpdate,syncDefault } from '@/apis/relay';
|
import { getDefault,relayExit,relayImport,relayRemove,relayShare,relayUpgrade,syncDefault } from '@/apis/relay';
|
||||||
import { injectGlobalData } from '@/provide';
|
import { injectGlobalData } from '@/provide';
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||||
import { computed, onMounted, onUnmounted, reactive, ref, watch } from 'vue'
|
import { computed, onMounted, onUnmounted, reactive, ref, watch } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import Ids from '../sync/Ids.vue';
|
import Ids from '../sync/Ids.vue';
|
||||||
import EditNode from './EditNode.vue';
|
import EditNode from './EditNode.vue';
|
||||||
import { Edit,ArrowDown,Refresh } from '@element-plus/icons-vue';
|
import { Edit,ArrowDown,Refresh,CircleClose,Plus,Share } from '@element-plus/icons-vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['modelValue','data'],
|
props: ['modelValue','data'],
|
||||||
emits: ['update:modelValue','success'],
|
emits: ['update:modelValue','success'],
|
||||||
components:{Ids,EditNode,Edit,ArrowDown,Refresh},
|
components:{Ids,EditNode,Edit,ArrowDown,Refresh,CircleClose,Plus,Share},
|
||||||
setup(props,{emit}) {
|
setup(props,{emit}) {
|
||||||
const {t} = useI18n();
|
const {t} = useI18n();
|
||||||
const globalData = injectGlobalData();
|
const globalData = injectGlobalData();
|
||||||
@@ -154,7 +179,7 @@ export default {
|
|||||||
}
|
}
|
||||||
const domIds = ref(null);
|
const domIds = ref(null);
|
||||||
const handleShowSync = (row,proto)=>{
|
const handleShowSync = (row,proto)=>{
|
||||||
state.syncData.Key = row.Id;
|
state.syncData.Key = row.NodeId;
|
||||||
state.syncData.Value = proto;
|
state.syncData.Value = proto;
|
||||||
state.showSync = true;
|
state.showSync = true;
|
||||||
}
|
}
|
||||||
@@ -176,39 +201,29 @@ export default {
|
|||||||
_getDefault();
|
_getDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSync2Server = (row)=>{
|
|
||||||
row.Sync2Server = !row.Sync2Server;
|
|
||||||
row.AllowTcp= (row.AllowProtocol & 1) == 1,
|
|
||||||
row.AllowUdp = (row.AllowProtocol & 2) == 2,
|
|
||||||
relayEdit(row).then(res => {
|
|
||||||
ElMessage.success(t('common.oper'));
|
|
||||||
}).catch(()=>{
|
|
||||||
ElMessage.error(t('common.operFail'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const handleExit = (row)=>{
|
const handleExit = (row)=>{
|
||||||
ElMessageBox.confirm(t('server.relayExit'), t('common.confirm'), {
|
ElMessageBox.confirm(t('server.relayExit'), t('common.confirm'), {
|
||||||
confirmButtonText: t('common.confirm'),
|
confirmButtonText: t('common.confirm'),
|
||||||
cancelButtonText: t('common.cancel'),
|
cancelButtonText: t('common.cancel'),
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
relayExit(row.Id).then(res => {
|
relayExit(row.NodeId).then(res => {
|
||||||
ElMessage.success(t('common.oper'));
|
ElMessage.success(t('common.oper'));
|
||||||
}).catch(()=>{
|
}).catch(()=>{
|
||||||
ElMessage.error(t('common.operFail'));
|
ElMessage.error(t('common.operFail'));
|
||||||
});
|
});
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
ElMessage.error(t('common.operFail'));
|
//ElMessage.error(t('common.operFail'));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const handleUpdate = (row)=>{
|
const handleUpgrade = (row)=>{
|
||||||
if(row.Manageable == false) return;
|
if(row.Manageable == false) return;
|
||||||
ElMessageBox.confirm(`${t('server.relayUpdate')} ${globalData.value.signin.Version}`,t('server.relayUpdate'), {
|
ElMessageBox.confirm(`${t('server.relayUpdate')} ${globalData.value.signin.Version}`,t('server.relayUpdate'), {
|
||||||
confirmButtonText: t('common.confirm'),
|
confirmButtonText: t('common.confirm'),
|
||||||
cancelButtonText: t('common.cancel'),
|
cancelButtonText: t('common.cancel'),
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
relayUpdate({Key:row.Id,Value:globalData.value.signin.Version}).then(res => {
|
relayUpgrade({Key:row.NodeId,Value:globalData.value.signin.Version}).then(res => {
|
||||||
ElMessage.success(t('common.oper'));
|
ElMessage.success(t('common.oper'));
|
||||||
}).catch(()=>{
|
}).catch(()=>{
|
||||||
ElMessage.error(t('common.operFail'));
|
ElMessage.error(t('common.operFail'));
|
||||||
@@ -218,6 +233,52 @@ export default {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleRemove = (row)=>{
|
||||||
|
ElMessageBox.confirm(t('server.relayRemove'), t('common.confirm'), {
|
||||||
|
confirmButtonText: t('common.confirm'),
|
||||||
|
cancelButtonText: t('common.cancel'),
|
||||||
|
type: 'warning',
|
||||||
|
}).then(() => {
|
||||||
|
relayRemove(row.NodeId).then(res => {
|
||||||
|
ElMessage.success(t('common.oper'));
|
||||||
|
}).catch(()=>{
|
||||||
|
ElMessage.error(t('common.operFail'));
|
||||||
|
});
|
||||||
|
}).catch(() => {
|
||||||
|
//ElMessage.error(t('common.operFail'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const handleImport = ()=>{
|
||||||
|
ElMessageBox.prompt(t('server.relayImport'), t('common.confirm'), {
|
||||||
|
confirmButtonText: t('common.confirm'),
|
||||||
|
cancelButtonText: t('common.cancel')
|
||||||
|
}).then(({ value }) => {
|
||||||
|
if(!value) return;
|
||||||
|
relayImport(value).then((res)=>{
|
||||||
|
if(res){
|
||||||
|
ElMessage.error(res);
|
||||||
|
}else{
|
||||||
|
ElMessage.success(t('common.oper'));
|
||||||
|
}
|
||||||
|
}).catch(()=>{})
|
||||||
|
}).catch(() => {
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const handleShare = (row)=>{
|
||||||
|
relayShare(row.NodeId).then((res)=>{
|
||||||
|
ElMessageBox.prompt(t('server.relayShare'), t('common.tips'), {
|
||||||
|
confirmButtonText: t('common.confirm'),
|
||||||
|
cancelButtonText: t('common.cancel'),
|
||||||
|
inputValue:res
|
||||||
|
}).then(({ value }) => {
|
||||||
|
navigator.clipboard.writeText(value)
|
||||||
|
}).catch(() => {
|
||||||
|
})
|
||||||
|
}).catch(()=>{
|
||||||
|
ElMessage.error(t('common.operFail'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(()=>{
|
onMounted(()=>{
|
||||||
_getDefault();
|
_getDefault();
|
||||||
});
|
});
|
||||||
@@ -227,7 +288,7 @@ export default {
|
|||||||
|
|
||||||
return {globalData,state,
|
return {globalData,state,
|
||||||
handleEdit,domIds,handleShowSync,handleSync,handleCancelSync,
|
handleEdit,domIds,handleShowSync,handleSync,handleCancelSync,
|
||||||
handleExit,handleUpdate,handleSync2Server}
|
handleExit,handleUpgrade,handleRemove,handleImport,handleShare}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog v-model="state.show" append-to=".app-wrap" :title="`与[${state.device.MachineName}]的链接`" top="1vh" width="350">
|
<el-dialog v-model="state.show" append-to=".app-wrap" :title="`与[${state.device.MachineName}]的链接`" top="1vh" width="350">
|
||||||
<div>
|
<div>
|
||||||
<el-descriptions border size="small" :column="1" column-max-width="120px" overlength-control="wrap">
|
<el-descriptions border size="small" :column="1" label-width="6rem" overlength-control="wrap">
|
||||||
<el-descriptions-item label="目标">{{ state.connection.IPEndPoint || '0.0.0.0:0' }}</el-descriptions-item>
|
<el-descriptions-item label="目标" >{{ state.connection.IPEndPoint }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="事务">{{ state.transactions[state.connection.TransactionId] }}</el-descriptions-item>
|
<el-descriptions-item label="事务" >{{ state.transactions[state.connection.TransactionId] }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="协议">
|
<el-descriptions-item label="协议" >
|
||||||
<div>
|
<div v-if="state.connection.Connected">
|
||||||
<p>{{ state.connection.TransportName }}({{ state.protocolTypes[state.connection.ProtocolType] }}) - {{ state.types[state.connection.Type] }}</p>
|
<p>{{ state.connection.TransportName }}({{ state.protocolTypes[state.connection.ProtocolType] }}) - {{ state.types[state.connection.Type] }}</p>
|
||||||
<p>{{ state.connection.SendBufferRemainingText }} - {{ state.connection.RecvBufferRemainingText }}</p>
|
<p>{{ state.connection.SendBufferRemainingText }} - {{ state.connection.RecvBufferRemainingText }}</p>
|
||||||
</div>
|
</div>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="SSL">{{ state.connection.SSL }}</el-descriptions-item>
|
<el-descriptions-item label="SSL" >{{ state.connection.SSL }}</el-descriptions-item>
|
||||||
|
|
||||||
<el-descriptions-item label="上传">
|
<el-descriptions-item label="上传" >
|
||||||
<div>
|
<div>
|
||||||
<p><span>{{ state.connection.SendBytesText }}</span></p>
|
<p><span>{{ state.connection.SendBytesText }}</span></p>
|
||||||
</div>
|
</div>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="下载">
|
<el-descriptions-item label="下载" >
|
||||||
<div>
|
<div>
|
||||||
<p><span>{{ state.connection.ReceiveBytesText }}</span></p>
|
<p><span>{{ state.connection.ReceiveBytesText }}</span></p>
|
||||||
</div>
|
</div>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
|
|
||||||
<el-descriptions-item label="中继">
|
<el-descriptions-item label="中继" >
|
||||||
<div>
|
<div>
|
||||||
<a v-if="state.connecting" href="javascript:;" class="a-line">
|
<a v-if="state.connecting" href="javascript:;" class="a-line">
|
||||||
<span>操作中.</span><el-icon size="14" class="loading"><Loading /></el-icon>
|
<span>操作中.</span><el-icon size="14" class="loading"><Loading /></el-icon>
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
<a v-else href="javascript:;" class="a-line" @click="handleNode">{{ state.nodesDic[state.connection.NodeId] || '选择节点' }}</a>
|
<a v-else href="javascript:;" class="a-line" @click="handleNode">{{ state.nodesDic[state.connection.NodeId] || '选择节点' }}</a>
|
||||||
</div>
|
</div>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="打洞">
|
<el-descriptions-item label="打洞" >
|
||||||
<div>
|
<div>
|
||||||
<a v-if="state.connecting" href="javascript:;" class="a-line">
|
<a v-if="state.connecting" href="javascript:;" class="a-line">
|
||||||
<span>操作中.</span><el-icon size="14" class="loading"><Loading /></el-icon>
|
<span>操作中.</span><el-icon size="14" class="loading"><Loading /></el-icon>
|
||||||
@@ -39,8 +39,8 @@
|
|||||||
<a v-else href="javascript:;" class="a-line" @click="handlep2p">尝试打洞</a>
|
<a v-else href="javascript:;" class="a-line" @click="handlep2p">尝试打洞</a>
|
||||||
</div>
|
</div>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="延迟">{{ state.connection.Delay }}</el-descriptions-item>
|
<el-descriptions-item label="延迟" >{{ state.connection.Delay }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="操作">
|
<el-descriptions-item label="操作" >
|
||||||
<div>
|
<div>
|
||||||
<AccessShow value="TunnelRemove">
|
<AccessShow value="TunnelRemove">
|
||||||
<el-popconfirm confirm-button-text="确认" cancel-button-text="取消"
|
<el-popconfirm confirm-button-text="确认" cancel-button-text="取消"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog v-model="state.show" append-to=".app-wrap" :title="state.title" top="1vh" width="370">
|
<el-dialog v-model="state.show" append-to=".app-wrap" :title="state.title" top="1vh" width="400">
|
||||||
<div>
|
<div>
|
||||||
<el-descriptions border size="small" :column="1" column-max-width="120px" overlength-control="wrap">
|
<el-descriptions border size="small" :column="1" label-width="8rem" overlength-control="wrap">
|
||||||
<el-descriptions-item label="名称">{{ state.status.Info.Name }}</el-descriptions-item>
|
<el-descriptions-item label="名称">{{ state.status.Info.Name }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="带宽">
|
<el-descriptions-item label="带宽">
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
Reference in New Issue
Block a user