mirror of
https://github.com/snltty/linker.git
synced 2025-12-18 01:16:46 +08:00
重构中继
This commit is contained in:
5
CONTRIBUTING.md
Normal file
5
CONTRIBUTING.md
Normal 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)框架
|
||||
@@ -1,5 +1,5 @@
|
||||
v1.9.6
|
||||
2025-12-04 17:55:01
|
||||
2025-12-05 16:42:02
|
||||
1. 一些累计更新,一些BUG修复
|
||||
2. 优化客户端数据同步,减少服务器流量
|
||||
3. 去除cdkey,改为发电解锁中继速度
|
||||
|
||||
@@ -19,56 +19,33 @@ slug: /install/config-server
|
||||
server.json
|
||||
```
|
||||
{
|
||||
"Cdkey": {
|
||||
// Cdkey 加解密密钥
|
||||
"SecretKey": "snltty"
|
||||
},
|
||||
//中继
|
||||
"Relay": {
|
||||
//多节点
|
||||
"Distributed": {
|
||||
//作为节点时配置
|
||||
"Node": {
|
||||
//节点Id
|
||||
"Id": "279DBACF-6F0B-46D4-9BA9-902EB6824849",
|
||||
//节点名称
|
||||
"Name": "default",
|
||||
//节点地址 域名/IP:端口 或 域名/IP,当只填写域名/IP时,默认使用 ServicePort
|
||||
"Host": "0.0.0.0:1802",
|
||||
//节点最大连接数
|
||||
"MaxConnection": 0,
|
||||
//节点连接最大带宽
|
||||
"MaxBandwidth": 0,
|
||||
//节点最大总带宽
|
||||
"MaxBandwidthTotal": 0,
|
||||
//节点最大流量
|
||||
"MaxGbTotal": 0,
|
||||
//节点剩余流量
|
||||
"MaxGbTotalLastBytes": 0,
|
||||
//当前月份,月份变化时重置剩余流量
|
||||
"MaxGbTotalMonth": 0,
|
||||
//节点是否公开
|
||||
"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"
|
||||
}
|
||||
}
|
||||
//分享key,自动生成,【无需修改】
|
||||
"ShareKey": "",
|
||||
//管理密钥,自动生成,第一个导入此中继的信标服务可以修改本中继节点配置,【无需修改】
|
||||
"MasterKey": "d763f00a21cd1e0a71e7d833ed2a4e51",
|
||||
//自动生成,【无需修改】
|
||||
"DataMonth": 0,
|
||||
//域名,可以不填
|
||||
"Domain": "",
|
||||
//节点id,自动生成,,【无需修改】
|
||||
"NodeId": "111FF038-C0D6-422C-9076-B8A47A81F1C0",
|
||||
//节点名称
|
||||
"Name": "default",
|
||||
//节点协议,1为TCP,2为UDP,3为TCP+UDP
|
||||
"Protocol": 1,
|
||||
//最大连接数,0为不限制
|
||||
"Connections": 0,
|
||||
//带宽限制,0为不限制
|
||||
"Bandwidth": 0,
|
||||
//月流量,0为不限制
|
||||
"DataEachMonth": 0,
|
||||
//剩余流量,自动生成,【无需修改】
|
||||
"DataRemain": 0,
|
||||
//跳转地址,可以填写你喜欢的地址,在节点列表中点击节点名称跳转到此地址
|
||||
"Url": "https://linker.snltty.com",
|
||||
//节点图标,可以填写你喜欢的图标,在节点列表中展示
|
||||
"Logo": "https://linker.snltty.com/img/logo.png"
|
||||
},
|
||||
//服务端口
|
||||
"ServicePort": 1802,
|
||||
@@ -152,6 +129,11 @@ server.json
|
||||
"Updater": {
|
||||
//要求客户端与服务端同步版本
|
||||
"Sync2Server": false
|
||||
},
|
||||
//白名单
|
||||
"WhiteList": {
|
||||
"Type": "afdian",
|
||||
"Value": ""
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -69,12 +69,16 @@ namespace linker.libs
|
||||
}
|
||||
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";
|
||||
}
|
||||
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";
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ namespace linker.messenger.relay.server
|
||||
public string MasterKey { get; set; } = string.Empty;
|
||||
public int DataMonth { get; set; }
|
||||
public string Domain { get; set; } = string.Empty;
|
||||
|
||||
}
|
||||
|
||||
public class RelayServerNodeReportInfo : RelayServerNodeInfo
|
||||
@@ -92,6 +93,7 @@ namespace linker.messenger.relay.server
|
||||
public int Delay { 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 Host { get; set; } = string.Empty;
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string SystemId { get; set; } = string.Empty;
|
||||
|
||||
}
|
||||
|
||||
public partial class RelayServerNodeReportInfoOld
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using linker.libs.extends;
|
||||
using linker.libs.timer;
|
||||
using linker.messenger.relay.messenger;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
@@ -75,9 +74,16 @@ namespace linker.messenger.relay.server
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -85,12 +91,7 @@ namespace linker.messenger.relay.server
|
||||
connection.Id = serverId;
|
||||
relayServerConnectionTransfer.TryAdd(ConnectionSideType.Master, connection.Id, connection);
|
||||
|
||||
//未被配置,或默认配置的,设它为管理端
|
||||
if (string.IsNullOrWhiteSpace(Config.MasterKey) || md5 == Config.MasterKey)
|
||||
{
|
||||
relayServerConfigStore.SetMasterKey(serverId.Md5());
|
||||
relayServerConfigStore.Confirm();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -131,7 +132,8 @@ namespace linker.messenger.relay.server
|
||||
NodeId = info.NodeId,
|
||||
Host = info.Host,
|
||||
Name = info.Name,
|
||||
LastTicks = Environment.TickCount64
|
||||
LastTicks = Environment.TickCount64,
|
||||
ShareKey = shareKey
|
||||
}).ConfigureAwait(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 list = await relayServerNodeStore.GetAll();
|
||||
list.ForEach(c =>
|
||||
{
|
||||
c.MasterKey = string.Empty;
|
||||
});
|
||||
|
||||
var result = list
|
||||
var result = (await relayServerNodeStore.GetAll())
|
||||
.Where(c => validated || Environment.TickCount64 - c.LastTicks < 15000)
|
||||
.Where(c =>
|
||||
{
|
||||
@@ -256,7 +252,7 @@ namespace linker.messenger.relay.server
|
||||
})
|
||||
.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.BandwidthRatio)
|
||||
.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.DataRemain == 0 ? long.MaxValue : x.DataRemain)
|
||||
.ToList();
|
||||
}
|
||||
public async Task<List<RelayServerNodeStoreInfo>> GetPublicNodes()
|
||||
{
|
||||
var list = await relayServerNodeStore.GetAll();
|
||||
|
||||
list.ForEach(c =>
|
||||
{
|
||||
c.MasterKey = string.Empty;
|
||||
c.LastTicks = Environment.TickCount64 - c.LastTicks;
|
||||
});
|
||||
|
||||
var result = list
|
||||
return list;
|
||||
}
|
||||
public async Task<List<RelayServerNodeStoreInfo>> GetPublicNodes()
|
||||
{
|
||||
var result = (await relayServerNodeStore.GetAll())
|
||||
.Where(c => Environment.TickCount64 - c.LastTicks < 15000)
|
||||
.Where(c => c.Public)
|
||||
.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.BandwidthRatio)
|
||||
.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.DataRemain == 0 ? long.MaxValue : x.DataRemain)
|
||||
.ToList();
|
||||
list.ForEach(c =>
|
||||
{
|
||||
c.MasterKey = string.Empty;
|
||||
c.LastTicks = Environment.TickCount64 - c.LastTicks;
|
||||
});
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
private async Task BuildShareKey()
|
||||
{
|
||||
try
|
||||
{
|
||||
await relayServerNodeStore.Add(new RelayServerNodeStoreInfo
|
||||
{
|
||||
NodeId = relayServerConfigStore.Config.NodeId,
|
||||
Name = "default",
|
||||
Host = $"{IPAddress.Loopback}:{relayServerConfigStore.ServicePort}"
|
||||
}).ConfigureAwait(false);
|
||||
|
||||
string host = Config.Domain;
|
||||
if (string.IsNullOrWhiteSpace(host))
|
||||
{
|
||||
@@ -311,12 +306,27 @@ namespace linker.messenger.relay.server
|
||||
{
|
||||
NodeId = Config.NodeId,
|
||||
Host = $"{host}:{relayServerConfigStore.ServicePort}",
|
||||
Name = Config.Name
|
||||
Name = Config.Name,
|
||||
SystemId = SystemIdHelper.GetSystemId().Md5()
|
||||
};
|
||||
string shareKey = Convert.ToBase64String(crypto.Encode(serializer.Serialize(shareKeyInfo)));
|
||||
relayServerConfigStore.SetShareKey(shareKey);
|
||||
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}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -401,7 +411,7 @@ namespace linker.messenger.relay.server
|
||||
{
|
||||
Connection = connection,
|
||||
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
|
||||
}).ConfigureAwait(false);
|
||||
if (resp.Code == MessageResponeCodes.OK && resp.Data.Span.SequenceEqual(Helper.TrueArray))
|
||||
@@ -411,7 +421,7 @@ namespace linker.messenger.relay.server
|
||||
}
|
||||
else
|
||||
{
|
||||
socket.SafeClose();
|
||||
connection.Disponse();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@@ -478,15 +478,18 @@ namespace linker.messenger.serializer.memorypack
|
||||
string Host => info.Host;
|
||||
[MemoryPackInclude]
|
||||
string Name => info.Name;
|
||||
[MemoryPackInclude]
|
||||
string SystemId => info.SystemId;
|
||||
|
||||
[MemoryPackConstructor]
|
||||
SerializableRelayServerNodeShareInfo(string nodeId, string host, string name)
|
||||
SerializableRelayServerNodeShareInfo(string nodeId, string host, string name, string systemid)
|
||||
{
|
||||
var info = new RelayServerNodeShareInfo
|
||||
{
|
||||
NodeId = nodeId,
|
||||
Host = host,
|
||||
Name = name
|
||||
Name = name,
|
||||
SystemId = systemid
|
||||
};
|
||||
this.info = info;
|
||||
}
|
||||
@@ -523,6 +526,7 @@ namespace linker.messenger.serializer.memorypack
|
||||
value.NodeId = reader.ReadValue<string>();
|
||||
value.Host = reader.ReadValue<string>();
|
||||
value.Name = reader.ReadValue<string>();
|
||||
value.SystemId = reader.ReadValue<string>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,6 @@ namespace linker.messenger.signin
|
||||
public string Host1 { get; set; } = string.Empty;
|
||||
public string[] Hosts { get; set; } = [];
|
||||
|
||||
public string SecretKey { get; set; } = string.Empty;
|
||||
public string UserId { get; set; } = Guid.NewGuid().ToString();
|
||||
|
||||
#if DEBUG
|
||||
@@ -60,8 +59,6 @@ namespace linker.messenger.signin
|
||||
{
|
||||
public int CleanDays { get; set; } = 7;
|
||||
|
||||
public string SecretKey { get; set; } = string.Empty;
|
||||
|
||||
public bool Enabled { get; set; } = true;
|
||||
public bool Anonymous { get; set; } = true;
|
||||
|
||||
|
||||
@@ -283,9 +283,6 @@ namespace linker.messenger.store.file
|
||||
if (configExportInfo.Updater) client.Updater = new linker.messenger.updater.UpdaterConfigClientInfo { Sync2Server = client.Updater.Sync2Server };
|
||||
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>();
|
||||
common.Install = true;
|
||||
common.Modes = ["client"];
|
||||
@@ -300,7 +297,6 @@ namespace linker.messenger.store.file
|
||||
Groups = new SignInClientGroupInfo[] { client.Group },
|
||||
Servers = new SignInClientServerInfo[] { client.Server },
|
||||
client.Updater,
|
||||
client.Tunnel,
|
||||
}, common, new { Install = true, Modes = new string[] { "client" } });
|
||||
}
|
||||
|
||||
|
||||
@@ -17,13 +17,6 @@ namespace linker.messenger.store.file.signIn
|
||||
public SignInClientStore(FileConfig 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)
|
||||
|
||||
@@ -12,23 +12,13 @@ namespace linker.messenger.store.file.signIn
|
||||
|
||||
public string[] Hosts => fileConfig.Data.Server.Hosts;
|
||||
|
||||
private readonly Storefactory dBfactory;
|
||||
private readonly ILiteCollection<SignCacheInfo> liteCollection;
|
||||
private readonly FileConfig fileConfig;
|
||||
public SignInServerStore(Storefactory dBfactory, FileConfig fileConfig)
|
||||
{
|
||||
this.dBfactory = dBfactory;
|
||||
liteCollection = dBfactory.GetCollection<SignCacheInfo>("signs");
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
using linker.messenger.tunnel;
|
||||
using linker.tunnel.transport;
|
||||
using LiteDB;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Text.Json.Serialization;
|
||||
namespace linker.messenger.store.file
|
||||
{
|
||||
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 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>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,16 +21,6 @@ namespace linker.messenger.store.file.tunnel
|
||||
public TunnelClientStore(FileConfig config, 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)
|
||||
{
|
||||
|
||||
@@ -16,8 +16,10 @@ namespace linker.messenger.tuntap
|
||||
private readonly TuntapProxy tuntapProxy;
|
||||
private readonly ISignInClientStore signInClientStore;
|
||||
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.tuntapConfigTransfer = tuntapConfigTransfer;
|
||||
@@ -31,7 +33,14 @@ namespace linker.messenger.tuntap
|
||||
private readonly LastTicksManager lastTicksManager = new LastTicksManager();
|
||||
public void SubscribePing()
|
||||
{
|
||||
lastTicksManager.Update();
|
||||
if (tuntapTransfer.Status == TuntapStatus.Running && lastTicksManager.DiffGreater(3000) && operatingManager.StartOperation())
|
||||
{
|
||||
lastTicksManager.Update();
|
||||
Ping().ContinueWith((result) =>
|
||||
{
|
||||
operatingManager.StopOperation();
|
||||
}).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
private void PingTask()
|
||||
{
|
||||
@@ -41,32 +50,29 @@ namespace linker.messenger.tuntap
|
||||
{
|
||||
await Ping().ConfigureAwait(false);
|
||||
}
|
||||
}, () => tuntapTransfer.Status == TuntapStatus.Running && lastTicksManager.DiffLessEqual(5000) ? 3000 : 30000);
|
||||
},30000);
|
||||
}
|
||||
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);
|
||||
if ((tuntapConfigTransfer.Info.Switch & TuntapSwitch.AutoConnect) != TuntapSwitch.AutoConnect)
|
||||
{
|
||||
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)
|
||||
{
|
||||
var connections = tuntapProxy.Connections;
|
||||
items = items.Where(c => connections.TryGetValue(c.MachineId, out ITunnelConnection connection) && connection.Connected || c.MachineId == signInClientStore.Id);
|
||||
}
|
||||
|
||||
await Task.WhenAll(items.Select(async c =>
|
||||
{
|
||||
using Ping ping = new Ping();
|
||||
PingReply pingReply = await ping.SendPingAsync(c.IP, 500).ConfigureAwait(false);
|
||||
c.Delay = pingReply.Status == IPStatus.Success ? (int)pingReply.RoundtripTime : -1;
|
||||
tuntapDecenter.DataVersion.Increment();
|
||||
})).ConfigureAwait(false);
|
||||
var connections = tuntapProxy.Connections;
|
||||
items = items.Where(c => connections.TryGetValue(c.MachineId, out ITunnelConnection connection) && connection.Connected || c.MachineId == signInClientStore.Id);
|
||||
}
|
||||
|
||||
await Task.WhenAll(items.Select(async c =>
|
||||
{
|
||||
using Ping ping = new Ping();
|
||||
PingReply pingReply = await ping.SendPingAsync(c.IP, 500).ConfigureAwait(false);
|
||||
c.Delay = pingReply.Status == IPStatus.Success ? (int)pingReply.RoundtripTime : -1;
|
||||
tuntapDecenter.DataVersion.Increment();
|
||||
})).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<div class="flex">
|
||||
<div>
|
||||
<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>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
@@ -37,10 +37,10 @@
|
||||
<p class="flex">
|
||||
<div>
|
||||
<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 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>
|
||||
</div>
|
||||
<span class="flex-1"></span>
|
||||
@@ -100,12 +100,12 @@
|
||||
<AccessBoolean v-if="state.super" value="RemoveRelayNode,UpdateRelayNode,ShareRelayNode,RebootRelayNode">
|
||||
<template #default="{values}">
|
||||
<p>
|
||||
<el-button v-if="scope.row.Manageable && values.RebootRelayNode" type="warning" size="small" @click="handleExit(scope.row)"><el-icon><Refresh /></el-icon></el-button>
|
||||
<el-button v-if="values.UpdateRelayNode" size="small" @click="handleEdit(scope.row)"><el-icon><Edit /></el-icon></el-button>
|
||||
<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 && scope.row.LastTicks<15000" size="small" @click="handleEdit(scope.row)"><el-icon><Edit /></el-icon></el-button>
|
||||
</p>
|
||||
<p>
|
||||
<el-button v-if="values.RemoveRelayNode" type="danger" size="small" @click="handleRemove(scope.row)"><el-icon><CircleClose /></el-icon></el-button>
|
||||
<el-button v-if="scope.row.Manageable && values.ShareRelayNode" type="info" size="small" @click="handleShare(scope.row)"><el-icon><Share /></el-icon></el-button>
|
||||
<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>
|
||||
</template>
|
||||
</AccessBoolean>
|
||||
@@ -306,5 +306,10 @@ a.a-edit{
|
||||
margin-right:1rem;
|
||||
height:4rem;
|
||||
vertical-align:text-top;
|
||||
|
||||
|
||||
}
|
||||
.gray{
|
||||
filter: grayscale(100%);
|
||||
}
|
||||
</style>
|
||||
@@ -19,7 +19,7 @@ export const provideTuntap = () => {
|
||||
});
|
||||
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 = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Diagnostics;
|
||||
using linker.messenger.entry;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using linker.messenger.store.file;
|
||||
|
||||
namespace linker
|
||||
{
|
||||
@@ -63,6 +64,10 @@ namespace linker
|
||||
LinkerMessengerEntry.Build();
|
||||
|
||||
using JsonDocument json = ParseArgs(args);
|
||||
if (json == null && args.Length == 1)
|
||||
{
|
||||
ConfigureByType(args[0]);
|
||||
}
|
||||
LinkerMessengerEntry.Setup(ExcludeModule.None, json);
|
||||
|
||||
LoggerHelper.Instance.Warning($"current version : {VersionHelper.Version}");
|
||||
@@ -74,6 +79,38 @@ namespace linker
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -84,11 +121,9 @@ namespace linker
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (args.Length > 0)
|
||||
{
|
||||
if (args.Length == 1)
|
||||
LoggerHelper.Instance.Error(args[0]);
|
||||
LoggerHelper.Instance.Error($"args parse fail {ex}");
|
||||
}
|
||||
LoggerHelper.Instance.Warning($"args parse fail {ex}");
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user