cdkey
57
readme/Demo/Controller/Api.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Plugin\Demo\Controller;
|
||||
|
||||
use App\Controller\Base\API\UserPlugin;
|
||||
use App\Interceptor\Waf;
|
||||
use App\Entity\CreateObjectEntity;
|
||||
use App\Entity\DeleteBatchEntity;
|
||||
use App\Entity\QueryTemplateEntity;
|
||||
use App\Service\Query;
|
||||
use App\Util\Date;
|
||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||
use Kernel\Annotation\Inject;
|
||||
use Kernel\Annotation\Interceptor;
|
||||
use Kernel\Exception\JSONException;
|
||||
use App\Model\Card;
|
||||
use App\Model\Commodity;
|
||||
|
||||
class Api extends UserPlugin
|
||||
{
|
||||
#[Inject]
|
||||
private Query $query;
|
||||
public function check():string {
|
||||
$num = (int)($_REQUEST['num'] ?? 10);
|
||||
$key = $_REQUEST['key'];
|
||||
if ($key != getPluginConfig("Demo")['KeyId']) {
|
||||
return "fail";
|
||||
}
|
||||
|
||||
$list = Commodity::query()->where("status", 1)->get();
|
||||
foreach($list as $item)
|
||||
{
|
||||
try{
|
||||
$delivery_message = json_decode($item["delivery_message"],true);
|
||||
$commodity_id = $item["id"];
|
||||
$count = Card::query()->where("commodity_id", (int)$commodity_id)->where("status", 0)->count();
|
||||
if($count < $num)
|
||||
{
|
||||
for($i = 0; $i < $num; $i++)
|
||||
{
|
||||
$cardObj = new \App\Model\Card();
|
||||
$cardObj->commodity_id = $commodity_id;
|
||||
$cardObj->owner = 0;
|
||||
$cardObj->secret = json_encode($delivery_message,JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
$cardObj->create_time = Date::current();
|
||||
$cardObj->save();
|
||||
}
|
||||
}
|
||||
}catch(\Exception $e){
|
||||
}
|
||||
}
|
||||
|
||||
return "ok";
|
||||
}
|
||||
|
||||
}
|
BIN
readme/logo.png
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
@@ -162,7 +162,7 @@ namespace linker.messenger.relay
|
||||
return new RelayServerCdkeyTestResultInfo();
|
||||
}
|
||||
|
||||
public async Task<bool> ImportCdkey(ApiControllerParamsInfo param)
|
||||
public async Task<string> ImportCdkey(ApiControllerParamsInfo param)
|
||||
{
|
||||
RelayServerCdkeyImportInfo info = param.Content.DeJson<RelayServerCdkeyImportInfo>();
|
||||
info.SecretKey = relayClientStore.Server.SecretKey;
|
||||
@@ -173,6 +173,25 @@ namespace linker.messenger.relay
|
||||
MessengerId = (ushort)RelayMessengerIds.ImportCdkey,
|
||||
Payload = serializer.Serialize(info)
|
||||
});
|
||||
if (resp.Code == MessageResponeCodes.OK)
|
||||
{
|
||||
return serializer.Deserialize<string>(resp.Data.Span);
|
||||
}
|
||||
return "Network";
|
||||
}
|
||||
public async Task<bool> UpdateNode(ApiControllerParamsInfo param)
|
||||
{
|
||||
RelayServerNodeUpdateInfo info = param.Content.DeJson<RelayServerNodeUpdateInfo>();
|
||||
var resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||
{
|
||||
Connection = signInClientState.Connection,
|
||||
MessengerId = (ushort)RelayMessengerIds.UpdateNodeForward,
|
||||
Payload = serializer.Serialize(new RelayServerNodeUpdateWrapInfo
|
||||
{
|
||||
Info = info,
|
||||
SecretKey = relayClientStore.Server.SecretKey
|
||||
})
|
||||
});
|
||||
return resp.Code == MessageResponeCodes.OK && resp.Data.Span.SequenceEqual(Helper.TrueArray);
|
||||
}
|
||||
}
|
||||
|
@@ -43,7 +43,7 @@ namespace linker.messenger.relay
|
||||
IRelayClientTransport transport = relayTransfer.Transports.FirstOrDefault(d => d.Type == relayClientStore.Server.RelayType);
|
||||
if (transport != null)
|
||||
{
|
||||
Nodes = await transport.RelayTestAsync(new RelayTestInfo
|
||||
Nodes = await transport.RelayTestAsync(new RelayTestInfo170
|
||||
{
|
||||
MachineId = signInClientStore.Id,
|
||||
SecretKey = relayClientStore.Server.SecretKey,
|
||||
|
@@ -78,7 +78,7 @@ namespace linker.messenger.relay.client
|
||||
return null;
|
||||
}
|
||||
|
||||
transport.RelayInfo relayInfo = new transport.RelayInfo
|
||||
transport.RelayInfo170 relayInfo = new transport.RelayInfo170
|
||||
{
|
||||
FlowingId = 0,
|
||||
FromMachineId = fromMachineId,
|
||||
@@ -126,7 +126,7 @@ namespace linker.messenger.relay.client
|
||||
/// </summary>
|
||||
/// <param name="relayInfo"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> OnBeginAsync(transport.RelayInfo relayInfo)
|
||||
public async Task<bool> OnBeginAsync(transport.RelayInfo170 relayInfo)
|
||||
{
|
||||
if (connectingDic.TryAdd(relayInfo.FromMachineId, true) == false)
|
||||
{
|
||||
@@ -173,7 +173,7 @@ namespace linker.messenger.relay.client
|
||||
/// </summary>
|
||||
/// <param name="relayInfo"></param>
|
||||
/// <param name="connection"></param>
|
||||
private void ConnectedCallback(transport.RelayInfo relayInfo, ITunnelConnection connection)
|
||||
private void ConnectedCallback(transport.RelayInfo170 relayInfo, ITunnelConnection connection)
|
||||
{
|
||||
if (OnConnected.TryGetValue(Helper.GlobalString, out List<Action<ITunnelConnection>> callbacks))
|
||||
{
|
||||
|
@@ -34,37 +34,51 @@ namespace linker.messenger.relay.client.transport
|
||||
/// </summary>
|
||||
/// <param name="relayInfo"></param>
|
||||
/// <returns></returns>
|
||||
public Task<ITunnelConnection> RelayAsync(RelayInfo relayInfo);
|
||||
public Task<ITunnelConnection> RelayAsync(RelayInfo170 relayInfo);
|
||||
/// <summary>
|
||||
/// 收到别人的中继请求
|
||||
/// </summary>
|
||||
/// <param name="relayInfo"></param>
|
||||
/// <returns></returns>
|
||||
public Task<bool> OnBeginAsync(RelayInfo relayInfo, Action<ITunnelConnection> callback);
|
||||
public Task<bool> OnBeginAsync(RelayInfo170 relayInfo, Action<ITunnelConnection> callback);
|
||||
|
||||
/// <summary>
|
||||
/// 测试一下中继通不通
|
||||
/// </summary>
|
||||
/// <param name="relayTestInfo"></param>
|
||||
/// <returns></returns>
|
||||
public Task<List<RelayServerNodeReportInfo>> RelayTestAsync(RelayTestInfo relayTestInfo);
|
||||
public Task<List<RelayServerNodeReportInfo>> RelayTestAsync(RelayTestInfo170 relayTestInfo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 中继测试
|
||||
/// </summary>
|
||||
public sealed partial class RelayTestInfo
|
||||
public partial class RelayTestInfo
|
||||
{
|
||||
public string MachineId { get; set; }
|
||||
public string SecretKey { get; set; }
|
||||
public IPEndPoint Server { get; set; }
|
||||
}
|
||||
public sealed partial class RelayTestInfo170: RelayTestInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// UserId
|
||||
/// </summary>
|
||||
public string UserId { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public partial class RelayInfo170 : RelayInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// UserId
|
||||
/// </summary>
|
||||
public string UserId { get; set; }
|
||||
}
|
||||
/// <summary>
|
||||
/// 中继交换数据
|
||||
/// </summary>
|
||||
public sealed partial class RelayInfo
|
||||
public partial class RelayInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 自己的id
|
||||
@@ -114,10 +128,7 @@ namespace linker.messenger.relay.client.transport
|
||||
/// </summary>
|
||||
public bool SSL { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// UserId
|
||||
/// </summary>
|
||||
public string UserId { get; set; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@@ -38,7 +38,7 @@ namespace linker.messenger.relay.client.transport
|
||||
this.messengerStore = messengerStore;
|
||||
}
|
||||
|
||||
public async Task<ITunnelConnection> RelayAsync(RelayInfo relayInfo)
|
||||
public async Task<ITunnelConnection> RelayAsync(RelayInfo170 relayInfo)
|
||||
{
|
||||
byte[] buffer = ArrayPool<byte>.Shared.Rent(1024);
|
||||
try
|
||||
@@ -119,12 +119,12 @@ namespace linker.messenger.relay.client.transport
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task<RelayAskResultInfo> RelayAsk(RelayInfo relayInfo)
|
||||
private async Task<RelayAskResultInfo> RelayAsk(RelayInfo170 relayInfo)
|
||||
{
|
||||
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||
{
|
||||
Connection = signInClientState.Connection,
|
||||
MessengerId = (ushort)RelayMessengerIds.RelayAsk,
|
||||
MessengerId = (ushort)RelayMessengerIds.RelayAsk170,
|
||||
Payload = serializer.Serialize(relayInfo),
|
||||
Timeout = 2000
|
||||
}).ConfigureAwait(false);
|
||||
@@ -138,7 +138,7 @@ namespace linker.messenger.relay.client.transport
|
||||
return result;
|
||||
|
||||
}
|
||||
private async Task<Socket> ConnectNodeServer(RelayInfo relayInfo, List<RelayServerNodeReportInfo> nodes)
|
||||
private async Task<Socket> ConnectNodeServer(RelayInfo170 relayInfo, List<RelayServerNodeReportInfo> nodes)
|
||||
{
|
||||
byte[] buffer = ArrayPool<byte>.Shared.Rent(1 * 1024);
|
||||
|
||||
@@ -211,13 +211,13 @@ namespace linker.messenger.relay.client.transport
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private async Task<bool> RelayConfirm(RelayInfo relayInfo)
|
||||
private async Task<bool> RelayConfirm(RelayInfo170 relayInfo)
|
||||
{
|
||||
//通知对方去确认中继
|
||||
var resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||
{
|
||||
Connection = signInClientState.Connection,
|
||||
MessengerId = (ushort)RelayMessengerIds.RelayForward,
|
||||
MessengerId = (ushort)RelayMessengerIds.RelayForward170,
|
||||
Payload = serializer.Serialize(relayInfo),
|
||||
});
|
||||
return resp.Code == MessageResponeCodes.OK && resp.Data.Span.SequenceEqual(Helper.TrueArray);
|
||||
@@ -228,7 +228,7 @@ namespace linker.messenger.relay.client.transport
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public async Task<bool> OnBeginAsync(RelayInfo relayInfo, Action<ITunnelConnection> callback)
|
||||
public async Task<bool> OnBeginAsync(RelayInfo170 relayInfo, Action<ITunnelConnection> callback)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -267,7 +267,7 @@ namespace linker.messenger.relay.client.transport
|
||||
return false;
|
||||
}
|
||||
|
||||
private async Task<TunnelConnectionTcp> WaitSSL(Socket socket, RelayInfo relayInfo)
|
||||
private async Task<TunnelConnectionTcp> WaitSSL(Socket socket, RelayInfo170 relayInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -306,14 +306,14 @@ namespace linker.messenger.relay.client.transport
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<List<RelayServerNodeReportInfo>> RelayTestAsync(RelayTestInfo relayTestInfo)
|
||||
public async Task<List<RelayServerNodeReportInfo>> RelayTestAsync(RelayTestInfo170 relayTestInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||
{
|
||||
Connection = signInClientState.Connection,
|
||||
MessengerId = (ushort)RelayMessengerIds.RelayTest,
|
||||
MessengerId = (ushort)RelayMessengerIds.RelayTest170,
|
||||
Payload = serializer.Serialize(relayTestInfo),
|
||||
Timeout = 2000
|
||||
}).ConfigureAwait(false);
|
||||
|
@@ -30,7 +30,7 @@ namespace linker.messenger.relay.messenger
|
||||
[MessengerId((ushort)RelayMessengerIds.Relay)]
|
||||
public async Task Relay(IConnection connection)
|
||||
{
|
||||
client.transport.RelayInfo info = serializer.Deserialize<client.transport.RelayInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||
client.transport.RelayInfo170 info = serializer.Deserialize<client.transport.RelayInfo170>(connection.ReceiveRequestWrap.Payload.Span);
|
||||
bool res = await relayTransfer.OnBeginAsync(info).ConfigureAwait(false);
|
||||
connection.Write(res ? Helper.TrueArray : Helper.FalseArray);
|
||||
}
|
||||
@@ -48,8 +48,9 @@ namespace linker.messenger.relay.messenger
|
||||
private readonly ISerializer serializer;
|
||||
private readonly IRelayServerCdkeyStore relayServerCdkeyStore;
|
||||
private readonly IRelayServerStore relayServerStore;
|
||||
private readonly RelayServerNodeTransfer relayServerNodeTransfer;
|
||||
|
||||
public RelayServerMessenger(IMessengerSender messengerSender, SignInServerCaching signCaching, ISerializer serializer, RelayServerMasterTransfer relayServerTransfer, RelayServerValidatorTransfer relayValidatorTransfer, IRelayServerCdkeyStore relayServerCdkeyStore, IRelayServerStore relayServerStore)
|
||||
public RelayServerMessenger(IMessengerSender messengerSender, SignInServerCaching signCaching, ISerializer serializer, RelayServerMasterTransfer relayServerTransfer, RelayServerValidatorTransfer relayValidatorTransfer, IRelayServerCdkeyStore relayServerCdkeyStore, IRelayServerStore relayServerStore, RelayServerNodeTransfer relayServerNodeTransfer)
|
||||
{
|
||||
this.messengerSender = messengerSender;
|
||||
this.signCaching = signCaching;
|
||||
@@ -58,6 +59,7 @@ namespace linker.messenger.relay.messenger
|
||||
this.serializer = serializer;
|
||||
this.relayServerCdkeyStore = relayServerCdkeyStore;
|
||||
this.relayServerStore = relayServerStore;
|
||||
this.relayServerNodeTransfer = relayServerNodeTransfer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -68,6 +70,16 @@ namespace linker.messenger.relay.messenger
|
||||
public async Task RelayTest(IConnection connection)
|
||||
{
|
||||
RelayTestInfo info = serializer.Deserialize<RelayTestInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||
await RelayTest(connection, info);
|
||||
}
|
||||
[MessengerId((ushort)RelayMessengerIds.RelayTest170)]
|
||||
public async Task RelayTest170(IConnection connection)
|
||||
{
|
||||
RelayTestInfo170 info = serializer.Deserialize<RelayTestInfo170>(connection.ReceiveRequestWrap.Payload.Span);
|
||||
await RelayTest(connection, info);
|
||||
}
|
||||
private async Task RelayTest(IConnection connection, RelayTestInfo info)
|
||||
{
|
||||
if (signCaching.TryGet(connection.Id, out SignCacheInfo cache) == false)
|
||||
{
|
||||
connection.Write(Helper.FalseArray);
|
||||
@@ -86,7 +98,6 @@ namespace linker.messenger.relay.messenger
|
||||
connection.Write(serializer.Serialize(nodes));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 请求中继
|
||||
/// </summary>
|
||||
@@ -95,6 +106,18 @@ namespace linker.messenger.relay.messenger
|
||||
public async Task RelayAsk(IConnection connection)
|
||||
{
|
||||
RelayInfo info = serializer.Deserialize<RelayInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||
await RelayAsk(connection, info, new List<RelayServerCdkeyInfo>());
|
||||
}
|
||||
[MessengerId((ushort)RelayMessengerIds.RelayAsk170)]
|
||||
public async Task RelayAsk170(IConnection connection)
|
||||
{
|
||||
RelayInfo170 info = serializer.Deserialize<RelayInfo170>(connection.ReceiveRequestWrap.Payload.Span);
|
||||
|
||||
List<RelayServerCdkeyInfo> cdkeys = (await relayServerCdkeyStore.GetAvailable(info.UserId)).Select(c => new RelayServerCdkeyInfo { Bandwidth = c.Bandwidth, CdkeyId = c.CdkeyId, LastBytes = c.LastBytes }).ToList();
|
||||
await RelayAsk(connection, info, cdkeys);
|
||||
}
|
||||
public async Task RelayAsk(IConnection connection, RelayInfo info, List<RelayServerCdkeyInfo> cdkeys)
|
||||
{
|
||||
if (signCaching.TryGet(connection.Id, out SignCacheInfo cacheFrom) == false || signCaching.TryGet(info.RemoteMachineId, out SignCacheInfo cacheTo) == false || cacheFrom.GroupId != cacheTo.GroupId)
|
||||
{
|
||||
connection.Write(serializer.Serialize(new RelayAskResultInfo { }));
|
||||
@@ -111,11 +134,9 @@ namespace linker.messenger.relay.messenger
|
||||
bool validated = string.IsNullOrWhiteSpace(error);
|
||||
result.Nodes = relayServerTransfer.GetNodes(validated);
|
||||
|
||||
List<RelayServerCdkeyStoreInfo> cdkeys = await relayServerCdkeyStore.GetAvailable(info.UserId);
|
||||
|
||||
if (result.Nodes.Count > 0)
|
||||
{
|
||||
result.FlowingId = relayServerTransfer.AddRelay(cacheFrom.MachineId, cacheFrom.MachineName, cacheTo.MachineId, cacheTo.MachineName, cacheFrom.GroupId, validated, cdkeys.Select(c => new RelayServerCdkeyInfo { Bandwidth = c.Bandwidth, CdkeyId = c.CdkeyId, LastBytes = c.LastBytes }).ToList());
|
||||
result.FlowingId = relayServerTransfer.AddRelay(cacheFrom.MachineId, cacheFrom.MachineName, cacheTo.MachineId, cacheTo.MachineName, cacheFrom.GroupId, validated, cdkeys);
|
||||
}
|
||||
|
||||
connection.Write(serializer.Serialize(result));
|
||||
@@ -129,7 +150,23 @@ namespace linker.messenger.relay.messenger
|
||||
[MessengerId((ushort)RelayMessengerIds.RelayForward)]
|
||||
public async Task RelayForward(IConnection connection)
|
||||
{
|
||||
client.transport.RelayInfo info = serializer.Deserialize<client.transport.RelayInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||
RelayInfo info = serializer.Deserialize<RelayInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||
await RelayForward(connection, info, () =>
|
||||
{
|
||||
return serializer.Serialize(info);
|
||||
});
|
||||
}
|
||||
[MessengerId((ushort)RelayMessengerIds.RelayForward170)]
|
||||
public async Task RelayForward170(IConnection connection)
|
||||
{
|
||||
RelayInfo170 info = serializer.Deserialize<RelayInfo170>(connection.ReceiveRequestWrap.Payload.Span);
|
||||
await RelayForward(connection, info, () =>
|
||||
{
|
||||
return serializer.Serialize(info);
|
||||
});
|
||||
}
|
||||
public async Task RelayForward(IConnection connection, RelayInfo info, Func<byte[]> data)
|
||||
{
|
||||
if (signCaching.TryGet(connection.Id, out SignCacheInfo cacheFrom) == false || signCaching.TryGet(info.RemoteMachineId, out SignCacheInfo cacheTo) == false || cacheFrom.GroupId != cacheTo.GroupId)
|
||||
{
|
||||
connection.Write(Helper.FalseArray);
|
||||
@@ -161,7 +198,7 @@ namespace linker.messenger.relay.messenger
|
||||
{
|
||||
Connection = cacheTo.Connection,
|
||||
MessengerId = (ushort)RelayMessengerIds.Relay,
|
||||
Payload = serializer.Serialize(info)
|
||||
Payload = data()
|
||||
}).ConfigureAwait(false);
|
||||
if (resp.Code == MessageResponeCodes.OK && resp.Data.Span.SequenceEqual(Helper.TrueArray))
|
||||
{
|
||||
@@ -210,6 +247,40 @@ namespace linker.messenger.relay.messenger
|
||||
}
|
||||
relayServerTransfer.SetNodeReport(connection, info);
|
||||
}
|
||||
/// <summary>
|
||||
/// 更新节点
|
||||
/// </summary>
|
||||
/// <param name="connection"></param>
|
||||
/// <returns></returns>
|
||||
[MessengerId((ushort)RelayMessengerIds.UpdateNode)]
|
||||
public void UpdateNode(IConnection connection)
|
||||
{
|
||||
RelayServerNodeUpdateInfo info = serializer.Deserialize<RelayServerNodeUpdateInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||
if (relayServerNodeTransfer.Id == info.Id)
|
||||
{
|
||||
relayServerNodeTransfer.UpdateNode(info);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 更新节点转发
|
||||
/// </summary>
|
||||
/// <param name="connection"></param>
|
||||
/// <returns></returns>
|
||||
[MessengerId((ushort)RelayMessengerIds.UpdateNodeForward)]
|
||||
public async Task UpdateNodeForward(IConnection connection)
|
||||
{
|
||||
RelayServerNodeUpdateWrapInfo info = serializer.Deserialize<RelayServerNodeUpdateWrapInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||
if (info.SecretKey == relayServerStore.SecretKey)
|
||||
{
|
||||
await relayServerTransfer.UpdateNodeReport(info.Info);
|
||||
connection.Write(Helper.TrueArray);
|
||||
}
|
||||
else
|
||||
{
|
||||
connection.Write(Helper.FalseArray);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 消耗流量报告
|
||||
/// </summary>
|
||||
@@ -283,7 +354,7 @@ namespace linker.messenger.relay.messenger
|
||||
}
|
||||
else
|
||||
{
|
||||
await relayServerCdkeyStore.Del(info.CdkeyId,info.UserId);
|
||||
await relayServerCdkeyStore.Del(info.CdkeyId, info.UserId);
|
||||
}
|
||||
connection.Write(Helper.TrueArray);
|
||||
}
|
||||
@@ -351,8 +422,8 @@ namespace linker.messenger.relay.messenger
|
||||
connection.Write(Helper.FalseArray);
|
||||
return;
|
||||
}
|
||||
bool result = await relayServerCdkeyStore.Import(info);
|
||||
connection.Write(result ? Helper.TrueArray : Helper.FalseArray);
|
||||
string result = await relayServerCdkeyStore.Import(info);
|
||||
connection.Write(serializer.Serialize(result));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -29,6 +29,11 @@
|
||||
ImportCdkey = 2116,
|
||||
|
||||
UpdateNode = 2117,
|
||||
UpdateNodeForward = 2118,
|
||||
|
||||
RelayTest170 = 2119,
|
||||
RelayAsk170 = 2120,
|
||||
RelayForward170 = 2121,
|
||||
|
||||
Max = 2199
|
||||
}
|
||||
|
@@ -33,7 +33,7 @@
|
||||
/// </summary>
|
||||
/// <param name="base64"></param>
|
||||
/// <returns></returns>
|
||||
public Task<bool> Import(RelayServerCdkeyImportInfo info);
|
||||
public Task<string> Import(RelayServerCdkeyImportInfo info);
|
||||
|
||||
/// <summary>
|
||||
/// 获取有效的CDKEY
|
||||
@@ -249,5 +249,6 @@
|
||||
/// </summary>
|
||||
public int Count { get; set; }
|
||||
|
||||
public string Type { get; set; }
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
using linker.libs;
|
||||
using System.Net;
|
||||
using linker.libs.extends;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace linker.messenger.relay.server
|
||||
{
|
||||
@@ -80,10 +81,17 @@ namespace linker.messenger.relay.server
|
||||
#else
|
||||
public string MasterSecretKey { get; set; } = string.Empty;
|
||||
#endif
|
||||
public string Url { get; set; } = "https://linker-doc.snltty.com";
|
||||
}
|
||||
|
||||
public sealed partial class RelayServerNodeUpdateWrapInfo
|
||||
{
|
||||
public string SecretKey { get; set; }
|
||||
public RelayServerNodeUpdateInfo Info { get; set; }
|
||||
}
|
||||
public sealed partial class RelayServerNodeUpdateInfo
|
||||
{
|
||||
public string Id { get; set; } = string.Empty;
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
public int MaxConnection { get; set; }
|
||||
@@ -92,6 +100,8 @@ namespace linker.messenger.relay.server
|
||||
public double MaxGbTotal { get; set; }
|
||||
public long MaxGbTotalLastBytes { get; set; }
|
||||
public bool Public { get; set; }
|
||||
|
||||
public string Url { get; set; } = "https://linker-doc.snltty.com";
|
||||
}
|
||||
public sealed partial class RelayServerNodeReportInfo
|
||||
{
|
||||
@@ -114,6 +124,11 @@ namespace linker.messenger.relay.server
|
||||
public IPEndPoint EndPoint { get; set; }
|
||||
|
||||
public long LastTicks { get; set; }
|
||||
|
||||
public string Url { get; set; } = "https://linker-doc.snltty.com";
|
||||
|
||||
[JsonIgnore]
|
||||
public IConnection Connection { get; set; }
|
||||
}
|
||||
|
||||
public sealed partial class RelayAskResultInfo
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using linker.libs;
|
||||
using linker.messenger.relay.messenger;
|
||||
using linker.messenger.relay.server.caching;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Net;
|
||||
@@ -18,11 +19,14 @@ namespace linker.messenger.relay.server
|
||||
private readonly IRelayServerCaching relayCaching;
|
||||
private readonly ISerializer serializer;
|
||||
private readonly IRelayServerCdkeyStore relayServerCdkeyStore;
|
||||
public RelayServerMasterTransfer(IRelayServerCaching relayCaching, ISerializer serializer, IRelayServerMasterStore relayServerMasterStore, IRelayServerCdkeyStore relayServerCdkeyStore)
|
||||
private readonly IMessengerSender messengerSender;
|
||||
|
||||
public RelayServerMasterTransfer(IRelayServerCaching relayCaching, ISerializer serializer, IRelayServerMasterStore relayServerMasterStore, IRelayServerCdkeyStore relayServerCdkeyStore, IMessengerSender messengerSender)
|
||||
{
|
||||
this.relayCaching = relayCaching;
|
||||
this.serializer = serializer;
|
||||
this.relayServerCdkeyStore = relayServerCdkeyStore;
|
||||
this.messengerSender = messengerSender;
|
||||
TrafficTask();
|
||||
}
|
||||
|
||||
@@ -70,6 +74,7 @@ namespace linker.messenger.relay.server
|
||||
info.EndPoint.Address = connection.Address.Address;
|
||||
}
|
||||
info.LastTicks = Environment.TickCount64;
|
||||
info.Connection = connection;
|
||||
reports.AddOrUpdate(info.Id, info, (a, b) => info);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -80,6 +85,25 @@ namespace linker.messenger.relay.server
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 更新节点
|
||||
/// </summary>
|
||||
/// <param name="info"></param>
|
||||
public async Task UpdateNodeReport(RelayServerNodeUpdateInfo info)
|
||||
{
|
||||
if (RelayServerNodeInfo.MASTER_NODE_ID == info.Id) return;
|
||||
|
||||
if (reports.TryGetValue(info.Id, out RelayServerNodeReportInfo cache))
|
||||
{
|
||||
await messengerSender.SendOnly(new MessageRequestWrap
|
||||
{
|
||||
Connection = cache.Connection,
|
||||
MessengerId = (ushort)RelayMessengerIds.UpdateNode,
|
||||
Payload = serializer.Serialize(info)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取节点列表
|
||||
/// </summary>
|
||||
@@ -90,7 +114,7 @@ namespace linker.messenger.relay.server
|
||||
var result = reports.Values
|
||||
.Where(c => c.Public || validated)
|
||||
.Where(c => Environment.TickCount64 - c.LastTicks < 15000)
|
||||
.Where(c => c.ConnectionRatio < 100 && (c.MaxGbTotal == 0 || (c.MaxGbTotal > 0 && c.MaxGbTotalLastBytes > 0)))
|
||||
.Where(c => validated || (c.ConnectionRatio < 100 && (c.MaxGbTotal == 0 || (c.MaxGbTotal > 0 && c.MaxGbTotalLastBytes > 0))))
|
||||
.OrderByDescending(c => c.LastTicks);
|
||||
|
||||
return result.OrderByDescending(x => x.MaxConnection == 0 ? int.MaxValue : x.MaxConnection)
|
||||
@@ -113,7 +137,11 @@ namespace linker.messenger.relay.server
|
||||
return reports.TryGetValue(nodeId, out RelayServerNodeReportInfo relayNodeReportInfo) && relayNodeReportInfo.Public == false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 消耗流量
|
||||
/// </summary>
|
||||
/// <param name="relayTrafficUpdateInfo"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<Dictionary<long, long>> AddTraffic(RelayTrafficUpdateInfo relayTrafficUpdateInfo)
|
||||
{
|
||||
if (relayTrafficUpdateInfo.Dic.Count > 0)
|
||||
@@ -134,7 +162,7 @@ namespace linker.messenger.relay.server
|
||||
await relayServerCdkeyStore.Traffic(dic).ConfigureAwait(false);
|
||||
}
|
||||
return true;
|
||||
},3000);
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -13,6 +13,8 @@ namespace linker.messenger.relay.server
|
||||
/// </summary>
|
||||
public class RelayServerNodeTransfer
|
||||
{
|
||||
public string Id=>relayServerNodeStore.Node.Id;
|
||||
|
||||
private uint connectionNum = 0;
|
||||
private IConnection localConnection;
|
||||
private IConnection remoteConnection;
|
||||
@@ -70,6 +72,11 @@ namespace linker.messenger.relay.server
|
||||
return null;
|
||||
}
|
||||
|
||||
public void UpdateNode(RelayServerNodeUpdateInfo info)
|
||||
{
|
||||
relayServerNodeStore.UpdateInfo(info);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 无效请求
|
||||
/// </summary>
|
||||
|
@@ -50,7 +50,9 @@ namespace linker.messenger.serializer.memorypack
|
||||
|
||||
|
||||
MemoryPackFormatterProvider.Register(new RelayTestInfoFormatter());
|
||||
MemoryPackFormatterProvider.Register(new RelayTestInfo170Formatter());
|
||||
MemoryPackFormatterProvider.Register(new RelayInfoFormatter());
|
||||
MemoryPackFormatterProvider.Register(new RelayInfo170Formatter());
|
||||
MemoryPackFormatterProvider.Register(new RelayServerNodeUpdateInfoFormatter());
|
||||
MemoryPackFormatterProvider.Register(new RelayServerNodeReportInfoFormatter());
|
||||
MemoryPackFormatterProvider.Register(new RelayAskResultInfoFormatter());
|
||||
@@ -67,6 +69,9 @@ namespace linker.messenger.serializer.memorypack
|
||||
MemoryPackFormatterProvider.Register(new RelayServerCdkeyTestResultInfoFormatter());
|
||||
MemoryPackFormatterProvider.Register(new RelayServerCdkeyOrderInfoFormatter());
|
||||
|
||||
MemoryPackFormatterProvider.Register(new RelayServerNodeUpdateInfoFormatter());
|
||||
MemoryPackFormatterProvider.Register(new RelayServerNodeUpdateWrapInfoFormatter());
|
||||
|
||||
|
||||
MemoryPackFormatterProvider.Register(new AccessUpdateInfoFormatter());
|
||||
MemoryPackFormatterProvider.Register(new AccessInfoFormatter());
|
||||
|
@@ -2,6 +2,7 @@
|
||||
using linker.messenger.relay.server;
|
||||
using MemoryPack;
|
||||
using System.Net;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace linker.messenger.serializer.memorypack
|
||||
{
|
||||
@@ -18,13 +19,11 @@ namespace linker.messenger.serializer.memorypack
|
||||
|
||||
[MemoryPackInclude, MemoryPackAllowSerialize]
|
||||
IPEndPoint Server => info.Server;
|
||||
[MemoryPackInclude]
|
||||
string UserId => info.UserId;
|
||||
|
||||
[MemoryPackConstructor]
|
||||
SerializableRelayTestInfo(string machineId, string secretKey, IPEndPoint server, string userid)
|
||||
SerializableRelayTestInfo(string machineId, string secretKey, IPEndPoint server)
|
||||
{
|
||||
var info = new RelayTestInfo { MachineId = machineId, SecretKey = secretKey, Server = server, UserId = userid };
|
||||
var info = new RelayTestInfo { MachineId = machineId, SecretKey = secretKey, Server = server };
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
@@ -61,6 +60,62 @@ namespace linker.messenger.serializer.memorypack
|
||||
}
|
||||
|
||||
|
||||
[MemoryPackable]
|
||||
public readonly partial struct SerializableRelayTestInfo170
|
||||
{
|
||||
[MemoryPackIgnore]
|
||||
public readonly RelayTestInfo170 info;
|
||||
|
||||
[MemoryPackInclude]
|
||||
string MachineId => info.MachineId;
|
||||
[MemoryPackInclude]
|
||||
string SecretKey => info.SecretKey;
|
||||
|
||||
[MemoryPackInclude, MemoryPackAllowSerialize]
|
||||
IPEndPoint Server => info.Server;
|
||||
[MemoryPackInclude]
|
||||
string UserId => info.UserId;
|
||||
|
||||
[MemoryPackConstructor]
|
||||
SerializableRelayTestInfo170(string machineId, string secretKey, IPEndPoint server, string userid)
|
||||
{
|
||||
var info = new RelayTestInfo170 { MachineId = machineId, SecretKey = secretKey, Server = server, UserId = userid };
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public SerializableRelayTestInfo170(RelayTestInfo170 info)
|
||||
{
|
||||
this.info = info;
|
||||
}
|
||||
}
|
||||
public class RelayTestInfo170Formatter : MemoryPackFormatter<RelayTestInfo170>
|
||||
{
|
||||
public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref RelayTestInfo170 value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullObjectHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WritePackable(new SerializableRelayTestInfo170(value));
|
||||
}
|
||||
|
||||
public override void Deserialize(ref MemoryPackReader reader, scoped ref RelayTestInfo170 value)
|
||||
{
|
||||
if (reader.PeekIsNull())
|
||||
{
|
||||
reader.Advance(1); // skip null block
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
var wrapped = reader.ReadPackable<SerializableRelayTestInfo170>();
|
||||
value = wrapped.info;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
[MemoryPackable]
|
||||
public readonly partial struct SerializableRelayInfo
|
||||
@@ -91,14 +146,12 @@ namespace linker.messenger.serializer.memorypack
|
||||
[MemoryPackInclude]
|
||||
bool SSL => info.SSL;
|
||||
|
||||
[MemoryPackInclude]
|
||||
string UserId => info.UserId;
|
||||
|
||||
[MemoryPackConstructor]
|
||||
SerializableRelayInfo(string fromMachineId, string fromMachineName,
|
||||
string remoteMachineId, string remoteMachineName,
|
||||
string transactionId, string secretKey, string transportName, ulong flowingId,
|
||||
string nodeId, IPEndPoint server, bool ssl, string userid)
|
||||
string nodeId, IPEndPoint server, bool ssl)
|
||||
{
|
||||
var info = new RelayInfo
|
||||
{
|
||||
@@ -112,8 +165,7 @@ namespace linker.messenger.serializer.memorypack
|
||||
TransactionId = transactionId,
|
||||
TransportName = transportName,
|
||||
SecretKey = secretKey,
|
||||
Server = server,
|
||||
UserId = userid
|
||||
Server = server
|
||||
};
|
||||
this.info = info;
|
||||
}
|
||||
@@ -150,12 +202,103 @@ namespace linker.messenger.serializer.memorypack
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[MemoryPackable]
|
||||
public readonly partial struct SerializableRelayInfo170
|
||||
{
|
||||
[MemoryPackIgnore]
|
||||
public readonly RelayInfo170 info;
|
||||
|
||||
[MemoryPackInclude]
|
||||
string FromMachineId => info.FromMachineId;
|
||||
[MemoryPackInclude]
|
||||
string FromMachineName => info.FromMachineName;
|
||||
[MemoryPackInclude]
|
||||
string RemoteMachineId => info.RemoteMachineId;
|
||||
[MemoryPackInclude]
|
||||
string RemoteMachineName => info.RemoteMachineName;
|
||||
[MemoryPackInclude]
|
||||
string TransactionId => info.TransactionId;
|
||||
[MemoryPackInclude]
|
||||
string SecretKey => info.SecretKey;
|
||||
[MemoryPackInclude]
|
||||
string TransportName => info.TransportName;
|
||||
[MemoryPackInclude]
|
||||
ulong FlowingId => info.FlowingId;
|
||||
[MemoryPackInclude]
|
||||
string NodeId => info.NodeId;
|
||||
[MemoryPackInclude, MemoryPackAllowSerialize]
|
||||
IPEndPoint Server => info.Server;
|
||||
[MemoryPackInclude]
|
||||
bool SSL => info.SSL;
|
||||
|
||||
[MemoryPackInclude]
|
||||
string UserId => info.UserId;
|
||||
|
||||
[MemoryPackConstructor]
|
||||
SerializableRelayInfo170(string fromMachineId, string fromMachineName,
|
||||
string remoteMachineId, string remoteMachineName,
|
||||
string transactionId, string secretKey, string transportName, ulong flowingId,
|
||||
string nodeId, IPEndPoint server, bool ssl, string userid)
|
||||
{
|
||||
var info = new RelayInfo170
|
||||
{
|
||||
FlowingId = flowingId,
|
||||
FromMachineId = fromMachineId,
|
||||
FromMachineName = fromMachineName,
|
||||
NodeId = nodeId,
|
||||
RemoteMachineId = remoteMachineId,
|
||||
RemoteMachineName = remoteMachineName,
|
||||
SSL = ssl,
|
||||
TransactionId = transactionId,
|
||||
TransportName = transportName,
|
||||
SecretKey = secretKey,
|
||||
Server = server,
|
||||
UserId = userid
|
||||
};
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public SerializableRelayInfo170(RelayInfo170 relayInfo)
|
||||
{
|
||||
this.info = relayInfo;
|
||||
}
|
||||
}
|
||||
public class RelayInfo170Formatter : MemoryPackFormatter<RelayInfo170>
|
||||
{
|
||||
public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref RelayInfo170 value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullObjectHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WritePackable(new SerializableRelayInfo170(value));
|
||||
}
|
||||
|
||||
public override void Deserialize(ref MemoryPackReader reader, scoped ref RelayInfo170 value)
|
||||
{
|
||||
if (reader.PeekIsNull())
|
||||
{
|
||||
reader.Advance(1); // skip null block
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
var wrapped = reader.ReadPackable<SerializableRelayInfo170>();
|
||||
value = wrapped.info;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[MemoryPackable]
|
||||
public readonly partial struct SerializableRelayServerNodeUpdateInfo
|
||||
{
|
||||
[MemoryPackIgnore]
|
||||
public readonly RelayServerNodeUpdateInfo info;
|
||||
|
||||
[MemoryPackInclude]
|
||||
string Id => info.Id;
|
||||
[MemoryPackInclude]
|
||||
string Name => info.Name;
|
||||
[MemoryPackInclude]
|
||||
@@ -170,23 +313,27 @@ namespace linker.messenger.serializer.memorypack
|
||||
long MaxGbTotalLastBytes => info.MaxGbTotalLastBytes;
|
||||
[MemoryPackInclude]
|
||||
bool Public => info.Public;
|
||||
[MemoryPackInclude]
|
||||
string Url => info.Url;
|
||||
|
||||
[MemoryPackConstructor]
|
||||
SerializableRelayServerNodeUpdateInfo(
|
||||
string name,
|
||||
string id, string name,
|
||||
int maxConnection, double maxBandwidth, double maxBandwidthTotal,
|
||||
double maxGbTotal, long maxGbTotalLastBytes,
|
||||
bool Public)
|
||||
bool Public, string url)
|
||||
{
|
||||
var info = new RelayServerNodeUpdateInfo
|
||||
{
|
||||
Id = id,
|
||||
MaxBandwidth = maxBandwidth,
|
||||
MaxBandwidthTotal = maxBandwidthTotal,
|
||||
MaxConnection = maxConnection,
|
||||
MaxGbTotal = maxGbTotal,
|
||||
MaxGbTotalLastBytes = maxGbTotalLastBytes,
|
||||
Name = name,
|
||||
Public = Public
|
||||
Public = Public,
|
||||
Url = url
|
||||
};
|
||||
this.info = info;
|
||||
}
|
||||
@@ -222,6 +369,59 @@ namespace linker.messenger.serializer.memorypack
|
||||
value = wrapped.info;
|
||||
}
|
||||
}
|
||||
[MemoryPackable]
|
||||
public readonly partial struct SerializableRelayServerNodeUpdateWrapInfo
|
||||
{
|
||||
[MemoryPackIgnore]
|
||||
public readonly RelayServerNodeUpdateWrapInfo info;
|
||||
[MemoryPackInclude]
|
||||
string SecretKey => info.SecretKey;
|
||||
[MemoryPackInclude, MemoryPackAllowSerialize]
|
||||
RelayServerNodeUpdateInfo Info => info.Info;
|
||||
|
||||
[MemoryPackConstructor]
|
||||
SerializableRelayServerNodeUpdateWrapInfo(
|
||||
string secretKey, RelayServerNodeUpdateInfo info)
|
||||
{
|
||||
this.info = new RelayServerNodeUpdateWrapInfo
|
||||
{
|
||||
SecretKey = secretKey,
|
||||
Info = info
|
||||
};
|
||||
}
|
||||
|
||||
public SerializableRelayServerNodeUpdateWrapInfo(RelayServerNodeUpdateWrapInfo info)
|
||||
{
|
||||
this.info = info;
|
||||
}
|
||||
}
|
||||
public class RelayServerNodeUpdateWrapInfoFormatter : MemoryPackFormatter<RelayServerNodeUpdateWrapInfo>
|
||||
{
|
||||
public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref RelayServerNodeUpdateWrapInfo value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNullObjectHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WritePackable(new SerializableRelayServerNodeUpdateWrapInfo(value));
|
||||
}
|
||||
|
||||
public override void Deserialize(ref MemoryPackReader reader, scoped ref RelayServerNodeUpdateWrapInfo value)
|
||||
{
|
||||
if (reader.PeekIsNull())
|
||||
{
|
||||
reader.Advance(1); // skip null block
|
||||
value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
var wrapped = reader.ReadPackable<SerializableRelayServerNodeUpdateWrapInfo>();
|
||||
value = wrapped.info;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
[MemoryPackable]
|
||||
@@ -256,6 +456,8 @@ namespace linker.messenger.serializer.memorypack
|
||||
IPEndPoint EndPoint => info.EndPoint;
|
||||
[MemoryPackInclude]
|
||||
long LastTicks => info.LastTicks;
|
||||
[MemoryPackInclude]
|
||||
string Url => info.Url;
|
||||
|
||||
|
||||
[MemoryPackConstructor]
|
||||
@@ -265,7 +467,7 @@ namespace linker.messenger.serializer.memorypack
|
||||
double maxGbTotal, long maxGbTotalLastBytes,
|
||||
double connectionRatio, double bandwidthRatio,
|
||||
bool Public, int delay,
|
||||
IPEndPoint endPoint, long lastTicks)
|
||||
IPEndPoint endPoint, long lastTicks, string url)
|
||||
{
|
||||
var info = new RelayServerNodeReportInfo
|
||||
{
|
||||
@@ -281,7 +483,8 @@ namespace linker.messenger.serializer.memorypack
|
||||
MaxGbTotal = maxGbTotal,
|
||||
MaxGbTotalLastBytes = maxGbTotalLastBytes,
|
||||
Name = name,
|
||||
Public = Public
|
||||
Public = Public,
|
||||
Url = url
|
||||
};
|
||||
this.info = info;
|
||||
}
|
||||
@@ -824,7 +1027,7 @@ namespace linker.messenger.serializer.memorypack
|
||||
RelayServerCdkeyPageRequestFlag Flag => info.Flag;
|
||||
|
||||
[MemoryPackConstructor]
|
||||
SerializableRelayServerCdkeyPageRequestInfo(int page, int size, string order, string sort, string userid, string remark, string orderid, string contact, string secretKey,RelayServerCdkeyPageRequestFlag flag)
|
||||
SerializableRelayServerCdkeyPageRequestInfo(int page, int size, string order, string sort, string userid, string remark, string orderid, string contact, string secretKey, RelayServerCdkeyPageRequestFlag flag)
|
||||
{
|
||||
var info = new RelayServerCdkeyPageRequestInfo
|
||||
{
|
||||
@@ -1141,10 +1344,12 @@ namespace linker.messenger.serializer.memorypack
|
||||
double PayPrice => info.PayPrice;
|
||||
[MemoryPackInclude]
|
||||
int Count => info.Count;
|
||||
[MemoryPackInclude]
|
||||
string Type => info.Type;
|
||||
|
||||
|
||||
[MemoryPackConstructor]
|
||||
SerializableRelayServerCdkeyOrderInfo(int gb, int speed, string time, string widgetUserId, string orderId, string contact, double costPrice, double price, double userPrice, double payPrice, int count)
|
||||
SerializableRelayServerCdkeyOrderInfo(int gb, int speed, string time, string widgetUserId, string orderId, string contact, double costPrice, double price, double userPrice, double payPrice, int count, string type)
|
||||
{
|
||||
var info = new RelayServerCdkeyOrderInfo
|
||||
{
|
||||
@@ -1158,7 +1363,8 @@ namespace linker.messenger.serializer.memorypack
|
||||
Price = price,
|
||||
UserPrice = userPrice,
|
||||
PayPrice = payPrice,
|
||||
Count = count
|
||||
Count = count,
|
||||
Type = type
|
||||
};
|
||||
this.info = info;
|
||||
}
|
||||
|
@@ -61,6 +61,11 @@ namespace linker.messenger.store.file.relay
|
||||
RelayServerCdkeyOrderInfo order = result.Cdkey.DeJson<RelayServerCdkeyOrderInfo>();
|
||||
result.Order = order;
|
||||
|
||||
if(order.Type != "Relay" || string.IsNullOrWhiteSpace(order.Type))
|
||||
{
|
||||
error.Add("Relay");
|
||||
}
|
||||
|
||||
if (order.WidgetUserId != info.UserId || string.IsNullOrWhiteSpace(order.WidgetUserId))
|
||||
{
|
||||
error.Add("UserId");
|
||||
@@ -98,13 +103,26 @@ namespace linker.messenger.store.file.relay
|
||||
|
||||
return await Task.FromResult(result);
|
||||
}
|
||||
public async Task<bool> Import(RelayServerCdkeyImportInfo info)
|
||||
public async Task<string> Import(RelayServerCdkeyImportInfo info)
|
||||
{
|
||||
RelayServerCdkeyTestResultInfo test = await Test(info);
|
||||
|
||||
if (test.Field.Count > 0)
|
||||
{
|
||||
return false;
|
||||
if (test.Field.Contains("Parse"))
|
||||
{
|
||||
return "Parse";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Field";
|
||||
}
|
||||
}
|
||||
if (liteCollection.Count(c => c.OrderId == test.Order.OrderId) > 0)
|
||||
{
|
||||
return "OrderId";
|
||||
}
|
||||
|
||||
RelayServerCdkeyOrderInfo order = test.Order;
|
||||
var time = Regex.Match(order.Time, regex).Groups;
|
||||
RelayServerCdkeyStoreInfo store = new RelayServerCdkeyStoreInfo
|
||||
@@ -120,8 +138,8 @@ namespace linker.messenger.store.file.relay
|
||||
.AddHours(int.Parse(time[4].Value))
|
||||
.AddMinutes(int.Parse(time[5].Value))
|
||||
.AddSeconds(int.Parse(time[6].Value)),
|
||||
LastBytes = order.Speed * 1024 * 1024 * 1024 * order.Count,
|
||||
MaxBytes = order.Speed * 1024 * 1024 * 1024 * order.Count,
|
||||
LastBytes = (long)order.GB * 1024 * 1024 * 1024 * order.Count,
|
||||
MaxBytes = (long)order.GB * 1024 * 1024 * 1024 * order.Count,
|
||||
Price = order.Price,
|
||||
Remark = "order",
|
||||
StartTime = DateTime.Now,
|
||||
@@ -134,7 +152,7 @@ namespace linker.messenger.store.file.relay
|
||||
Id = ObjectId.NewObjectId().ToString()
|
||||
};
|
||||
liteCollection.Insert(store);
|
||||
return await Task.FromResult(true);
|
||||
return await Task.FromResult(string.Empty);
|
||||
}
|
||||
|
||||
public async Task<bool> Traffic(Dictionary<long, long> dic)
|
||||
|
@@ -31,6 +31,7 @@ namespace linker.messenger.store.file.relay
|
||||
config.Data.Server.Relay.Distributed.Node.MaxGbTotal = update.MaxGbTotal;
|
||||
config.Data.Server.Relay.Distributed.Node.MaxGbTotalLastBytes = update.MaxGbTotalLastBytes;
|
||||
config.Data.Server.Relay.Distributed.Node.Public = update.Public;
|
||||
config.Data.Server.Relay.Distributed.Node.Url = update.Url;
|
||||
|
||||
}
|
||||
public void SetMaxGbTotalLastBytes(long value)
|
||||
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 32 KiB |
BIN
src/linker.web/public/avatar.png
Normal file
After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 40 KiB |
BIN
src/linker.web/public/logo.zip
Normal file
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 32 KiB |
@@ -26,4 +26,10 @@ export const relayCdkeyMy = (data) => {
|
||||
}
|
||||
export const relayCdkeyTest = (data) => {
|
||||
return sendWebsocketMsg('relay/TestCdkey', data);
|
||||
}
|
||||
export const relayCdkeyImport = (data) => {
|
||||
return sendWebsocketMsg('relay/ImportCdkey', data);
|
||||
}
|
||||
export const relayUpdateNode = (data) => {
|
||||
return sendWebsocketMsg('relay/UpdateNode', data);
|
||||
}
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 32 KiB |
@@ -51,6 +51,10 @@ export default {
|
||||
'status.groupDelConfirm': 'Are you sure to delete?',
|
||||
|
||||
'status.support': 'Support',
|
||||
'status.website': 'Website',
|
||||
'status.doc': 'Document',
|
||||
'status.cdkey': 'CDKEY store',
|
||||
|
||||
'status.export': 'Export',
|
||||
'status.exportText': 'Export the configuration to run elsewhere',
|
||||
'status.exportSingle': 'Single',
|
||||
@@ -126,6 +130,7 @@ export default {
|
||||
'server.relayConnection': 'Conn',
|
||||
'server.relayDelay': 'Delay',
|
||||
'server.relayPublic': 'Public',
|
||||
'server.relayUrl': 'Url',
|
||||
'server.relayOper': 'Oper',
|
||||
'server.relayUse': 'Use',
|
||||
'server.relayMyCdkey': 'My CDKEY',
|
||||
@@ -169,6 +174,35 @@ export default {
|
||||
'server.relayCdkeyFlagDeleted': 'Deleted',
|
||||
'server.relayCdkeyFlagUnDeleted': 'Not deleted',
|
||||
|
||||
'server.relayCdkeyTestTitle': 'Test CDKEY',
|
||||
'server.relayCdkeyTestKey': 'CDKEY',
|
||||
'server.relayCdkeyTestGB': 'GB',
|
||||
'server.relayCdkeyTestGBError': 'Must > 0',
|
||||
'server.relayCdkeyTestSpeed': 'Mbps',
|
||||
'server.relayCdkeyTestSpeedError': 'Must > 0',
|
||||
'server.relayCdkeyTestTime': 'Time',
|
||||
'server.relayCdkeyTestTimeError': 'Format error',
|
||||
'server.relayCdkeyTestUserId': 'UserId',
|
||||
'server.relayCdkeyTestUserIdError': 'UserId error',
|
||||
'server.relayCdkeyTestOrderId': 'OrderNo',
|
||||
'server.relayCdkeyTestOrderIdError': 'OrderNo is empty',
|
||||
'server.relayCdkeyTestContact': 'Contact',
|
||||
'server.relayCdkeyTestCostPrice': 'Cost',
|
||||
'server.relayCdkeyTestPrice': 'Price',
|
||||
'server.relayCdkeyTestUserPrice': 'User price',
|
||||
'server.relayCdkeyTestPayPrice': 'Pay',
|
||||
'server.relayCdkeyTestCount': 'Count',
|
||||
'server.relayCdkeyTestCountError': 'Must > 0',
|
||||
'server.relayCdkeyTestType': 'Type',
|
||||
'server.relayCdkeyTestTypeError': 'Must be relay',
|
||||
'server.relayCdkeyTestParseError': 'decode fail',
|
||||
|
||||
'server.relayCdkeyImport': 'Import CDKEY',
|
||||
'server.relayCdkeyImportParse': 'Decode fail',
|
||||
'server.relayCdkeyImportField': 'Field invalid',
|
||||
'server.relayCdkeyImportNetwork': 'Network error',
|
||||
'server.relayCdkeyImportOrderId': 'OrderNo has exists',
|
||||
|
||||
|
||||
'server.sforwardSecretKey': 'Server forward secretKey',
|
||||
'server.sforwardText': 'The server forward can be used when the key is correct',
|
||||
|
@@ -51,6 +51,9 @@ export default {
|
||||
'status.groupDelConfirm': '确认删除吗?',
|
||||
|
||||
'status.support': '赞助',
|
||||
'status.website': '官网',
|
||||
'status.doc': '文档',
|
||||
'status.cdkey': 'CDKEY商城',
|
||||
|
||||
'status.export': '导出配置',
|
||||
'status.exportText': '导出配置,作为子设备运行,如果使用docker,容器映射configs文件夹即可',
|
||||
@@ -123,12 +126,14 @@ export default {
|
||||
'server.relayTitle': '中继节点',
|
||||
'server.relayName': '名称',
|
||||
'server.relayFlow': '月流量',
|
||||
'server.relayFlowLast': '剩余流量',
|
||||
'server.relaySpeed': '带宽',
|
||||
'server.relaySpeed1': '总带宽',
|
||||
'server.relaySpeed2': '速率',
|
||||
'server.relayConnection': '连接数',
|
||||
'server.relayDelay': '延迟',
|
||||
'server.relayPublic': '公开',
|
||||
'server.relayUrl': 'Url',
|
||||
'server.relayOper': '操作',
|
||||
'server.relayUse': '使用',
|
||||
'server.relayMyCdkey': '我的CDKEY',
|
||||
@@ -191,8 +196,16 @@ export default {
|
||||
'server.relayCdkeyTestPayPrice': '支付',
|
||||
'server.relayCdkeyTestCount': '数量',
|
||||
'server.relayCdkeyTestCountError': '数量要大于0',
|
||||
'server.relayCdkeyTestType': '类别',
|
||||
'server.relayCdkeyTestTypeError': '类别应该是Relay',
|
||||
'server.relayCdkeyTestParseError': '解密失败',
|
||||
|
||||
'server.relayCdkeyImport': '导入CDKEY',
|
||||
'server.relayCdkeyImportParse': '解密失败',
|
||||
'server.relayCdkeyImportField': '字段有误',
|
||||
'server.relayCdkeyImportNetwork': '网络错误',
|
||||
'server.relayCdkeyImportOrderId': '订单号已存在',
|
||||
|
||||
'server.sforwardSecretKey': '服务器穿透密钥',
|
||||
'server.sforwardText': '当密钥正确是可用',
|
||||
|
||||
|
@@ -61,7 +61,11 @@
|
||||
<el-dialog v-model="state.showNodes" :title="$t('server.relayTitle')" width="760" top="2vh">
|
||||
<div>
|
||||
<el-table :data="state.nodes" size="small" border height="600">
|
||||
<el-table-column property="Name" :label="$t('server.relayName')"></el-table-column>
|
||||
<el-table-column property="Name" :label="$t('server.relayName')">
|
||||
<template #default="scope">
|
||||
<a :href="scope.row.Url" class="a-line blue" target="_blank">{{ scope.row.Name }}</a>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column property="MaxGbTotal" :label="$t('server.relayFlow')" width="160">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.MaxGbTotal == 0">--</span>
|
||||
@@ -78,7 +82,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column property="MaxBandwidthTotal" :label="$t('server.relaySpeed1')" width="80">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.MaxBandwidthTotal == 0">无限制</span>
|
||||
<span v-if="scope.row.MaxBandwidthTotal == 0">--</span>
|
||||
<span v-else>{{ scope.row.MaxBandwidthTotal }}Mbps</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -215,4 +219,7 @@ export default {
|
||||
<style lang="stylus" scoped>
|
||||
|
||||
.head{padding-bottom:1rem}
|
||||
.blue {
|
||||
color: #409EFF;
|
||||
}
|
||||
</style>
|
106
src/linker.web/src/views/full/server/EditNode.vue
Normal file
@@ -0,0 +1,106 @@
|
||||
<template>
|
||||
<el-dialog class="options-center" :title="$t('server.relayTitle')" destroy-on-close v-model="state.show" width="30rem" top="2vh">
|
||||
<div>
|
||||
<el-form ref="ruleFormRef" :model="state.ruleForm" :rules="state.rules" label-width="auto">
|
||||
<el-form-item :label="$t('server.relayName')" prop="Name">
|
||||
<el-input minlength="1" maxlength="32" show-word-limit v-model="state.ruleForm.Name" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('server.relayConnection')" prop="MaxConnection">
|
||||
<el-input-number v-model="state.ruleForm.MaxConnection" :min="0" :max="65535"/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('server.relaySpeed')" prop="MaxBandwidth">
|
||||
<el-input-number v-model="state.ruleForm.MaxBandwidth" :min="0"/>Mbps
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('server.relaySpeed1')" prop="MaxBandwidthTotal">
|
||||
<el-input-number v-model="state.ruleForm.MaxBandwidthTotal" :min="0"/>Mbps
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('server.relayFlow')" prop="MaxGbTotal">
|
||||
<el-input-number v-model="state.ruleForm.MaxGbTotal" :min="0"/>GB <el-button size="small" @click="handleRefresh"><el-icon><Refresh /></el-icon></el-button>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('server.relayFlowLast')" prop="MaxGbTotalLastBytes">
|
||||
<el-input-number v-model="state.ruleForm.MaxGbTotalLastBytes" :min="0" />byte
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('server.relayUrl')" prop="Url">
|
||||
<el-input v-model="state.ruleForm.Url" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('server.relayPublic')" prop="Public">
|
||||
<el-switch v-model="state.ruleForm.Public " size="small" />
|
||||
</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.show = false">{{$t('common.cancel')}}</el-button>
|
||||
<el-button type="primary" @click="handleSave">{{$t('common.confirm')}}</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { reactive, ref, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { relayUpdateNode } from '@/apis/relay';
|
||||
import { Refresh } from '@element-plus/icons-vue'
|
||||
export default {
|
||||
props: ['data','modelValue'],
|
||||
emits: ['update:modelValue','success'],
|
||||
components:{Refresh},
|
||||
setup(props,{emit}) {
|
||||
const {t} = useI18n();
|
||||
const state = reactive({
|
||||
show:true,
|
||||
ruleForm:{
|
||||
Id:props.data.Id,
|
||||
Name:props.data.Name,
|
||||
MaxConnection:props.data.MaxConnection,
|
||||
MaxBandwidth:props.data.MaxBandwidth,
|
||||
MaxBandwidthTotal:props.data.MaxBandwidthTotal,
|
||||
MaxGbTotal:props.data.MaxGbTotal,
|
||||
MaxGbTotalLastBytes:props.data.MaxGbTotalLastBytes,
|
||||
Public:props.data.Public,
|
||||
Url:props.data.Url,
|
||||
},
|
||||
rules:{
|
||||
}
|
||||
});
|
||||
watch(() => state.show, (val) => {
|
||||
if (!val) {
|
||||
setTimeout(() => {
|
||||
emit('update:modelValue', val);
|
||||
}, 300);
|
||||
}
|
||||
});
|
||||
const handleRefresh = ()=>{
|
||||
state.ruleForm.MaxGbTotalLastBytes = state.ruleForm.MaxGbTotal * 1024*1024*1024;
|
||||
}
|
||||
|
||||
const ruleFormRef = ref(null);
|
||||
const handleSave = ()=>{
|
||||
ruleFormRef.value.validate((valid) => {
|
||||
if (!valid) return;
|
||||
|
||||
const json = JSON.parse(JSON.stringify(state.ruleForm));
|
||||
relayUpdateNode(json).then((res)=>{
|
||||
if(res){
|
||||
ElMessage.success(t('common.oper'));
|
||||
state.show = false;
|
||||
emit('success');
|
||||
}else{
|
||||
ElMessage.error(t('common.operFail'));
|
||||
}
|
||||
}).catch(()=>{
|
||||
ElMessage.error(t('common.operFail'));
|
||||
});
|
||||
});
|
||||
}
|
||||
return {state,ruleFormRef,handleRefresh,handleSave}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="stylus" scoped>
|
||||
.el-form-item{margin-bottom:1rem}
|
||||
.el-input-number--small{width:10rem !important}
|
||||
</style>
|
@@ -1,24 +1,32 @@
|
||||
<template>
|
||||
<el-form-item :label="$t('server.relaySecretKey')">
|
||||
<div class="flex">
|
||||
<el-input class="flex-1" type="password" show-password v-model="state.list.SecretKey" maxlength="36" @change="handleSave" />
|
||||
<Sync class="mgl-1" name="RelaySecretKey"></Sync>
|
||||
<div class="mgl-1">
|
||||
<el-checkbox class="mgr-1" v-model="state.list.SSL" :label="$t('server.relaySSL')" @change="handleSave" />
|
||||
<el-checkbox v-model="state.list.Disabled" :label="$t('server.relayDisable')" @change="handleSave" />
|
||||
<div >
|
||||
<div class="flex">
|
||||
<el-input class="flex-1" type="password" show-password v-model="state.list.SecretKey" maxlength="36" @change="handleSave" />
|
||||
<Sync class="mgl-1" name="RelaySecretKey"></Sync>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div class="mgr-1">
|
||||
<el-checkbox class="mgr-1" v-model="state.list.SSL" :label="$t('server.relaySSL')" @change="handleSave" />
|
||||
<el-checkbox v-model="state.list.Disabled" :label="$t('server.relayDisable')" @change="handleSave" />
|
||||
</div>
|
||||
<a href="javascript:;" @click="state.show=true" class="mgl-1 delay a-line" :class="{red:state.nodes.length==0,green:state.nodes.length>0}">
|
||||
{{$t('server.relayNodes')}} : {{state.nodes.length}}
|
||||
</a>
|
||||
<RelayCdkey></RelayCdkey>
|
||||
</div>
|
||||
<a href="javascript:;" @click="state.show=true" class="mgl-1 delay a-line" :class="{red:state.nodes.length==0,green:state.nodes.length>0}">
|
||||
{{$t('server.relayNodes')}} : {{state.nodes.length}}
|
||||
</a>
|
||||
<RelayCdkey></RelayCdkey>
|
||||
</div>
|
||||
|
||||
</el-form-item>
|
||||
|
||||
</el-form-item>
|
||||
<el-dialog v-model="state.show" :title="$t('server.relayTitle')" width="760" top="2vh">
|
||||
<div>
|
||||
<el-table :data="state.nodes" size="small" border height="500">
|
||||
<el-table-column property="Name" :label="$t('server.relayName')"></el-table-column>
|
||||
<el-table-column property="Name" :label="$t('server.relayName')">
|
||||
<template #default="scope">
|
||||
<a :href="scope.row.Url" class="a-line blue" target="_blank">{{ scope.row.Name }}</a>
|
||||
<a v-if="state.hasRelayCdkey" href="javascript:;" class="a-line" @click="handleEdit(scope.row)"><el-icon><Edit /></el-icon></a>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column property="MaxGbTotal" :label="$t('server.relayFlow')" width="160">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.MaxGbTotal == 0">--</span>
|
||||
@@ -59,17 +67,20 @@
|
||||
</el-table>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<EditNode v-if="state.showEdit" v-model="state.showEdit" :data="state.current"></EditNode>
|
||||
</template>
|
||||
<script>
|
||||
import { setRelayServers, setRelaySubscribe } from '@/apis/relay';
|
||||
import { relayCdkeyAccess, setRelayServers, setRelaySubscribe } from '@/apis/relay';
|
||||
import { injectGlobalData } from '@/provide';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { onMounted, onUnmounted, reactive, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import Sync from '../sync/Index.vue'
|
||||
import RelayCdkey from './relayCdkey/Index.vue'
|
||||
import EditNode from './EditNode.vue';
|
||||
import { Edit } from '@element-plus/icons-vue';
|
||||
export default {
|
||||
components:{Sync,RelayCdkey},
|
||||
components:{Sync,RelayCdkey,EditNode,Edit},
|
||||
setup(props) {
|
||||
const {t} = useI18n();
|
||||
const globalData = injectGlobalData();
|
||||
@@ -77,11 +88,19 @@ export default {
|
||||
list:globalData.value.config.Client.Relay.Server,
|
||||
show:false,
|
||||
nodes:[],
|
||||
timer:0
|
||||
timer:0,
|
||||
showEdit:false,
|
||||
current:{},
|
||||
hasRelayCdkey:false
|
||||
});
|
||||
watch(()=>globalData.value.config.Client.Relay.Server,()=>{
|
||||
state.list.Delay = globalData.value.config.Client.Relay.Server.Delay;
|
||||
})
|
||||
});
|
||||
|
||||
const handleEdit = (row)=>{
|
||||
state.current = row;
|
||||
state.showEdit = true;
|
||||
}
|
||||
|
||||
const handleSave = ()=>{
|
||||
setRelayServers(state.list).then(()=>{
|
||||
@@ -91,7 +110,6 @@ export default {
|
||||
ElMessage.error(t('common.operFail'));
|
||||
});;
|
||||
}
|
||||
|
||||
const _setRelaySubscribe = ()=>{
|
||||
setRelaySubscribe().then((res)=>{
|
||||
state.nodes = res;
|
||||
@@ -102,14 +120,20 @@ export default {
|
||||
}
|
||||
onMounted(()=>{
|
||||
_setRelaySubscribe();
|
||||
relayCdkeyAccess().then(res=>{
|
||||
state.hasRelayCdkey = res;
|
||||
}).catch(()=>{})
|
||||
});
|
||||
onUnmounted(()=>{
|
||||
clearTimeout(state.timer);
|
||||
})
|
||||
|
||||
return {state,handleSave}
|
||||
return {state,handleSave,handleEdit}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="stylus" scoped>
|
||||
.blue {
|
||||
color: #409EFF;
|
||||
}
|
||||
</style>
|
@@ -20,7 +20,7 @@ export default {
|
||||
const state = reactive({
|
||||
hasRelayCdkey:false,
|
||||
showManager:false,
|
||||
showMy:true
|
||||
showMy:false
|
||||
});
|
||||
|
||||
onMounted(()=>{
|
||||
|
@@ -11,6 +11,11 @@
|
||||
<el-icon><Search /></el-icon>
|
||||
</el-button>
|
||||
</div>
|
||||
<div>
|
||||
<el-button size="small" type="success" @click="handleImport">
|
||||
<el-icon><Plus /></el-icon>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<Flags @change="handleFlagsChange"></Flags>
|
||||
</div>
|
||||
@@ -77,8 +82,9 @@ import { injectGlobalData } from '@/provide';
|
||||
import { onMounted, reactive, watch } from 'vue'
|
||||
import { Delete,Plus,Search } from '@element-plus/icons-vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import {relayCdkeyMy,relayCdkeyDel } from '@/apis/relay';
|
||||
import {relayCdkeyMy,relayCdkeyDel, relayCdkeyImport } from '@/apis/relay';
|
||||
import Flags from './Flags.vue';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
export default {
|
||||
props: ['modelValue'],
|
||||
emits: ['update:modelValue'],
|
||||
@@ -144,11 +150,34 @@ export default {
|
||||
handleSearch();
|
||||
}).catch(()=>{})
|
||||
}
|
||||
|
||||
const handleImport = ()=>{
|
||||
ElMessageBox.prompt(t('server.relayCdkeyImport'), t('common.tips'), {
|
||||
confirmButtonText: t('common.confirm'),
|
||||
cancelButtonText: t('common.cancel')
|
||||
}).then(({ value }) => {
|
||||
if(!value){
|
||||
handleImport();
|
||||
return;
|
||||
}
|
||||
|
||||
relayCdkeyImport({Base64:value}).then((res)=>{
|
||||
if(res){
|
||||
ElMessage.error(t(`server.relayCdkeyImport${res}`));
|
||||
handleImport();
|
||||
}else{
|
||||
ElMessage.success(t('common.oper'));
|
||||
handleSearch();
|
||||
}
|
||||
}).catch(()=>{})
|
||||
}).catch(() => {
|
||||
})
|
||||
}
|
||||
onMounted(()=>{
|
||||
handleSearch();
|
||||
})
|
||||
|
||||
return {state,parseSpeed,handleSort,handleFlagsChange,handleSearch,handlePageChange,handleDel}
|
||||
return {state,parseSpeed,handleSort,handleFlagsChange,handleSearch,handlePageChange,handleDel,handleImport}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@@ -11,126 +11,137 @@
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('server.relayCdkeyTestGB')" prop="GB">
|
||||
<el-row>
|
||||
<el-col :span="18">
|
||||
<el-row class="w-100">
|
||||
<el-col :span="15">
|
||||
<el-input v-model="state.ruleForm.Order.GB" />
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-col :span="9">
|
||||
<span class="red" v-if="state.ruleForm.Field.indexOf('GB')>=0">{{$t('server.relayCdkeyTestGBError')}}</span>
|
||||
<span v-else class="green">success</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('server.relayCdkeyTestSpeed')" prop="Speed">
|
||||
<el-row>
|
||||
<el-col :span="18">
|
||||
<el-row class="w-100">
|
||||
<el-col :span="15">
|
||||
<el-input v-model="state.ruleForm.Order.Speed" />
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-col :span="9">
|
||||
<span class="red" v-if="state.ruleForm.Field.indexOf('Speed')>=0">{{$t('server.relayCdkeyTestSpeedError')}}</span>
|
||||
<span v-else class="green">success</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('server.relayCdkeyTestTime')" prop="Time">
|
||||
<el-row>
|
||||
<el-col :span="18">
|
||||
<el-row class="w-100">
|
||||
<el-col :span="15">
|
||||
<el-input v-model="state.ruleForm.Order.Time" />
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-col :span="9">
|
||||
<span class="red" v-if="state.ruleForm.Field.indexOf('Time')>=0">{{$t('server.relayCdkeyTestTimeError')}}</span>
|
||||
<span v-else class="green">success</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('server.relayCdkeyTestUserId')" prop="WidgetUserId">
|
||||
<el-row>
|
||||
<el-col :span="18">
|
||||
<el-row class="w-100">
|
||||
<el-col :span="15">
|
||||
<el-input v-model="state.ruleForm.Order.WidgetUserId" />
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-col :span="9">
|
||||
<span class="red" v-if="state.ruleForm.Field.indexOf('UserId')>=0">{{$t('server.relayCdkeyTestUserIdError')}}</span>
|
||||
<span v-else class="green">success</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('server.relayCdkeyTestOrderId')" prop="OrderId">
|
||||
<el-row>
|
||||
<el-col :span="18">
|
||||
<el-row class="w-100">
|
||||
<el-col :span="15">
|
||||
<el-input v-model="state.ruleForm.Order.OrderId" />
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-col :span="9">
|
||||
<span class="red" v-if="state.ruleForm.Field.indexOf('OrderId')>=0">{{$t('server.relayCdkeyTestOrderIdError')}}</span>
|
||||
<span v-else class="green">success</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('server.relayCdkeyTestContact')" prop="Contact">
|
||||
<el-row>
|
||||
<el-col :span="18">
|
||||
<el-row class="w-100">
|
||||
<el-col :span="15">
|
||||
<el-input v-model="state.ruleForm.Order.Contact" />
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-col :span="9">
|
||||
<span class="red" v-if="state.ruleForm.Field.indexOf('Contact')>=0">{{$t('server.relayCdkeyTestContactError')}}</span>
|
||||
<span v-else class="green">success</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('server.relayCdkeyTestCostPrice')" prop="CostPrice">
|
||||
<el-row>
|
||||
<el-col :span="18">
|
||||
<el-row class="w-100">
|
||||
<el-col :span="15">
|
||||
<el-input v-model="state.ruleForm.Order.CostPrice" />
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-col :span="9">
|
||||
<span class="red" v-if="state.ruleForm.Field.indexOf('CostPrice')>=0">{{$t('server.relayCdkeyTestCostPriceError')}}</span>
|
||||
<span v-else class="green">success</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('server.relayCdkeyTestPrice')" prop="Price">
|
||||
<el-row>
|
||||
<el-col :span="18">
|
||||
<el-row class="w-100">
|
||||
<el-col :span="15">
|
||||
<el-input v-model="state.ruleForm.Order.Price" />
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-col :span="9">
|
||||
<span class="red" v-if="state.ruleForm.Field.indexOf('Price')>=0">{{$t('server.relayCdkeyTestPriceError')}}</span>
|
||||
<span v-else class="green">success</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('server.relayCdkeyTestUserPrice')" prop="UserPrice">
|
||||
<el-row>
|
||||
<el-col :span="18">
|
||||
<el-row class="w-100">
|
||||
<el-col :span="15">
|
||||
<el-input v-model="state.ruleForm.Order.UserPrice" />
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-col :span="9">
|
||||
<span class="red" v-if="state.ruleForm.Field.indexOf('UserPrice')>=0">{{$t('server.relayCdkeyTestUserPriceError')}}</span>
|
||||
<span v-else class="green">success</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('server.relayCdkeyTestPayPrice')" prop="PayPrice">
|
||||
<el-row>
|
||||
<el-col :span="18">
|
||||
<el-row class="w-100">
|
||||
<el-col :span="15">
|
||||
<el-input v-model="state.ruleForm.Order.PayPrice" />
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-col :span="9">
|
||||
<span class="red" v-if="state.ruleForm.Field.indexOf('PayPrice')>=0">{{$t('server.relayCdkeyTestPayPriceError')}}</span>
|
||||
<span v-else class="green">success</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('server.relayCdkeyTestCount')" prop="Count">
|
||||
<el-row>
|
||||
<el-col :span="18">
|
||||
<el-row class="w-100">
|
||||
<el-col :span="15">
|
||||
<el-input v-model="state.ruleForm.Order.Count" />
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-col :span="9">
|
||||
<span class="red" v-if="state.ruleForm.Field.indexOf('Count')>=0">{{$t('server.relayCdkeyTestCountError')}}</span>
|
||||
<span v-else class="green">success</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('server.relayCdkeyTestType')" prop="Type">
|
||||
<el-row class="w-100">
|
||||
<el-col :span="15">
|
||||
<el-input v-model="state.ruleForm.Order.Type" />
|
||||
</el-col>
|
||||
<el-col :span="9">
|
||||
<span class="red" v-if="state.ruleForm.Field.indexOf('Type')>=0 || state.ruleForm.Order.Type !='Relay' ">{{$t('server.relayCdkeyTestTypeError')}}</span>
|
||||
<span v-else class="green">success</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item label="" prop="Btns">
|
||||
<div class="t-c w-100">
|
||||
<el-button @click="state.show = false">{{$t('common.cancel')}}</el-button>
|
||||
@@ -155,7 +166,7 @@ export default {
|
||||
const {t} = useI18n();
|
||||
const state = reactive({
|
||||
show:true,
|
||||
Base64:'qn1vYOBtu81DkBI10nTTw7h/Vzi1Do3X1HI2+P5fflINL2wNPxrUYQPeOxUqgT+RcZSKLGF3dCMOyYBB+1VKmuI6ZaN86Whr1Xux2dY25tI5/3i/x/K1S78E6+E70ruh61phQZT3QLLVAHnIa2HpFhtPLKZaWc++ReSzixBqkW/sTT/l2iDqG2rl/zKynRM6srXWJkJr+2Msme1u5/Qu/0o6VaJ3ylv71HlB4zubNybQX5WMsOWrjN4/ruRSVF0LcayshqEfwlpeGR44nn5jMxpgQhxxpk/1flVImF00cC4=',
|
||||
Base64:'',
|
||||
ruleForm:{
|
||||
Order:{},
|
||||
Cdkey:'',
|
||||
|
@@ -4,8 +4,12 @@
|
||||
<a href="javascript:;" class="memory" :title="$t('status.support')" @click="state.showPay = true">
|
||||
<img src="@/assets/coin.svg" alt="memory" />
|
||||
<span>{{$t('status.support')}}</span>
|
||||
<span>©linker {{ self.Version }}</span>
|
||||
</a>
|
||||
<a href="https://github.com/snltty/linker" target="_blank">©linker {{ self.Version }}</a>
|
||||
<a href="https://github.com/snltty/linker" target="_blank">Github</a>
|
||||
<a href="https://linker.snltty.com" target="_blank">{{$t('status.website')}}</a>
|
||||
<a href="https://linker-doc.snltty.com" target="_blank">{{$t('status.doc')}}</a>
|
||||
<a href="https://v.netzo123.com" target="_blank">{{$t('status.cdkey')}}</a>
|
||||
</div>
|
||||
<div class="flex-1"></div>
|
||||
<div class="export"><Export :config="config"></Export></div>
|
||||
@@ -59,7 +63,7 @@ export default {
|
||||
|
||||
.copy{
|
||||
padding-left:.5rem;
|
||||
a{color:#555;}
|
||||
a{color:#555;margin-right:1rem}
|
||||
}
|
||||
|
||||
a.memory{
|
||||
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
@@ -1,5 +1,5 @@
|
||||
v1.6.9
|
||||
2025-03-08 19:25:04
|
||||
2025-03-09 18:12:09
|
||||
1. 优化linux下路由跟踪问题
|
||||
2. 优化linux下获取本机IP问题
|
||||
3. 增加ICS,让win7+、win server2008+支持NAT
|
||||
|