This commit is contained in:
snltty
2024-07-10 19:03:21 +08:00
parent ccde030c2e
commit aa65b16892
13 changed files with 408 additions and 86 deletions

View File

@@ -118,10 +118,8 @@ namespace linker.tunnel
/// <returns></returns> /// <returns></returns>
public async Task<ITunnelConnection> ConnectAsync(string remoteMachineId, string transactionId) public async Task<ITunnelConnection> ConnectAsync(string remoteMachineId, string transactionId)
{ {
if (connectingDic.TryAdd(remoteMachineId, true) == false) if (connectingDic.TryAdd(remoteMachineId, true) == false) return null;
{ if (IsBackground(remoteMachineId, transactionId)) return null;
return null;
}
try try
{ {
@@ -221,7 +219,6 @@ namespace linker.tunnel
{ {
connectingDic.TryRemove(remoteMachineId, out _); connectingDic.TryRemove(remoteMachineId, out _);
} }
return null; return null;
} }
/// <summary> /// <summary>
@@ -393,5 +390,54 @@ namespace linker.tunnel
tunnelTransportInfo.RemoteEndPoints = eps; tunnelTransportInfo.RemoteEndPoints = eps;
} }
private ConcurrentDictionary<string, bool> backgroundDic = new ConcurrentDictionary<string, bool>();
public void StartBackground(string remoteMachineId, string transactionId)
{
if (IsBackground(remoteMachineId, transactionId)) return;
AddBackground(remoteMachineId, transactionId);
Task.Run(async () =>
{
try
{
for (int i = 0; i < 10; i++)
{
await Task.Delay(3000);
ITunnelConnection connection = await ConnectAsync(remoteMachineId, transactionId);
if (connection != null)
{
break;
}
}
}
catch (Exception)
{
}
finally
{
RemoveBackground(remoteMachineId, transactionId);
}
});
}
private void AddBackground(string remoteMachineId, string transactionId)
{
backgroundDic.TryAdd(GetBackgroundKey(remoteMachineId, transactionId), true);
}
private void RemoveBackground(string remoteMachineId, string transactionId)
{
backgroundDic.TryRemove(GetBackgroundKey(remoteMachineId, transactionId), out _);
}
private bool IsBackground(string remoteMachineId, string transactionId)
{
return backgroundDic.ContainsKey(GetBackgroundKey(remoteMachineId, transactionId));
}
private string GetBackgroundKey(string remoteMachineId, string transactionId)
{
return $"{remoteMachineId}@{transactionId}";
}
} }
} }

View File

@@ -277,6 +277,15 @@ namespace linker.tunnel.proxy
{ {
GC.Collect(); GC.Collect();
} }
public ConnectId GetTcpConnectId()
{
return new ConnectId(Proxy.ConnectId, Connection.RemoteMachineId.GetHashCode(), Connection.TransactionId.GetHashCode(), (byte)Proxy.Direction);
}
public ConnectIdUdp GetUdpConnectId()
{
return new ConnectIdUdp(Proxy.ConnectId, Proxy.SourceEP, Connection.RemoteMachineId.GetHashCode(), Connection.TransactionId.GetHashCode());
}
} }
} }

View File

@@ -5,6 +5,7 @@ using System.Buffers;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Collections.Generic;
namespace linker.tunnel.proxy namespace linker.tunnel.proxy
{ {
@@ -106,7 +107,7 @@ namespace linker.tunnel.proxy
} }
token.Proxy.Step = ProxyStep.Forward; token.Proxy.Step = ProxyStep.Forward;
//绑定 //绑定
tcpConnections.TryAdd(new ConnectId(token.Proxy.ConnectId, token.Connection.GetHashCode(), (byte)ProxyDirection.Reverse), token); tcpConnections.TryAdd(token.GetConnectId(ProxyDirection.Reverse), token);
} }
else if (closeConnect) else if (closeConnect)
{ {
@@ -258,7 +259,7 @@ namespace linker.tunnel.proxy
{ {
await token.Socket.SendAsync(state.Data.AsMemory(0, state.Length), SocketFlags.None).ConfigureAwait(false); await token.Socket.SendAsync(state.Data.AsMemory(0, state.Length), SocketFlags.None).ConfigureAwait(false);
} }
tcpConnections.TryAdd(new ConnectId(token.Proxy.ConnectId, token.Connection.GetHashCode(), (byte)ProxyDirection.Forward), token); tcpConnections.TryAdd(token.GetConnectId(ProxyDirection.Forward), token);
await SendToConnection(token).ConfigureAwait(false); await SendToConnection(token).ConfigureAwait(false);
token.Proxy.Step = ProxyStep.Forward; token.Proxy.Step = ProxyStep.Forward;
@@ -286,7 +287,7 @@ namespace linker.tunnel.proxy
{ {
if (tunnelToken.Proxy.Protocol == ProxyProtocol.Tcp) if (tunnelToken.Proxy.Protocol == ProxyProtocol.Tcp)
{ {
ConnectId connectId = new ConnectId(tunnelToken.Proxy.ConnectId, tunnelToken.Connection.GetHashCode(), (byte)tunnelToken.Proxy.Direction); ConnectId connectId = tunnelToken.GetTcpConnectId();
if (tcpConnections.TryGetValue(connectId, out AsyncUserToken token)) if (tcpConnections.TryGetValue(connectId, out AsyncUserToken token))
{ {
_ = ProcessReceive(token); _ = ProcessReceive(token);
@@ -301,7 +302,7 @@ namespace linker.tunnel.proxy
{ {
if (tunnelToken.Proxy.Protocol == ProxyProtocol.Tcp) if (tunnelToken.Proxy.Protocol == ProxyProtocol.Tcp)
{ {
ConnectId connectId = new ConnectId(tunnelToken.Proxy.ConnectId, tunnelToken.Connection.GetHashCode(), (byte)tunnelToken.Proxy.Direction); ConnectId connectId = tunnelToken.GetTcpConnectId();
if (tcpConnections.TryRemove(connectId, out AsyncUserToken token)) if (tcpConnections.TryRemove(connectId, out AsyncUserToken token))
{ {
CloseClientSocket(token); CloseClientSocket(token);
@@ -316,7 +317,7 @@ namespace linker.tunnel.proxy
/// <returns></returns> /// <returns></returns>
private async Task SendToSocketTcp(AsyncUserTunnelToken tunnelToken) private async Task SendToSocketTcp(AsyncUserTunnelToken tunnelToken)
{ {
ConnectId connectId = new ConnectId(tunnelToken.Proxy.ConnectId, tunnelToken.Connection.GetHashCode(), (byte)tunnelToken.Proxy.Direction); ConnectId connectId = tunnelToken.GetTcpConnectId();
if (tunnelToken.Proxy.Step == ProxyStep.Close || tunnelToken.Proxy.Data.Length == 0) if (tunnelToken.Proxy.Step == ProxyStep.Close || tunnelToken.Proxy.Data.Length == 0)
{ {
if (tcpConnections.TryRemove(connectId, out AsyncUserToken token)) if (tcpConnections.TryRemove(connectId, out AsyncUserToken token))
@@ -329,6 +330,7 @@ namespace linker.tunnel.proxy
{ {
try try
{ {
token1.Connection = tunnelToken.Connection;
await token1.Socket.SendAsync(tunnelToken.Proxy.Data, SocketFlags.None).AsTask().WaitAsync(TimeSpan.FromMilliseconds(5000)).ConfigureAwait(false); await token1.Socket.SendAsync(tunnelToken.Proxy.Data, SocketFlags.None).AsTask().WaitAsync(TimeSpan.FromMilliseconds(5000)).ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
@@ -348,14 +350,15 @@ namespace linker.tunnel.proxy
if (token == null) return; if (token == null) return;
if (token.Connection != null) if (token.Connection != null)
{ {
tcpConnections.TryRemove(new ConnectId(token.Proxy.ConnectId, token.Connection.GetHashCode(), (byte)token.Proxy.Direction), out _); tcpConnections.TryRemove(token.GetConnectId(), out _);
} }
token.Clear(); token.Clear();
} }
private void CloseClientSocketTcp(ITunnelConnection connection) private void CloseClientSocketTcp(ITunnelConnection connection)
{ {
int hashcode = connection.GetHashCode(); int hashcode1 = connection.RemoteMachineId.GetHashCode();
var tokens = tcpConnections.Where(c => c.Key.hashcode == hashcode).ToList(); int hashcode2 = connection.TransactionId.GetHashCode();
var tokens = tcpConnections.Where(c => c.Key.hashcode1 == hashcode1 && c.Key.hashcode2 == hashcode2).ToList();
foreach (var item in tokens) foreach (var item in tokens)
{ {
try try
@@ -407,23 +410,25 @@ namespace linker.tunnel.proxy
{ {
public bool Equals(ConnectId x, ConnectId y) public bool Equals(ConnectId x, ConnectId y)
{ {
return x.connectId == y.connectId && x.hashcode == y.hashcode && x.direction == y.direction; return x.connectId == y.connectId && x.hashcode1 == y.hashcode1 && x.hashcode2 == y.hashcode2 && x.direction == y.direction;
} }
public int GetHashCode(ConnectId obj) public int GetHashCode(ConnectId obj)
{ {
return obj.connectId.GetHashCode() ^ obj.hashcode ^ obj.direction; return obj.connectId.GetHashCode() ^ obj.hashcode1 ^ obj.hashcode2 ^ obj.direction;
} }
} }
public record struct ConnectId public record struct ConnectId
{ {
public ulong connectId; public ulong connectId;
public int hashcode; public int hashcode1;
public int hashcode2;
public byte direction; public byte direction;
public ConnectId(ulong connectId, int hashcode, byte direction) public ConnectId(ulong connectId, int hashcode1, int hashcode2, byte direction)
{ {
this.connectId = connectId; this.connectId = connectId;
this.hashcode = hashcode; this.hashcode1 = hashcode1;
this.hashcode2 = hashcode2;
this.direction = direction; this.direction = direction;
} }
} }
@@ -450,6 +455,15 @@ namespace linker.tunnel.proxy
GC.Collect(); GC.Collect();
} }
public ConnectId GetConnectId()
{
return new ConnectId(Proxy.ConnectId, Connection.RemoteMachineId.GetHashCode(), Connection.TransactionId.GetHashCode(), (byte)Proxy.Direction);
}
public ConnectId GetConnectId(ProxyDirection proxyDirection)
{
return new ConnectId(Proxy.ConnectId, Connection.RemoteMachineId.GetHashCode(), Connection.TransactionId.GetHashCode(), (byte)proxyDirection);
}
} }
public sealed class ConnectState public sealed class ConnectState
{ {

View File

@@ -153,7 +153,7 @@ namespace linker.tunnel.proxy
if (tunnelToken.Proxy.Direction == ProxyDirection.Forward) if (tunnelToken.Proxy.Direction == ProxyDirection.Forward)
{ {
ConnectIdUdp connectId = new ConnectIdUdp(tunnelToken.Proxy.ConnectId, tunnelToken.Proxy.SourceEP, tunnelToken.Connection.GetHashCode()); ConnectIdUdp connectId = tunnelToken.GetUdpConnectId();
try try
{ {
IPEndPoint target = new IPEndPoint(tunnelToken.Proxy.TargetEP.Address, tunnelToken.Proxy.TargetEP.Port); IPEndPoint target = new IPEndPoint(tunnelToken.Proxy.TargetEP.Address, tunnelToken.Proxy.TargetEP.Port);
@@ -185,6 +185,7 @@ namespace linker.tunnel.proxy
{ {
try try
{ {
asyncUserUdpToken.Connection = tunnelToken.Connection;
if (await ConnectionReceiveUdp(tunnelToken, asyncUserUdpToken).ConfigureAwait(false) == false) if (await ConnectionReceiveUdp(tunnelToken, asyncUserUdpToken).ConfigureAwait(false) == false)
{ {
await asyncUserUdpToken.SourceSocket.SendToAsync(tunnelToken.Proxy.Data, tunnelToken.Proxy.SourceEP).ConfigureAwait(false); await asyncUserUdpToken.SourceSocket.SendToAsync(tunnelToken.Proxy.Data, tunnelToken.Proxy.SourceEP).ConfigureAwait(false);
@@ -207,7 +208,7 @@ namespace linker.tunnel.proxy
await socket.SendToAsync(tunnelToken.Proxy.Data, target).ConfigureAwait(false); await socket.SendToAsync(tunnelToken.Proxy.Data, target).ConfigureAwait(false);
ConnectIdUdp connectId = new ConnectIdUdp(tunnelToken.Proxy.ConnectId, tunnelToken.Proxy.SourceEP, tunnelToken.Connection.GetHashCode()); ConnectIdUdp connectId = tunnelToken.GetUdpConnectId();
AsyncUserUdpTokenTarget udpToken = new AsyncUserUdpTokenTarget AsyncUserUdpTokenTarget udpToken = new AsyncUserUdpTokenTarget
{ {
Proxy = new ProxyInfo Proxy = new ProxyInfo
@@ -325,8 +326,9 @@ namespace linker.tunnel.proxy
private void CloseClientSocketUdp(ITunnelConnection connection) private void CloseClientSocketUdp(ITunnelConnection connection)
{ {
int hashcode = connection.GetHashCode(); int hashcode1 = connection.RemoteMachineId.GetHashCode();
var tokens = udpConnections.Where(c => c.Key.hashcode == hashcode).ToList(); int hashcode2 = connection.TransactionId.GetHashCode();
var tokens = udpConnections.Where(c => c.Key.hashcode1 == hashcode1 && c.Key.hashcode2 == hashcode2).ToList();
foreach (var item in tokens) foreach (var item in tokens)
{ {
try try
@@ -437,25 +439,27 @@ namespace linker.tunnel.proxy
{ {
public bool Equals(ConnectIdUdp x, ConnectIdUdp y) public bool Equals(ConnectIdUdp x, ConnectIdUdp y)
{ {
return x.source != null && x.source.Equals(y.source) && x.connectId == y.connectId && x.hashcode == y.hashcode; return x.source != null && x.source.Equals(y.source) && x.connectId == y.connectId && x.hashcode1 == y.hashcode1 && x.hashcode2 == y.hashcode2;
} }
public int GetHashCode(ConnectIdUdp obj) public int GetHashCode(ConnectIdUdp obj)
{ {
if (obj.source == null) return 0; if (obj.source == null) return 0;
return obj.source.GetHashCode() ^ obj.connectId.GetHashCode() ^ obj.hashcode; return obj.source.GetHashCode() ^ obj.connectId.GetHashCode() ^ obj.hashcode1 ^ obj.hashcode2;
} }
} }
public readonly struct ConnectIdUdp public readonly struct ConnectIdUdp
{ {
public readonly IPEndPoint source { get; } public readonly IPEndPoint source { get; }
public readonly ulong connectId { get; } public readonly ulong connectId { get; }
public int hashcode { get; } public int hashcode1 { get; }
public int hashcode2 { get; }
public ConnectIdUdp(ulong connectId, IPEndPoint source, int hashcode) public ConnectIdUdp(ulong connectId, IPEndPoint source, int hashcode1, int hashcode2)
{ {
this.connectId = connectId; this.connectId = connectId;
this.source = source; this.source = source;
this.hashcode = hashcode; this.hashcode1 = hashcode1;
this.hashcode2 = hashcode2;
} }
} }
} }

View File

@@ -1,7 +1,10 @@
using Fizzler.Systems.HtmlAgilityPack; using Fizzler.Systems.HtmlAgilityPack;
using HtmlAgilityPack; using HtmlAgilityPack;
using linker.libs; using linker.libs;
using System.Diagnostics;
using System.IO.Compression;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text;
namespace linker.updater namespace linker.updater
{ {
@@ -13,17 +16,36 @@ namespace linker.updater
await Helper.Await(); await Helper.Await();
} }
static string rootPath = "./updater";
static void Updater() static void Updater()
{ {
Task.Factory.StartNew(async () => Task.Factory.StartNew(async () =>
{ {
while (true) while (true)
{
try
{ {
UpdateInfo updateInfo = GetUpdateInfo(); UpdateInfo updateInfo = GetUpdateInfo();
if (updateInfo != null) if (updateInfo != null)
{ {
if (NeedDownload(updateInfo))
{
await DownloadUpdate(updateInfo);
}
}
}
catch (Exception)
{
}
try
{
if (NeedExtract())
{
ExtractUpdate();
}
}
catch (Exception)
{
} }
await Task.Delay(15000); await Task.Delay(15000);
@@ -32,7 +54,75 @@ namespace linker.updater
}, TaskCreationOptions.LongRunning); }, TaskCreationOptions.LongRunning);
} }
static bool NeedExtract()
{
try
{
return File.Exists(Path.Join(rootPath, "version.txt"))
&& File.Exists(Path.Join(rootPath,"updater.zip"))
&& File.Exists(Path.Join(rootPath, "extract.txt"))
&& File.ReadAllText(Path.Join(rootPath, "version.txt")) != $"v{FileVersionInfo.GetVersionInfo("linker.exe").FileVersion}";
}
catch (Exception)
{
}
return false;
}
static void ExtractUpdate()
{
try
{
ZipFile.ExtractToDirectory(Path.Join(rootPath, "updater.zip"), "./", Encoding.UTF8, true);
File.Delete(Path.Join(rootPath, "version.txt"));
File.Delete(Path.Join(rootPath, "msg.txt"));
File.Delete(Path.Join(rootPath, "extract.txt"));
File.Delete(Path.Join(rootPath, "updater.zip"));
}
catch (Exception)
{
}
}
static bool NeedDownload(UpdateInfo updateInfo)
{
try
{
return true;
return (File.Exists(Path.Join(rootPath, "version.txt")) == false
|| File.ReadAllText(Path.Join(rootPath, "version.txt")) != updateInfo.Tag)
&& $"v{FileVersionInfo.GetVersionInfo("linker.exe").FileVersion}" != updateInfo.Tag;
}
catch (Exception)
{
}
return false;
}
static async Task DownloadUpdate(UpdateInfo updateInfo)
{
try
{
if (Directory.Exists(rootPath) == false)
{
Directory.CreateDirectory(rootPath);
}
using FileStream fileStream = new FileStream(Path.Join(rootPath, "updater.zip"), FileMode.OpenOrCreate, FileAccess.ReadWrite);
using HttpClient httpClient = new HttpClient();
using Stream stream = await httpClient.GetStreamAsync(updateInfo.Url);
await stream.CopyToAsync(fileStream);
fileStream.Flush();
fileStream.Close();
fileStream.Dispose();
File.WriteAllText(Path.Join(rootPath, "version.txt"), updateInfo.Tag);
File.WriteAllText(Path.Join(rootPath, "msg.txt"), updateInfo.Msg);
}
catch (Exception)
{
}
}
static UpdateInfo GetUpdateInfo() static UpdateInfo GetUpdateInfo()
{ {
try try

View File

@@ -41,6 +41,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Fizzler.Systems.HtmlAgilityPack" Version="1.2.1" /> <PackageReference Include="Fizzler.Systems.HtmlAgilityPack" Version="1.2.1" />
<PackageReference Include="System.IO.Compression.ZipFile" Version="4.3.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\linker.libs\linker.libs.csproj" /> <ProjectReference Include="..\linker.libs\linker.libs.csproj" />

View File

@@ -1,13 +1,18 @@
<template> <template>
<div> <div>
<el-dialog v-model="state.show" title="初始化配置" width="500"> <el-dialog v-model="state.show" title="初始化配置" width="500" top="2vh">
<div> <div>
<div class="head t-c">
<el-checkbox v-model="state.form.client" label="客户端" />
<el-checkbox v-model="state.form.server" label="服务端" />
</div>
<div class="body"> <div class="body">
<el-card shadow="never" v-if="state.form.client">
<template #header>
<div class="card-header"><span>客户端</span></div>
</template>
<div>
<el-form ref="formDom" :model="state.form" :rules="state.rules" label-width="8rem"> <el-form ref="formDom" :model="state.form" :rules="state.rules" label-width="8rem">
<el-form-item label="模式" prop="mode">
<el-checkbox v-model="state.form.client" label="客户端" readonly disabled />
<el-checkbox v-model="state.form.server" label="服务端" readonly disabled />
</el-form-item>
<el-form-item label="" label-width="0"> <el-form-item label="" label-width="0">
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
@@ -42,14 +47,61 @@
show-word-limit /> show-word-limit />
</el-form-item> </el-form-item>
</el-form-item> </el-form-item>
<el-form-item label="重启" prop="mode"> </el-form>
<el-radio-group v-model="state.form.restart"> </div>
<el-radio :value="true">自动重启</el-radio> </el-card>
<el-radio :value="false">手动重启</el-radio> <el-card shadow="never" v-if="state.form.server">
</el-radio-group> <template #header>
<div class="card-header"><span>服务端</span></div>
</template>
<div>
<el-form ref="formDom" :model="state.form" :rules="state.rules" label-width="10rem">
<el-form-item label="" label-width="0">
<el-row>
<el-col :span="12">
<el-form-item label="服务端口" prop="servicePort">
<el-input v-model="state.form.servicePort" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="web穿透端口" prop="sforwardPort">
<el-input v-model="state.form.sforwardPort" />
</el-form-item>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="" label-width="0">
<el-row>
<el-col :span="12">
<el-form-item label="开放最小端口" prop="sforwardPort1">
<el-input v-model="state.form.sforwardPort1" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="开放最大端口" prop="sforwardPort2">
<el-input v-model="state.form.sforwardPort2" />
</el-form-item>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="" label-width="0">
<el-row>
<el-col :span="12">
<el-form-item label="穿透密钥" prop="sforwardKey">
<el-input v-model="state.form.sforwardKey" maxlength="36" show-word-limit />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="中继密钥" prop="relayKey">
<el-input v-model="state.form.relayKey" maxlength="36" show-word-limit />
</el-form-item>
</el-col>
</el-row>
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
</el-card>
</div>
</div> </div>
<template #footer> <template #footer>
<div class="dialog-footer t-c"> <div class="dialog-footer t-c">
@@ -73,13 +125,20 @@ export default {
show: false, show: false,
form: { form: {
client: true, client: true,
server: false, server: true,
restart: false, restart: false,
name: '', name: '',
groupid: '', groupid: '',
api: 0, api: 0,
web: 0, web: 0,
password: '' password: '',
relayKey:'',
sforwardKey:'',
servicePort:1802,
sforwardPort:80,
sforwardPort1:10000,
sforwardPort2:60000,
}, },
rules: { rules: {
name: [{ required: true, message: "必填", trigger: "blur" }], name: [{ required: true, message: "必填", trigger: "blur" }],
@@ -148,9 +207,10 @@ export default {
</script> </script>
<style lang="stylus" scoped> <style lang="stylus" scoped>
.body{ .body{
padding:1rem 0 2rem 0; padding:1rem 0 0 0;
} }
.footer{ .footer{
padding: 1rem 0; padding: 1rem 0;
} }
.el-card+.el-card{margin-top:1rem;}
</style> </style>

View File

@@ -67,7 +67,7 @@ namespace linker.config
} }
} }
#if DEBUG #if DEBUG
private string groupid = "snltty"; private string groupid = string.Empty;//"snltty";
#else #else
private string groupid = string.Empty; private string groupid = string.Empty;
#endif #endif

View File

@@ -113,6 +113,8 @@ namespace linker.plugins.forward.proxy
if (connection == null) if (connection == null)
{ {
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Debug($"forward relay to {machineId}"); if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Debug($"forward relay to {machineId}");
//转入后台打洞
tunnelTransfer.StartBackground(machineId, "forward");
//尝试中继 //尝试中继
connection = await relayTransfer.ConnectAsync(config.Data.Client.Id, machineId, "forward").ConfigureAwait(false); connection = await relayTransfer.ConnectAsync(config.Data.Client.Id, machineId, "forward").ConfigureAwait(false);
if (connection != null) if (connection != null)

View File

@@ -262,6 +262,7 @@ namespace linker.plugins.tuntap.proxy
{ {
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Debug($"tuntap relay to {machineId}"); if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Debug($"tuntap relay to {machineId}");
tunnelTransfer.StartBackground(machineId, "tuntap");
connection = await relayTransfer.ConnectAsync(config.Data.Client.Id, machineId, "tuntap").ConfigureAwait(false); connection = await relayTransfer.ConnectAsync(config.Data.Client.Id, machineId, "tuntap").ConfigureAwait(false);
if (connection != null) if (connection != null)
{ {

View File

@@ -0,0 +1,43 @@
using linker.config;
using linker.libs;
using linker.startup;
using Microsoft.Extensions.DependencyInjection;
using System.Diagnostics;
using System.Reflection;
namespace linker.plugins.updater
{
public sealed class UpdaterStartup : IStartup
{
public string Name => "updater";
public bool Required => false;
public StartupLevel Level => StartupLevel.Normal;
public string[] Dependent => Array.Empty<string>();
public StartupLoadType LoadType => StartupLoadType.Normal;
public void AddClient(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies)
{
}
public void AddServer(ServiceCollection serviceCollection, ConfigWrap config, Assembly[] assemblies)
{
}
public void UseClient(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies)
{
foreach (var item in Process.GetProcessesByName("linker.updater"))
{
item.Kill();
}
//CommandHelper.Execute();
}
public void UseServer(ServiceProvider serviceProvider, ConfigWrap config, Assembly[] assemblies)
{
}
}
}

View File

@@ -0,0 +1,52 @@
using linker.plugins.updater.config;
namespace linker.plugins.updater.config
{
public sealed class UpdaterConfigInfo
{
private string runWindows = "sc start linker.service";
private string stopWindows = "sc stop linker.service & taskkill /F /IM linker.exe & taskkill /F /IM linker.tray.win.exe";
private string runLinux = "systemctl start linker";
private string stopLinux = "systemctl stop linker";
private string runOsx = "launchctl start linker";
private string stopOsx = "launchctl stop linker";
private string runCommand = string.Empty;
public string RunCommand
{
get => runCommand; set
{
runCommand = value;
if (string.IsNullOrWhiteSpace(runCommand))
{
runCommand = OperatingSystem.IsWindows() ? runWindows : OperatingSystem.IsLinux() ? runLinux : runOsx;
}
}
}
private string stopCommand = string.Empty;
public string StopCommand
{
get => stopCommand; set
{
stopCommand = value;
if (string.IsNullOrWhiteSpace(stopCommand))
{
stopCommand = OperatingSystem.IsWindows() ? stopWindows : OperatingSystem.IsLinux() ? stopLinux : stopOsx;
}
}
}
}
}
namespace linker.client.config
{
public sealed partial class ConfigClientInfo
{
public UpdaterConfigInfo Updater { get; set; } = new UpdaterConfigInfo();
}
}

View File

@@ -27,7 +27,7 @@ for %%r in (win-x64,win-arm64) do (
for %%r in (win-x64,win-arm64,linux-x64,linux-arm64,osx-x64,osx-arm64) do ( for %%r in (win-x64,win-arm64,linux-x64,linux-arm64,osx-x64,osx-arm64) do (
rem dotnet publish ./linker.updater -c release -f net8.0 -o public/publish/%%r/linker-%%r/ -r %%r -p:PublishSingleFile=true -p:PublishTrimmed=true --self-contained true -p:TrimMode=full -p:TieredPGO=true -p:DebugType=none -p:DebugSymbols=false -p:EnableCompressionInSingleFile=true -p:DebuggerSupport=false -p:EnableUnsafeBinaryFormatterSerialization=false -p:EnableUnsafeUTF7Encoding=false -p:HttpActivityPropagationSupport=false -p:InvariantGlobalization=true -p:MetadataUpdaterSupport=false -p:UseSystemResourceKeys=true rem dotnet publish ./linker.updater -c release -f net8.0 -o public/publish/%%r/linker-%%r/ -r %%r -p:PublishSingleFile=true -p:PublishTrimmed=true --self-contained true -p:TrimMode=partial -p:TieredPGO=true -p:DebugType=none -p:DebugSymbols=false -p:EnableCompressionInSingleFile=true -p:DebuggerSupport=false -p:EnableUnsafeBinaryFormatterSerialization=false -p:EnableUnsafeUTF7Encoding=false -p:HttpActivityPropagationSupport=false -p:InvariantGlobalization=true -p:MetadataUpdaterSupport=false -p:UseSystemResourceKeys=true
dotnet publish ./linker -c release -f net8.0 -o ./public/publish/%%r/linker-%%r -r %%r -p:PublishSingleFile=true -p:PublishTrimmed=true --self-contained true -p:TrimMode=partial -p:TieredPGO=true -p:DebugType=none -p:DebugSymbols=false -p:EnableCompressionInSingleFile=true -p:DebuggerSupport=false -p:EnableUnsafeBinaryFormatterSerialization=false -p:EnableUnsafeUTF7Encoding=false -p:HttpActivityPropagationSupport=false -p:InvariantGlobalization=true -p:MetadataUpdaterSupport=false -p:UseSystemResourceKeys=true dotnet publish ./linker -c release -f net8.0 -o ./public/publish/%%r/linker-%%r -r %%r -p:PublishSingleFile=true -p:PublishTrimmed=true --self-contained true -p:TrimMode=partial -p:TieredPGO=true -p:DebugType=none -p:DebugSymbols=false -p:EnableCompressionInSingleFile=true -p:DebuggerSupport=false -p:EnableUnsafeBinaryFormatterSerialization=false -p:EnableUnsafeUTF7Encoding=false -p:HttpActivityPropagationSupport=false -p:InvariantGlobalization=true -p:MetadataUpdaterSupport=false -p:UseSystemResourceKeys=true
echo F|xcopy "public\\extends\\%%r\\linker-%%r\\*" "public\\publish\\%%r\\linker-%%r\\*" /s /f /h /y echo F|xcopy "public\\extends\\%%r\\linker-%%r\\*" "public\\publish\\%%r\\linker-%%r\\*" /s /f /h /y