重构中继

This commit is contained in:
snltty
2025-12-05 16:42:02 +08:00
parent 7acd88526c
commit deb46da405
17 changed files with 175 additions and 168 deletions

5
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,5 @@
## 贡献指南
1. **PR**请提交至 **dev** 分支
2. 前端管理页面在`src/linker.web`是vue3.0 + element-plus
2. 文档在`src/linker.doc.web`,使用[Docusaurus](https://github.com/facebook/docusaurus)框架

View File

@@ -1,5 +1,5 @@
v1.9.6 v1.9.6
2025-12-04 17:55:01 2025-12-05 16:42:02
1. 一些累计更新一些BUG修复 1. 一些累计更新一些BUG修复
2. 优化客户端数据同步,减少服务器流量 2. 优化客户端数据同步,减少服务器流量
3. 去除cdkey改为发电解锁中继速度 3. 去除cdkey改为发电解锁中继速度

View File

@@ -19,56 +19,33 @@ slug: /install/config-server
server.json server.json
``` ```
{ {
"Cdkey": {
// Cdkey 加解密密钥
"SecretKey": "snltty"
},
//中继
"Relay": { "Relay": {
//多节点 //分享key自动生成【无需修改】
"Distributed": { "ShareKey": "",
//作为节点配置 //管理密钥,自动生成,第一个导入此中继的信标服务可以修改本中继节点配置,【无需修改】
"Node": { "MasterKey": "d763f00a21cd1e0a71e7d833ed2a4e51",
//节点Id //自动生成,【无需修改】
"Id": "279DBACF-6F0B-46D4-9BA9-902EB6824849", "DataMonth": 0,
//域名,可以不填
"Domain": "",
//节点id自动生成【无需修改】
"NodeId": "111FF038-C0D6-422C-9076-B8A47A81F1C0",
//节点名称 //节点名称
"Name": "default", "Name": "default",
//节点地址 域名/IP:端口 或 域名/IP当只填写域名/IP时默认使用 ServicePort //节点协议1为TCP2为UDP3为TCP+UDP
"Host": "0.0.0.0:1802", "Protocol": 1,
//节点最大连接数 //最大连接数0为不限制
"MaxConnection": 0, "Connections": 0,
//节点连接最大带宽 //带宽限制0为不限制
"MaxBandwidth": 0, "Bandwidth": 0,
//节点最大总带宽 //月流量0为不限制
"MaxBandwidthTotal": 0, "DataEachMonth": 0,
//节点最大流量 //剩余流量,自动生成,【无需修改】
"MaxGbTotal": 0, "DataRemain": 0,
//节点剩余流量 //跳转地址,可以填写你喜欢的地址,在节点列表中点击节点名称跳转到此地址
"MaxGbTotalLastBytes": 0, "Url": "https://linker.snltty.com",
//当前月份,月份变化时重置剩余流量 //节点图标,可以填写你喜欢的图标,在节点列表中展示
"MaxGbTotalMonth": 0, "Logo": "https://linker.snltty.com/img/logo.png"
//节点是否公开
"Public": false,
//主机地址
"MasterHost": "127.0.0.1:1802",
//主机密钥
"MasterSecretKey": "snltty",
//随便url管理页面展示时点击跳转
"Url": "https://linker-doc.snltty.com",
//支持TCP
"AllowTcp": true,
//支持UDP
"AllowUdp": false,
//与主机同步版本
"Sync2Server": false,
//主机备用地址,默认不填即可
"MasterHosts": []
},
//作为主机时
"Master": {
"SecretKey": "snltty"
}
}
}, },
//服务端口 //服务端口
"ServicePort": 1802, "ServicePort": 1802,
@@ -152,6 +129,11 @@ server.json
"Updater": { "Updater": {
//要求客户端与服务端同步版本 //要求客户端与服务端同步版本
"Sync2Server": false "Sync2Server": false
},
//白名单
"WhiteList": {
"Type": "afdian",
"Value": ""
} }
} }
``` ```

View File

@@ -69,12 +69,16 @@ namespace linker.libs
} }
private static string SystemName() private static string SystemName()
{ {
string pattern = @"ikuai|fnos|iphone|samsung|vivo|oppo|google|huawei|xiaomi|ios|android|windows|docker|ubuntu|openwrt|armbian|archlinux|fedora|centos|rocky|alpine|debian|linux"; string pattern = @"pve|ikuai|fnos|iphone|samsung|vivo|oppo|google|huawei|xiaomi|ios|android|windows|docker|ubuntu|openwrt|armbian|archlinux|fedora|centos|rocky|alpine|debian|linux";
return Regex.Match(GetDesc(), pattern)?.Value ?? "unknow"; return Regex.Match(GetDesc(), pattern)?.Value ?? "unknow";
} }
private static string GetDesc() private static string GetDesc()
{ {
if(string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("SNLTTY_LINKER_IS_FNOS")) == false) if (string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("SNLTTY_LINKER_IS_BT")) == false)
{
return "bt";
}
if (string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("SNLTTY_LINKER_IS_FNOS")) == false)
{ {
return "fnos"; return "fnos";
} }

View File

@@ -64,6 +64,7 @@ namespace linker.messenger.relay.server
public string MasterKey { get; set; } = string.Empty; public string MasterKey { get; set; } = string.Empty;
public int DataMonth { get; set; } public int DataMonth { get; set; }
public string Domain { get; set; } = string.Empty; public string Domain { get; set; } = string.Empty;
} }
public class RelayServerNodeReportInfo : RelayServerNodeInfo public class RelayServerNodeReportInfo : RelayServerNodeInfo
@@ -92,6 +93,7 @@ namespace linker.messenger.relay.server
public int Delay { get; set; } public int Delay { get; set; }
public bool Manageable { get; set; } public bool Manageable { get; set; }
public string ShareKey { get; set; } = string.Empty;
} }
@@ -100,6 +102,8 @@ namespace linker.messenger.relay.server
public string NodeId { get; set; } = string.Empty; public string NodeId { get; set; } = string.Empty;
public string Host { get; set; } = string.Empty; public string Host { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty; public string Name { get; set; } = string.Empty;
public string SystemId { get; set; } = string.Empty;
} }
public partial class RelayServerNodeReportInfoOld public partial class RelayServerNodeReportInfoOld

View File

@@ -2,7 +2,6 @@
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;
@@ -75,9 +74,16 @@ namespace linker.messenger.relay.server
return await relayServerNodeStore.Report(info).ConfigureAwait(false); return await relayServerNodeStore.Report(info).ConfigureAwait(false);
} }
public async Task<bool> SignIn(string serverId, string nodeId, IConnection connection) public async Task<bool> SignIn(string serverId, string shareKey, IConnection connection)
{ {
if (nodeId != Config.NodeId) //未被配置,或默认配置的,设它为管理端
if (string.IsNullOrWhiteSpace(Config.MasterKey) || md5 == Config.MasterKey)
{
relayServerConfigStore.SetMasterKey(serverId.Md5());
relayServerConfigStore.Confirm();
}
if (shareKey != Config.ShareKey && serverId.Md5() != Config.MasterKey)
{ {
return false; return false;
} }
@@ -85,12 +91,7 @@ namespace linker.messenger.relay.server
connection.Id = serverId; connection.Id = serverId;
relayServerConnectionTransfer.TryAdd(ConnectionSideType.Master, connection.Id, connection); relayServerConnectionTransfer.TryAdd(ConnectionSideType.Master, connection.Id, connection);
//未被配置,或默认配置的,设它为管理端
if (string.IsNullOrWhiteSpace(Config.MasterKey) || md5 == Config.MasterKey)
{
relayServerConfigStore.SetMasterKey(serverId.Md5());
relayServerConfigStore.Confirm();
}
return true; return true;
} }
@@ -131,7 +132,8 @@ namespace linker.messenger.relay.server
NodeId = info.NodeId, NodeId = info.NodeId,
Host = info.Host, Host = info.Host,
Name = info.Name, Name = info.Name,
LastTicks = Environment.TickCount64 LastTicks = Environment.TickCount64,
ShareKey = shareKey
}).ConfigureAwait(false); }).ConfigureAwait(false);
if (result == false) if (result == false)
{ {
@@ -241,13 +243,7 @@ namespace linker.messenger.relay.server
{ {
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 list = await relayServerNodeStore.GetAll(); var result = (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 =>
{ {
@@ -256,7 +252,7 @@ namespace linker.messenger.relay.server
}) })
.OrderByDescending(c => c.LastTicks); .OrderByDescending(c => c.LastTicks);
return result.OrderByDescending(x => x.Connections == 0 ? int.MaxValue : x.Connections) var list = result.OrderByDescending(x => x.Connections == 0 ? int.MaxValue : x.Connections)
.ThenBy(x => x.ConnectionsRatio) .ThenBy(x => x.ConnectionsRatio)
.ThenBy(x => x.BandwidthRatio) .ThenBy(x => x.BandwidthRatio)
.ThenByDescending(x => x.BandwidthEach == 0 ? int.MaxValue : x.BandwidthEach) .ThenByDescending(x => x.BandwidthEach == 0 ? int.MaxValue : x.BandwidthEach)
@@ -264,21 +260,22 @@ namespace linker.messenger.relay.server
.ThenByDescending(x => x.DataEachMonth == 0 ? int.MaxValue : x.DataEachMonth) .ThenByDescending(x => x.DataEachMonth == 0 ? int.MaxValue : x.DataEachMonth)
.ThenByDescending(x => x.DataRemain == 0 ? long.MaxValue : x.DataRemain) .ThenByDescending(x => x.DataRemain == 0 ? long.MaxValue : x.DataRemain)
.ToList(); .ToList();
}
public async Task<List<RelayServerNodeStoreInfo>> GetPublicNodes()
{
var list = await relayServerNodeStore.GetAll();
list.ForEach(c => list.ForEach(c =>
{ {
c.MasterKey = string.Empty; c.MasterKey = string.Empty;
c.LastTicks = Environment.TickCount64 - c.LastTicks;
}); });
return list;
var result = list }
public async Task<List<RelayServerNodeStoreInfo>> GetPublicNodes()
{
var result = (await relayServerNodeStore.GetAll())
.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);
return result.OrderByDescending(x => x.Connections == 0 ? int.MaxValue : x.Connections) var list = result.OrderByDescending(x => x.Connections == 0 ? int.MaxValue : x.Connections)
.ThenBy(x => x.ConnectionsRatio) .ThenBy(x => x.ConnectionsRatio)
.ThenBy(x => x.BandwidthRatio) .ThenBy(x => x.BandwidthRatio)
.ThenByDescending(x => x.BandwidthEach == 0 ? int.MaxValue : x.BandwidthEach) .ThenByDescending(x => x.BandwidthEach == 0 ? int.MaxValue : x.BandwidthEach)
@@ -286,20 +283,18 @@ namespace linker.messenger.relay.server
.ThenByDescending(x => x.DataEachMonth == 0 ? int.MaxValue : x.DataEachMonth) .ThenByDescending(x => x.DataEachMonth == 0 ? int.MaxValue : x.DataEachMonth)
.ThenByDescending(x => x.DataRemain == 0 ? long.MaxValue : x.DataRemain) .ThenByDescending(x => x.DataRemain == 0 ? long.MaxValue : x.DataRemain)
.ToList(); .ToList();
list.ForEach(c =>
{
c.MasterKey = string.Empty;
c.LastTicks = Environment.TickCount64 - c.LastTicks;
});
return list;
} }
private async Task BuildShareKey() private async Task BuildShareKey()
{ {
try try
{ {
await relayServerNodeStore.Add(new RelayServerNodeStoreInfo
{
NodeId = relayServerConfigStore.Config.NodeId,
Name = "default",
Host = $"{IPAddress.Loopback}:{relayServerConfigStore.ServicePort}"
}).ConfigureAwait(false);
string host = Config.Domain; string host = Config.Domain;
if (string.IsNullOrWhiteSpace(host)) if (string.IsNullOrWhiteSpace(host))
{ {
@@ -311,12 +306,27 @@ namespace linker.messenger.relay.server
{ {
NodeId = Config.NodeId, NodeId = Config.NodeId,
Host = $"{host}:{relayServerConfigStore.ServicePort}", Host = $"{host}:{relayServerConfigStore.ServicePort}",
Name = Config.Name Name = Config.Name,
SystemId = SystemIdHelper.GetSystemId().Md5()
}; };
string shareKey = Convert.ToBase64String(crypto.Encode(serializer.Serialize(shareKeyInfo))); string shareKey = Convert.ToBase64String(crypto.Encode(serializer.Serialize(shareKeyInfo)));
relayServerConfigStore.SetShareKey(shareKey); relayServerConfigStore.SetShareKey(shareKey);
relayServerConfigStore.Confirm(); relayServerConfigStore.Confirm();
host = $"{IPAddress.Loopback}:{relayServerConfigStore.ServicePort}";
var node = await relayServerNodeStore.GetByNodeId(relayServerConfigStore.Config.NodeId);
if(node == null || node.ShareKey != shareKey || node.Name != Config.Name || node.Host != host)
{
await relayServerNodeStore.Delete(relayServerConfigStore.Config.NodeId);
await relayServerNodeStore.Add(new RelayServerNodeStoreInfo
{
NodeId = relayServerConfigStore.Config.NodeId,
Name = "default",
Host = $"{IPAddress.Loopback}:{relayServerConfigStore.ServicePort}",
ShareKey = shareKey
}).ConfigureAwait(false);
}
LoggerHelper.Instance.Warning($"build relay share key : {shareKey}"); LoggerHelper.Instance.Warning($"build relay share key : {shareKey}");
} }
catch (Exception ex) catch (Exception ex)
@@ -401,7 +411,7 @@ namespace linker.messenger.relay.server
{ {
Connection = connection, Connection = connection,
MessengerId = (ushort)RelayMessengerIds.SignIn, MessengerId = (ushort)RelayMessengerIds.SignIn,
Payload = serializer.Serialize(new KeyValuePair<string, string>(Config.NodeId, c.NodeId)), Payload = serializer.Serialize(new KeyValuePair<string, string>(Config.NodeId, c.ShareKey)),
Timeout = 5000 Timeout = 5000
}).ConfigureAwait(false); }).ConfigureAwait(false);
if (resp.Code == MessageResponeCodes.OK && resp.Data.Span.SequenceEqual(Helper.TrueArray)) if (resp.Code == MessageResponeCodes.OK && resp.Data.Span.SequenceEqual(Helper.TrueArray))
@@ -411,7 +421,7 @@ namespace linker.messenger.relay.server
} }
else else
{ {
socket.SafeClose(); connection.Disponse();
} }
}); });

View File

@@ -478,15 +478,18 @@ namespace linker.messenger.serializer.memorypack
string Host => info.Host; string Host => info.Host;
[MemoryPackInclude] [MemoryPackInclude]
string Name => info.Name; string Name => info.Name;
[MemoryPackInclude]
string SystemId => info.SystemId;
[MemoryPackConstructor] [MemoryPackConstructor]
SerializableRelayServerNodeShareInfo(string nodeId, string host, string name) SerializableRelayServerNodeShareInfo(string nodeId, string host, string name, string systemid)
{ {
var info = new RelayServerNodeShareInfo var info = new RelayServerNodeShareInfo
{ {
NodeId = nodeId, NodeId = nodeId,
Host = host, Host = host,
Name = name Name = name,
SystemId = systemid
}; };
this.info = info; this.info = info;
} }
@@ -523,6 +526,7 @@ namespace linker.messenger.serializer.memorypack
value.NodeId = reader.ReadValue<string>(); value.NodeId = reader.ReadValue<string>();
value.Host = reader.ReadValue<string>(); value.Host = reader.ReadValue<string>();
value.Name = reader.ReadValue<string>(); value.Name = reader.ReadValue<string>();
value.SystemId = reader.ReadValue<string>();
} }
} }

View File

@@ -44,7 +44,6 @@ namespace linker.messenger.signin
public string Host1 { get; set; } = string.Empty; public string Host1 { get; set; } = string.Empty;
public string[] Hosts { get; set; } = []; public string[] Hosts { get; set; } = [];
public string SecretKey { get; set; } = string.Empty;
public string UserId { get; set; } = Guid.NewGuid().ToString(); public string UserId { get; set; } = Guid.NewGuid().ToString();
#if DEBUG #if DEBUG
@@ -60,8 +59,6 @@ namespace linker.messenger.signin
{ {
public int CleanDays { get; set; } = 7; public int CleanDays { get; set; } = 7;
public string SecretKey { get; set; } = string.Empty;
public bool Enabled { get; set; } = true; public bool Enabled { get; set; } = true;
public bool Anonymous { get; set; } = true; public bool Anonymous { get; set; } = true;

View File

@@ -283,9 +283,6 @@ namespace linker.messenger.store.file
if (configExportInfo.Updater) client.Updater = new linker.messenger.updater.UpdaterConfigClientInfo { Sync2Server = client.Updater.Sync2Server }; if (configExportInfo.Updater) client.Updater = new linker.messenger.updater.UpdaterConfigClientInfo { Sync2Server = client.Updater.Sync2Server };
else client.Updater = new linker.messenger.updater.UpdaterConfigClientInfo { }; else client.Updater = new linker.messenger.updater.UpdaterConfigClientInfo { };
if (configExportInfo.Tunnel) client.Tunnel = new TunnelConfigClientInfo { Transports = client.Tunnel.Transports };
else client.Tunnel = new TunnelConfigClientInfo { Transports = new List<linker.tunnel.transport.TunnelTransportItemInfo>() };
ConfigCommonInfo common = config.Data.Common.ToJson().DeJson<ConfigCommonInfo>(); ConfigCommonInfo common = config.Data.Common.ToJson().DeJson<ConfigCommonInfo>();
common.Install = true; common.Install = true;
common.Modes = ["client"]; common.Modes = ["client"];
@@ -300,7 +297,6 @@ namespace linker.messenger.store.file
Groups = new SignInClientGroupInfo[] { client.Group }, Groups = new SignInClientGroupInfo[] { client.Group },
Servers = new SignInClientServerInfo[] { client.Server }, Servers = new SignInClientServerInfo[] { client.Server },
client.Updater, client.Updater,
client.Tunnel,
}, common, new { Install = true, Modes = new string[] { "client" } }); }, common, new { Install = true, Modes = new string[] { "client" } });
} }

View File

@@ -17,13 +17,6 @@ namespace linker.messenger.store.file.signIn
public SignInClientStore(FileConfig config) public SignInClientStore(FileConfig config)
{ {
this.config = config; this.config = config;
if (string.IsNullOrWhiteSpace(Server.SecretKey) == false)
{
Server.SuperKey = Server.SecretKey;
Server.SuperPassword = Server.SecretKey;
Server.SecretKey = string.Empty;
config.Data.Update();
}
} }
public void SetName(string newName) public void SetName(string newName)

View File

@@ -12,23 +12,13 @@ namespace linker.messenger.store.file.signIn
public string[] Hosts => fileConfig.Data.Server.Hosts; public string[] Hosts => fileConfig.Data.Server.Hosts;
private readonly Storefactory dBfactory;
private readonly ILiteCollection<SignCacheInfo> liteCollection; private readonly ILiteCollection<SignCacheInfo> liteCollection;
private readonly FileConfig fileConfig; private readonly FileConfig fileConfig;
public SignInServerStore(Storefactory dBfactory, FileConfig fileConfig) public SignInServerStore(Storefactory dBfactory, FileConfig fileConfig)
{ {
this.dBfactory = dBfactory;
liteCollection = dBfactory.GetCollection<SignCacheInfo>("signs"); liteCollection = dBfactory.GetCollection<SignCacheInfo>("signs");
this.fileConfig = fileConfig; this.fileConfig = fileConfig;
if (string.IsNullOrWhiteSpace(fileConfig.Data.Server.SignIn.SecretKey) == false)
{
fileConfig.Data.Server.SignIn.Anonymous = false;
fileConfig.Data.Server.SignIn.SuperKey = fileConfig.Data.Server.SignIn.SecretKey;
fileConfig.Data.Server.SignIn.SuperPassword = fileConfig.Data.Server.SignIn.SecretKey;
fileConfig.Data.Server.SignIn.SecretKey = string.Empty;
fileConfig.Data.Update();
}
} }

View File

@@ -1,8 +1,5 @@
using linker.messenger.tunnel; using linker.messenger.tunnel;
using linker.tunnel.transport; using linker.tunnel.transport;
using LiteDB;
using System.Collections.Concurrent;
using System.Text.Json.Serialization;
namespace linker.messenger.store.file namespace linker.messenger.store.file
{ {
public sealed partial class RunningConfigInfo public sealed partial class RunningConfigInfo
@@ -28,16 +25,5 @@ namespace linker.messenger.store.file
public Dictionary<string, List<TunnelTransportItemInfo>> Transports { get; set; } = new Dictionary<string, List<TunnelTransportItemInfo>>(); public Dictionary<string, List<TunnelTransportItemInfo>> Transports { get; set; } = new Dictionary<string, List<TunnelTransportItemInfo>>();
} }
public partial class ConfigClientInfo
{
public TunnelConfigClientInfo Tunnel { get; set; } = new TunnelConfigClientInfo();
}
public sealed class TunnelConfigClientInfo
{
/// <summary>
/// 打洞协议列表
/// </summary>
public List<TunnelTransportItemInfo> Transports { get; set; } = new List<TunnelTransportItemInfo>();
}
} }

View File

@@ -21,16 +21,6 @@ namespace linker.messenger.store.file.tunnel
public TunnelClientStore(FileConfig config, RunningConfig runningConfig) public TunnelClientStore(FileConfig config, RunningConfig runningConfig)
{ {
this.runningConfig = runningConfig; this.runningConfig = runningConfig;
if (config.Data.Client.Tunnel.Transports != null && config.Data.Client.Tunnel.Transports.Count > 0)
{
runningConfig.Data.Tunnel.Transports[Helper.GlobalString] = config.Data.Client.Tunnel.Transports;
//.AddOrUpdate(Helper.GlobalString, config.Data.Client.Tunnel.Transports, (a, b) => config.Data.Client.Tunnel.Transports);
runningConfig.Data.Update();
config.Data.Client.Tunnel.Transports = [];
config.Data.Update();
}
} }
public async Task<bool> SetTunnelTransports(string machineId, List<TunnelTransportItemInfo> list) public async Task<bool> SetTunnelTransports(string machineId, List<TunnelTransportItemInfo> list)
{ {

View File

@@ -16,8 +16,10 @@ namespace linker.messenger.tuntap
private readonly TuntapProxy tuntapProxy; private readonly TuntapProxy tuntapProxy;
private readonly ISignInClientStore signInClientStore; private readonly ISignInClientStore signInClientStore;
private readonly TuntapDecenter tuntapDecenter; private readonly TuntapDecenter tuntapDecenter;
private readonly OperatingManager operatingManager = new OperatingManager();
public TuntapPingTransfer(TuntapTransfer tuntapTransfer, TuntapConfigTransfer tuntapConfigTransfer, TuntapProxy tuntapProxy, ISignInClientStore signInClientStore, TuntapDecenter tuntapDecenter) public TuntapPingTransfer(TuntapTransfer tuntapTransfer, TuntapConfigTransfer tuntapConfigTransfer,
TuntapProxy tuntapProxy, ISignInClientStore signInClientStore, TuntapDecenter tuntapDecenter)
{ {
this.tuntapTransfer = tuntapTransfer; this.tuntapTransfer = tuntapTransfer;
this.tuntapConfigTransfer = tuntapConfigTransfer; this.tuntapConfigTransfer = tuntapConfigTransfer;
@@ -30,8 +32,15 @@ namespace linker.messenger.tuntap
private readonly LastTicksManager lastTicksManager = new LastTicksManager(); private readonly LastTicksManager lastTicksManager = new LastTicksManager();
public void SubscribePing() public void SubscribePing()
{
if (tuntapTransfer.Status == TuntapStatus.Running && lastTicksManager.DiffGreater(3000) && operatingManager.StartOperation())
{ {
lastTicksManager.Update(); lastTicksManager.Update();
Ping().ContinueWith((result) =>
{
operatingManager.StopOperation();
}).ConfigureAwait(false);
}
} }
private void PingTask() private void PingTask()
{ {
@@ -41,11 +50,9 @@ namespace linker.messenger.tuntap
{ {
await Ping().ConfigureAwait(false); await Ping().ConfigureAwait(false);
} }
}, () => tuntapTransfer.Status == TuntapStatus.Running && lastTicksManager.DiffLessEqual(5000) ? 3000 : 30000); },30000);
} }
private async Task Ping() private async Task Ping()
{
if (tuntapTransfer.Status == TuntapStatus.Running && (tuntapConfigTransfer.Info.Switch & TuntapSwitch.ShowDelay) == TuntapSwitch.ShowDelay)
{ {
var items = tuntapDecenter.Infos.Values.Where(c => c.IP != null && c.IP.Equals(IPAddress.Any) == false && (c.Status & TuntapStatus.Running) == TuntapStatus.Running); var items = tuntapDecenter.Infos.Values.Where(c => c.IP != null && c.IP.Equals(IPAddress.Any) == false && (c.Status & TuntapStatus.Running) == TuntapStatus.Running);
if ((tuntapConfigTransfer.Info.Switch & TuntapSwitch.AutoConnect) != TuntapSwitch.AutoConnect) if ((tuntapConfigTransfer.Info.Switch & TuntapSwitch.AutoConnect) != TuntapSwitch.AutoConnect)
@@ -62,11 +69,10 @@ namespace linker.messenger.tuntap
tuntapDecenter.DataVersion.Increment(); tuntapDecenter.DataVersion.Increment();
})).ConfigureAwait(false); })).ConfigureAwait(false);
} }
}
public async Task SubscribeForwardTest(List<TuntapForwardTestInfo> list) public async Task SubscribeForwardTest(List<TuntapForwardTestInfo> list)
{ {
await Task.WhenAll(list.Where(c=>c.ConnectAddr.Equals(IPAddress.Any)==false && c.ConnectPort > 0 && c.ListenPort > 0).Select(async c => await Task.WhenAll(list.Where(c => c.ConnectAddr.Equals(IPAddress.Any) == false && c.ConnectPort > 0 && c.ListenPort > 0).Select(async c =>
{ {
try try
{ {

View File

@@ -19,7 +19,7 @@
<div class="flex"> <div class="flex">
<div> <div>
<a :href="scope.row.Url" target="_blank" > <a :href="scope.row.Url" target="_blank" >
<img class="logo" :src="scope.row.Logo || 'https://linker.snltty.com/img/logo.png'" alt=""/> <img class="logo" :class="{'gray': scope.row.LastTicks>15000}" :src="scope.row.Logo || 'https://linker.snltty.com/img/logo.png'" alt=""/>
</a> </a>
</div> </div>
<div class="flex-1"> <div class="flex-1">
@@ -37,10 +37,10 @@
<p class="flex"> <p class="flex">
<div> <div>
<template v-if="state.syncData.Key == scope.row.NodeId"> <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>{{ scope.row.Host }}</el-checkbox>
</template> </template>
<template v-else> <template v-else>
<el-checkbox size="small" disabled @click.stop="handleShowSync(scope.row, 1)">{{ $t('server.relayDefault') }}</el-checkbox> <el-checkbox size="small" disabled @click.stop="handleShowSync(scope.row, 1)">{{ scope.row.Host }}</el-checkbox>
</template> </template>
</div> </div>
<span class="flex-1"></span> <span class="flex-1"></span>
@@ -100,12 +100,12 @@
<AccessBoolean v-if="state.super" value="RemoveRelayNode,UpdateRelayNode,ShareRelayNode,RebootRelayNode"> <AccessBoolean v-if="state.super" value="RemoveRelayNode,UpdateRelayNode,ShareRelayNode,RebootRelayNode">
<template #default="{values}"> <template #default="{values}">
<p> <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="scope.row.Manageable && values.RebootRelayNode && scope.row.LastTicks<15000" 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> <el-button v-if="values.UpdateRelayNode && scope.row.LastTicks<15000" size="small" @click="handleEdit(scope.row)"><el-icon><Edit /></el-icon></el-button>
</p> </p>
<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="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> <el-button v-if="scope.row.Manageable && values.ShareRelayNode && scope.row.LastTicks<15000" type="info" size="small" @click="handleShare(scope.row)"><el-icon><Share /></el-icon></el-button>
</p> </p>
</template> </template>
</AccessBoolean> </AccessBoolean>
@@ -306,5 +306,10 @@ a.a-edit{
margin-right:1rem; margin-right:1rem;
height:4rem; height:4rem;
vertical-align:text-top; vertical-align:text-top;
} }
.gray{
filter: grayscale(100%);
}
</style> </style>

View File

@@ -19,7 +19,7 @@ export const provideTuntap = () => {
}); });
provide(tuntapSymbol, tuntap); provide(tuntapSymbol, tuntap);
const reg = /ikuai|fnos|iphone|samsung|vivo|oppo|google|huawei|xiaomi|ios|android|windows|ubuntu|openwrt|armbian|archlinux|fedora|centos|rocky|alpine|debian|linux|docker/g; const reg = /pve|ikuai|fnos|iphone|samsung|vivo|oppo|google|huawei|xiaomi|ios|android|windows|ubuntu|openwrt|armbian|archlinux|fedora|centos|rocky|alpine|debian|linux|docker/g;
const tuntapDataFn = () => { const tuntapDataFn = () => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {

View File

@@ -4,6 +4,7 @@ using System.Diagnostics;
using linker.messenger.entry; using linker.messenger.entry;
using System.Text; using System.Text;
using System.Text.Json; using System.Text.Json;
using linker.messenger.store.file;
namespace linker namespace linker
{ {
@@ -63,6 +64,10 @@ namespace linker
LinkerMessengerEntry.Build(); LinkerMessengerEntry.Build();
using JsonDocument json = ParseArgs(args); using JsonDocument json = ParseArgs(args);
if (json == null && args.Length == 1)
{
ConfigureByType(args[0]);
}
LinkerMessengerEntry.Setup(ExcludeModule.None, json); LinkerMessengerEntry.Setup(ExcludeModule.None, json);
LoggerHelper.Instance.Warning($"current version : {VersionHelper.Version}"); LoggerHelper.Instance.Warning($"current version : {VersionHelper.Version}");
@@ -74,6 +79,38 @@ namespace linker
GCHelper.EmptyWorkingSet(); GCHelper.EmptyWorkingSet();
} }
private static void ConfigureByType(string type)
{
FileConfig config = LinkerMessengerEntry.GetService<FileConfig>();
switch (type)
{
case "client":
{
config.Data.Common.Modes = ["client"];
}
break;
case "server":
{
ConfigServerInfo temp = new ConfigServerInfo();
config.Data.Common.Modes = ["server"];
config.Data.Server.ApiPort = temp.ApiPort;
config.Data.Server.SignIn.Anonymous = temp.SignIn.Anonymous;
config.Data.Server.SignIn.Enabled = temp.SignIn.Enabled;
}
break;
case "node":
{
config.Data.Common.Modes = ["server"];
config.Data.Server.ApiPort = 0;
config.Data.Server.SignIn.Anonymous = false;
config.Data.Server.SignIn.Enabled = false;
}
break;
default:
break;
}
}
private static JsonDocument ParseArgs(string[] args) private static JsonDocument ParseArgs(string[] args)
{ {
@@ -84,11 +121,9 @@ namespace linker
} }
catch (Exception ex) catch (Exception ex)
{ {
if (args.Length > 0) if (args.Length == 1)
{
LoggerHelper.Instance.Error(args[0]); LoggerHelper.Instance.Error(args[0]);
LoggerHelper.Instance.Error($"args parse fail {ex}"); LoggerHelper.Instance.Warning($"args parse fail {ex}");
}
} }
return json; return json;
} }