一些常规优化

This commit is contained in:
snltty
2024-11-29 00:49:22 +08:00
parent 75e66acebb
commit fb7e2d4f4e
34 changed files with 322 additions and 235 deletions

View File

@@ -57,9 +57,9 @@ jobs:
docker tag snltty/linker-musl-x64:latest snltty/linker-musl:amd64 && \ docker tag snltty/linker-musl-x64:latest snltty/linker-musl:amd64 && \
docker push snltty/linker-musl:amd64 && \ docker push snltty/linker-musl:amd64 && \
docker manifest create snltty/linker-musl:latest snltty/linker-musl:amd64 snltty/linker-musl:arm64 snltty/linker-musl:arm && \ docker manifest create snltty/linker-musl:latest snltty/linker-musl:amd64 snltty/linker-musl:arm64 snltty/linker-musl:arm && \
docker manifest create snltty/linker-musl:v1.5.9 snltty/linker-musl:amd64 snltty/linker-musl:arm64 snltty/linker-musl:arm && \ docker manifest create snltty/linker-musl:v1.6.0 snltty/linker-musl:amd64 snltty/linker-musl:arm64 snltty/linker-musl:arm && \
docker manifest push snltty/linker-musl:latest && \ docker manifest push snltty/linker-musl:latest && \
docker manifest push snltty/linker-musl:v1.5.9 && \ docker manifest push snltty/linker-musl:v1.6.0 && \
docker pull --platform linux/arm/v7 snltty/linker-debian-arm:latest && \ docker pull --platform linux/arm/v7 snltty/linker-debian-arm:latest && \
docker tag snltty/linker-debian-arm:latest snltty/linker-debian:arm && \ docker tag snltty/linker-debian-arm:latest snltty/linker-debian:arm && \
docker push snltty/linker-debian:arm && \ docker push snltty/linker-debian:arm && \
@@ -70,6 +70,6 @@ jobs:
docker tag snltty/linker-debian-x64:latest snltty/linker-debian:amd64 && \ docker tag snltty/linker-debian-x64:latest snltty/linker-debian:amd64 && \
docker push snltty/linker-debian:amd64 && \ docker push snltty/linker-debian:amd64 && \
docker manifest create snltty/linker-debian:latest snltty/linker-debian:amd64 snltty/linker-debian:arm64 snltty/linker-debian:arm && \ docker manifest create snltty/linker-debian:latest snltty/linker-debian:amd64 snltty/linker-debian:arm64 snltty/linker-debian:arm && \
docker manifest create snltty/linker-debian:v1.5.9 snltty/linker-debian:amd64 snltty/linker-debian:arm64 snltty/linker-debian:arm && \ docker manifest create snltty/linker-debian:v1.6.0 snltty/linker-debian:amd64 snltty/linker-debian:arm64 snltty/linker-debian:arm && \
docker manifest push snltty/linker-debian:latest && \ docker manifest push snltty/linker-debian:latest && \
docker manifest push snltty/linker-debian:v1.5.9 docker manifest push snltty/linker-debian:v1.6.0

View File

@@ -33,11 +33,11 @@ jobs:
env: env:
GITHUB_TOKEN: ${{ secrets.ACTIONS_TOKEN }} GITHUB_TOKEN: ${{ secrets.ACTIONS_TOKEN }}
with: with:
tag_name: v1.5.9 tag_name: v1.6.0
release_name: v1.5.9.${{ steps.date.outputs.today }} release_name: v1.6.0.${{ steps.date.outputs.today }}
draft: false draft: false
prerelease: false prerelease: false
body: "1. 优化UI\r\n2. 优化网卡\r\n3. 修复网卡禁用自动重启\r\n4. 增加一键安装脚本" body: "1. 优化websocket(某些代理环境下可能请求头key名称不规范)\r\n2. 尝试解决UDP获取外网IP端口失败的问题\r\n3. 测试中"
- name: upload-win-x86-oss - name: upload-win-x86-oss
id: upload-win-x86-oss id: upload-win-x86-oss
uses: tvrcgo/oss-action@v0.1.1 uses: tvrcgo/oss-action@v0.1.1
@@ -47,7 +47,7 @@ jobs:
key-secret: ${{ secrets.ALIYUN_OSS_SECRET }} key-secret: ${{ secrets.ALIYUN_OSS_SECRET }}
bucket: ide-qbcode bucket: ide-qbcode
asset-path: ./public/publish-zip/linker-win-x86.zip asset-path: ./public/publish-zip/linker-win-x86.zip
target-path: /downloads/linker/v1.5.9/linker-win-x86.zip target-path: /downloads/linker/v1.6.0/linker-win-x86.zip
- name: upload-win-x86 - name: upload-win-x86
id: upload-win-x86 id: upload-win-x86
uses: actions/upload-release-asset@master uses: actions/upload-release-asset@master
@@ -67,7 +67,7 @@ jobs:
key-secret: ${{ secrets.ALIYUN_OSS_SECRET }} key-secret: ${{ secrets.ALIYUN_OSS_SECRET }}
bucket: ide-qbcode bucket: ide-qbcode
asset-path: ./public/publish-zip/linker-win-x64.zip asset-path: ./public/publish-zip/linker-win-x64.zip
target-path: /downloads/linker/v1.5.9/linker-win-x64.zip target-path: /downloads/linker/v1.6.0/linker-win-x64.zip
- name: upload-win-x64 - name: upload-win-x64
id: upload-win-x64 id: upload-win-x64
uses: actions/upload-release-asset@master uses: actions/upload-release-asset@master
@@ -87,7 +87,7 @@ jobs:
key-secret: ${{ secrets.ALIYUN_OSS_SECRET }} key-secret: ${{ secrets.ALIYUN_OSS_SECRET }}
bucket: ide-qbcode bucket: ide-qbcode
asset-path: ./public/publish-zip/linker-win-arm64.zip asset-path: ./public/publish-zip/linker-win-arm64.zip
target-path: /downloads/linker/v1.5.9/linker-win-arm64.zip target-path: /downloads/linker/v1.6.0/linker-win-arm64.zip
- name: upload-win-arm64 - name: upload-win-arm64
id: upload-win-arm64 id: upload-win-arm64
uses: actions/upload-release-asset@master uses: actions/upload-release-asset@master
@@ -107,7 +107,7 @@ jobs:
key-secret: ${{ secrets.ALIYUN_OSS_SECRET }} key-secret: ${{ secrets.ALIYUN_OSS_SECRET }}
bucket: ide-qbcode bucket: ide-qbcode
asset-path: ./public/publish-zip/linker-linux-x64.zip asset-path: ./public/publish-zip/linker-linux-x64.zip
target-path: /downloads/linker/v1.5.9/linker-linux-x64.zip target-path: /downloads/linker/v1.6.0/linker-linux-x64.zip
- name: upload-linux-x64 - name: upload-linux-x64
id: upload-linux-x64 id: upload-linux-x64
uses: actions/upload-release-asset@master uses: actions/upload-release-asset@master
@@ -127,7 +127,7 @@ jobs:
key-secret: ${{ secrets.ALIYUN_OSS_SECRET }} key-secret: ${{ secrets.ALIYUN_OSS_SECRET }}
bucket: ide-qbcode bucket: ide-qbcode
asset-path: ./public/publish-zip/linker-linux-arm.zip asset-path: ./public/publish-zip/linker-linux-arm.zip
target-path: /downloads/linker/v1.5.9/linker-linux-arm.zip target-path: /downloads/linker/v1.6.0/linker-linux-arm.zip
- name: upload-linux-arm - name: upload-linux-arm
id: upload-linux-arm id: upload-linux-arm
uses: actions/upload-release-asset@master uses: actions/upload-release-asset@master
@@ -147,7 +147,7 @@ jobs:
key-secret: ${{ secrets.ALIYUN_OSS_SECRET }} key-secret: ${{ secrets.ALIYUN_OSS_SECRET }}
bucket: ide-qbcode bucket: ide-qbcode
asset-path: ./public/publish-zip/linker-linux-arm64.zip asset-path: ./public/publish-zip/linker-linux-arm64.zip
target-path: /downloads/linker/v1.5.9/linker-linux-arm64.zip target-path: /downloads/linker/v1.6.0/linker-linux-arm64.zip
- name: upload-linux-arm64 - name: upload-linux-arm64
id: upload-linux-arm64 id: upload-linux-arm64
uses: actions/upload-release-asset@master uses: actions/upload-release-asset@master
@@ -167,7 +167,7 @@ jobs:
key-secret: ${{ secrets.ALIYUN_OSS_SECRET }} key-secret: ${{ secrets.ALIYUN_OSS_SECRET }}
bucket: ide-qbcode bucket: ide-qbcode
asset-path: ./public/publish-zip/linker-linux-musl-x64.zip asset-path: ./public/publish-zip/linker-linux-musl-x64.zip
target-path: /downloads/linker/v1.5.9/linker-linux-musl-x64.zip target-path: /downloads/linker/v1.6.0/linker-linux-musl-x64.zip
- name: upload-linux-musl-x64 - name: upload-linux-musl-x64
id: upload-linux-musl-x64 id: upload-linux-musl-x64
uses: actions/upload-release-asset@master uses: actions/upload-release-asset@master
@@ -187,7 +187,7 @@ jobs:
key-secret: ${{ secrets.ALIYUN_OSS_SECRET }} key-secret: ${{ secrets.ALIYUN_OSS_SECRET }}
bucket: ide-qbcode bucket: ide-qbcode
asset-path: ./public/publish-zip/linker-linux-musl-arm.zip asset-path: ./public/publish-zip/linker-linux-musl-arm.zip
target-path: /downloads/linker/v1.5.9/linker-linux-musl-arm.zip target-path: /downloads/linker/v1.6.0/linker-linux-musl-arm.zip
- name: upload-linux-musl-arm - name: upload-linux-musl-arm
id: upload-linux-musl-arm id: upload-linux-musl-arm
uses: actions/upload-release-asset@master uses: actions/upload-release-asset@master
@@ -207,7 +207,7 @@ jobs:
key-secret: ${{ secrets.ALIYUN_OSS_SECRET }} key-secret: ${{ secrets.ALIYUN_OSS_SECRET }}
bucket: ide-qbcode bucket: ide-qbcode
asset-path: ./public/publish-zip/linker-linux-musl-arm64.zip asset-path: ./public/publish-zip/linker-linux-musl-arm64.zip
target-path: /downloads/linker/v1.5.9/linker-linux-musl-arm64.zip target-path: /downloads/linker/v1.6.0/linker-linux-musl-arm64.zip
- name: upload-linux-musl-arm64 - name: upload-linux-musl-arm64
id: upload-linux-musl-arm64 id: upload-linux-musl-arm64
uses: actions/upload-release-asset@master uses: actions/upload-release-asset@master
@@ -227,7 +227,7 @@ jobs:
key-secret: ${{ secrets.ALIYUN_OSS_SECRET }} key-secret: ${{ secrets.ALIYUN_OSS_SECRET }}
bucket: ide-qbcode bucket: ide-qbcode
asset-path: ./public/publish-zip/linker-osx-x64.zip asset-path: ./public/publish-zip/linker-osx-x64.zip
target-path: /downloads/linker/v1.5.9/linker-osx-x64.zip target-path: /downloads/linker/v1.6.0/linker-osx-x64.zip
- name: upload-osx-x64 - name: upload-osx-x64
id: upload-osx-x64 id: upload-osx-x64
uses: actions/upload-release-asset@master uses: actions/upload-release-asset@master
@@ -247,7 +247,7 @@ jobs:
key-secret: ${{ secrets.ALIYUN_OSS_SECRET }} key-secret: ${{ secrets.ALIYUN_OSS_SECRET }}
bucket: ide-qbcode bucket: ide-qbcode
asset-path: ./public/publish-zip/linker-osx-arm64.zip asset-path: ./public/publish-zip/linker-osx-arm64.zip
target-path: /downloads/linker/v1.5.9/linker-osx-arm64.zip target-path: /downloads/linker/v1.6.0/linker-osx-arm64.zip
- name: upload-osx-arm64 - name: upload-osx-arm64
id: upload-osx-arm64 id: upload-osx-arm64
uses: actions/upload-release-asset@master uses: actions/upload-release-asset@master
@@ -277,7 +277,7 @@ jobs:
key-secret: ${{ secrets.ALIYUN_OSS_SECRET }} key-secret: ${{ secrets.ALIYUN_OSS_SECRET }}
bucket: ide-qbcode bucket: ide-qbcode
asset-path: ./public/publish-zip/linker-windows-route.zip asset-path: ./public/publish-zip/linker-windows-route.zip
target-path: /downloads/linker/v1.5.9/linker-windows-route.zip target-path: /downloads/linker/v1.6.0/linker-windows-route.zip
- name: upload-version-oss - name: upload-version-oss
id: upload-version-oss id: upload-version-oss
uses: tvrcgo/oss-action@v0.1.1 uses: tvrcgo/oss-action@v0.1.1

View File

@@ -38,6 +38,6 @@ jobs:
- name: Push - name: Push
run: | run: |
nuget push ./linker.tunnel/bin/release/linker.tunnel.1.5.9.nupkg -Source https://api.nuget.org/v3/index.json -SkipDuplicate -ApiKey ${{ secrets.NUGET_KEY }} -NoSymbol nuget push ./linker.tunnel/bin/release/linker.tunnel.1.6.0.nupkg -Source https://api.nuget.org/v3/index.json -SkipDuplicate -ApiKey ${{ secrets.NUGET_KEY }} -NoSymbol
nuget push ./linker.libs/bin/release/linker.libs.1.5.9.nupkg -Source https://api.nuget.org/v3/index.json -SkipDuplicate -ApiKey ${{ secrets.NUGET_KEY }} -NoSymbol nuget push ./linker.libs/bin/release/linker.libs.1.6.0.nupkg -Source https://api.nuget.org/v3/index.json -SkipDuplicate -ApiKey ${{ secrets.NUGET_KEY }} -NoSymbol
nuget push ./linker.tun/bin/release/linker.tun.1.5.9.nupkg -Source https://api.nuget.org/v3/index.json -SkipDuplicate -ApiKey ${{ secrets.NUGET_KEY }} -NoSymbol nuget push ./linker.tun/bin/release/linker.tun.1.6.0.nupkg -Source https://api.nuget.org/v3/index.json -SkipDuplicate -ApiKey ${{ secrets.NUGET_KEY }} -NoSymbol

View File

@@ -3,6 +3,10 @@ sidebar_position: 1
--- ---
# 1、首页 # 1、首页
:::danger[特别声明]
1. 因为没有签名,又需要较高的权限,所以可能存在报毒的情况,请手动在安全软件中添加白名单
2. 如有疑问,可右上角移步软件源码,公开透明
:::
:::tip[说明] :::tip[说明]

View File

@@ -15,14 +15,15 @@ sidebar_position: 1
下载安装脚本 下载安装脚本
``` ```
curl -fsSL https://linker-doc.snltty.com/linker-install.sh -o linker-install.sh curl -fsSL https://linker-doc.snltty.com/linker-install.sh -o linker-install.sh
chmod +x linker-install.sh
``` ```
默认安装位置 默认安装位置
``` ```
sudo sh linker-install.sh ./linker-install.sh
``` ```
指定安装位置 指定安装位置
``` ```
sudo sh linker-install.sh /usr/local/bin ./linker-install.sh /usr/local/bin
``` ```
::: :::

View File

@@ -17,15 +17,11 @@ plain='\033[0m'
export PATH=$PATH:/usr/local/bin export PATH=$PATH:/usr/local/bin
install_base() {
(command -v git >/dev/null 2>&1 && command -v curl >/dev/null 2>&1 && command -v wget >/dev/null 2>&1 && command -v unzip >/dev/null 2>&1 && command -v getenforce >/dev/null 2>&1) ||
(install_soft curl wget git unzip)
}
install_soft() { install_soft() {
(command -v yum >/dev/null 2>&1 && yum makecache >/dev/null 2>&1 && yum install $* iproute2 dmidecode net-tools curl traceroute iptables ca-certificates -y >/dev/null 2>&1) || (command -v yum >/dev/null 2>&1 && yum makecache >/dev/null 2>&1 && yum install curl wget git unzip iproute dmidecode net-tools curl traceroute iptables ca-certificates -y >/dev/null 2>&1) ||
(command -v apt >/dev/null 2>&1 && apt update >/dev/null 2>&1 && apt install $* iproute2 dmidecode net-tools curl traceroute iptables ca-certificates -y >/dev/null 2>&1) || (command -v apt >/dev/null 2>&1 && apt update >/dev/null 2>&1 && apt install curl wget git unzip iproute2 dmidecode net-tools curl traceroute iptables ca-certificates -y >/dev/null 2>&1) ||
(command -v pacman >/dev/null 2>&1 && pacman -Syu $* base-devel --noconfirm && install_arch) || (command -v pacman >/dev/null 2>&1 && pacman -Syu curl wget git unzip base-devel --noconfirm && install_arch) ||
(command -v apt-get >/dev/null 2>&1 && apt-get update >/dev/null 2>&1 && apt-get install $* iproute2 dmidecode net-tools curl traceroute iptables ca-certificates -y >/dev/null 2>&1) || (command -v apt-get >/dev/null 2>&1 && apt-get update >/dev/null 2>&1 && apt-get install curl wget git unzip iproute2 dmidecode net-tools curl traceroute iptables ca-certificates -y >/dev/null 2>&1) ||
(command -v apk >/dev/null 2>&1 && apk update >/dev/null 2>&1 && apk add --no-cache net-tools iproute2 numactl-dev iputils iptables dmidecode -f >/dev/null 2>&1) (command -v apk >/dev/null 2>&1 && apk update >/dev/null 2>&1 && apk add --no-cache net-tools iproute2 numactl-dev iputils iptables dmidecode -f >/dev/null 2>&1)
} }
install_systemd() { install_systemd() {
@@ -131,14 +127,20 @@ install_docker() {
os_alpine="0" os_alpine="0"
[ -e /etc/os-release ] && cat /etc/os-release | grep -i "PRETTY_NAME" | grep -qi "alpine" && os_alpine='1' [ -e /etc/os-release ] && cat /etc/os-release | grep -i "PRETTY_NAME" | grep -qi "alpine" && os_alpine='1'
command -v docker >/dev/null 2>&1 command -v docker >/dev/null 2>&1
if [[ $? != 0 ]]; then if docker --version >/dev/null 2>&1; then
echo -e "${yellow}===================================================${plain}\n正在安装 Docker" echo -e "${green}已安装docker${plain}"
else
echo -e "${yellow}===================================================${plain}\n正在安装 docker"
if [ "$os_alpine" != 1 ]; then if [ "$os_alpine" != 1 ]; then
echo -e "下载docker脚本..."
bash <(curl -sL https://get.docker.com -o get-docker.sh) >/dev/null 2>&1 bash <(curl -sL https://get.docker.com -o get-docker.sh) >/dev/null 2>&1
if [[ $? != 0 ]]; then if [[ $? != 0 ]]; then
echo -e "${red}下载脚本失败,请检查本机能否连接 https://get.docker.com${plain}" echo -e "${red}下载脚本失败,请检查本机能否连接 https://get.docker.com${plain}"
return 0 return 0
fi fi
echo -e "执行docker脚本..."
chmod +x get-docker.sh
./get-docker.sh
systemctl enable docker.service >/dev/null 2>&1 systemctl enable docker.service >/dev/null 2>&1
systemctl start docker.service >/dev/null 2>&1 systemctl start docker.service >/dev/null 2>&1
else else
@@ -146,7 +148,11 @@ install_docker() {
rc-update add docker rc-update add docker
rc-service docker start rc-service docker start
fi fi
echo -e "${green}Docker 安装成功${plain}" if docker --version >/dev/null 2>&1; then
echo -e "${green}docker 安装成功${plain}"
else
echo -e "${red}docker 安装失败,可以多试几次${plain}" && exit 1
fi
fi fi
LINKER_IMAGES=$(docker ps | grep -w "linker") LINKER_IMAGES=$(docker ps | grep -w "linker")
@@ -198,7 +204,7 @@ install_docker() {
select_version() { select_version() {
if [[ -z $LINKER_IS_DOCKER ]]; then if [[ -z $LINKER_IS_DOCKER ]]; then
echo -e "${yellow}===================================================\n${plain}请自行选择您的安装方式:${yellow}\n1. Docker\n2. 独立安装${plain}" echo -e "${yellow}===================================================\n${plain}请自行选择您的安装方式:${yellow}\n1. docker\n2. 独立安装${plain}"
while true; do while true; do
read -e -r -p "请输入选择 [1-2]" option read -e -r -p "请输入选择 [1-2]" option
case "${option}" in case "${option}" in
@@ -218,7 +224,7 @@ select_version() {
fi fi
} }
install_base install_soft
select_version select_version

View File

@@ -4,6 +4,8 @@ using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Text;
using System.Text; using System.Text;
using System;
using System.Diagnostics;
namespace linker.gen namespace linker.gen
{ {
@@ -24,13 +26,15 @@ namespace linker.gen
new GeneratorInfo{ ClassName="ConfigSyncTypesLoader", ClassNameSpace="linker.plugins.config", InterfaceName="linker.plugins.config.IConfigSync"}, new GeneratorInfo{ ClassName="ConfigSyncTypesLoader", ClassNameSpace="linker.plugins.config", InterfaceName="linker.plugins.config.IConfigSync"},
new GeneratorInfo{ ClassName="DecenterTypesLoader", ClassNameSpace="linker.plugins.decenter", InterfaceName="linker.plugins.decenter.IDecenter"}, new GeneratorInfo{ ClassName="DecenterTypesLoader", ClassNameSpace="linker.plugins.decenter", InterfaceName="linker.plugins.decenter.IDecenter"},
}; };
public void Initialize(IncrementalGeneratorInitializationContext context) public void Initialize(IncrementalGeneratorInitializationContext context)
{ {
IncrementalValueProvider<Compilation> compilations = context.CompilationProvider.Select((compilation, cancellationToken) => compilation); IncrementalValueProvider<Compilation> compilations = context.CompilationProvider.Select((compilation, cancellationToken) => compilation);
context.RegisterSourceOutput(compilations, (sourceProductionContext, compilation) => context.RegisterSourceOutput(compilations, (sourceProductionContext, compilation) =>
{ {
foreach (GeneratorInfo info in generators) foreach (GeneratorInfo info in generators)
{ {
var iFlowSymbol = compilation.GetTypeByMetadataName(info.InterfaceName); var iFlowSymbol = compilation.GetTypeByMetadataName(info.InterfaceName);

View File

@@ -21,7 +21,7 @@ namespace linker.libs.api
protected readonly Dictionary<string, PluginPathCacheInfo> plugins = new(); protected readonly Dictionary<string, PluginPathCacheInfo> plugins = new();
protected readonly ConcurrentDictionary<uint, ConnectionTimeInfo> connectionTimes = new(); protected readonly ConcurrentDictionary<uint, ConnectionTimeInfo> connectionTimes = new();
public uint OnlineNum = 0; public uint OnlineNum = 0;
private Memory<byte> password = Helper.EmptyArray; private string password = string.Empty;
private WebSocketServer server; private WebSocketServer server;
@@ -34,7 +34,7 @@ namespace linker.libs.api
/// </summary> /// </summary>
public void Websocket(int port, string password = "") public void Websocket(int port, string password = "")
{ {
this.password = Encoding.UTF8.GetBytes(password); this.password = password;
server = new WebSocketServer(); server = new WebSocketServer();
try try
{ {
@@ -46,10 +46,10 @@ namespace linker.libs.api
} }
server.OnConnecting = (connection, header) => server.OnConnecting = (connection, header) =>
{ {
bool res = this.password.Length == 0 || this.password.Span.SequenceEqual(header.SecWebSocketProtocol.Span); bool res = string.IsNullOrWhiteSpace(this.password) || (header.TryGetHeaderValue(WebsocketHeaderKey.SecWebSocketProtocol, out string _password) && _password.Contains(this.password));
if (res) if (res)
{ {
header.SecWebSocketExtensions = Helper.EmptyArray; header.SetHeaderValue(WebsocketHeaderKey.SecWebSocketExtensions, string.Empty);
} }
return res; return res;
}; };

View File

@@ -1,5 +1,6 @@
using linker.libs.jsonConverters; using linker.libs.jsonConverters;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Unicode; using System.Text.Unicode;
namespace linker.libs.extends namespace linker.libs.extends
@@ -23,15 +24,15 @@ namespace linker.libs.extends
WriteIndented = true, WriteIndented = true,
Converters = { new IPAddressJsonConverter(), new IPEndpointJsonConverter(), new DateTimeConverter() } Converters = { new IPAddressJsonConverter(), new IPEndpointJsonConverter(), new DateTimeConverter() }
}; };
private static JsonSerializerOptions jsonSerializerOptionsIndented = new JsonSerializerOptions public static void AddAOT(JsonSerializerContext[] contexts)
{ {
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(UnicodeRanges.All), foreach (var context in contexts)
AllowTrailingCommas = true, {
ReadCommentHandling = JsonCommentHandling.Skip, jsonSerializerOptions1.TypeInfoResolverChain.Insert(0, context);
PropertyNameCaseInsensitive = true, jsonSerializerOptions.TypeInfoResolverChain.Insert(0, context);
WriteIndented = true, }
Converters = { new IPAddressJsonConverter(), new IPEndpointJsonConverter(), new DateTimeConverter() } }
};
public static string ToJson(this object obj) public static string ToJson(this object obj)
{ {
return JsonSerializer.Serialize(obj, jsonSerializerOptions1); return JsonSerializer.Serialize(obj, jsonSerializerOptions1);
@@ -45,4 +46,6 @@ namespace linker.libs.extends
return JsonSerializer.Deserialize<T>(json, options: jsonSerializerOptions); return JsonSerializer.Deserialize<T>(json, options: jsonSerializerOptions);
} }
} }
} }

View File

@@ -14,9 +14,9 @@
<Copyright>snltty</Copyright> <Copyright>snltty</Copyright>
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl> <PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl> <RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
<Version>1.5.9</Version> <Version>1.6.0</Version>
<AssemblyVersion>1.5.9</AssemblyVersion> <AssemblyVersion>1.6.0</AssemblyVersion>
<FileVersion>1.5.9</FileVersion> <FileVersion>1.6.0</FileVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>full</DebugType> <DebugType>full</DebugType>

View File

@@ -140,10 +140,9 @@ namespace linker.libs.websocket
{ {
token.SecWebSocketKey = WebSocketParser.BuildSecWebSocketKey(); token.SecWebSocketKey = WebSocketParser.BuildSecWebSocketKey();
byte[] connectData = WebSocketParser.BuildConnectData(new WebsocketHeaderInfo WebsocketHeaderInfo header = new WebsocketHeaderInfo();
{ header.SetHeaderValue(WebsocketHeaderKey.SecWebSocketKey, token.SecWebSocketKey);
SecWebSocketKey = token.SecWebSocketKey, byte[] connectData = WebSocketParser.BuildConnectData(header);
});
token.TargetSocket.Send(connectData, SocketFlags.None); token.TargetSocket.Send(connectData, SocketFlags.None);
@@ -366,7 +365,7 @@ namespace linker.libs.websocket
private void HandleConnect(AsyncServerUserToken token, Memory<byte> data) private void HandleConnect(AsyncServerUserToken token, Memory<byte> data)
{ {
WebsocketHeaderInfo header = WebsocketHeaderInfo.Parse(data); WebsocketHeaderInfo header = WebsocketHeaderInfo.Parse(data);
if (!WebSocketParser.VerifySecWebSocketAccept(token.SecWebSocketKey, header.SecWebSocketAccept)) if (header.TryGetHeaderValue(WebsocketHeaderKey.SecWebSocketAccept, out string accept) == false || WebSocketParser.VerifySecWebSocketAccept(token.SecWebSocketKey, accept) == false)
{ {
OnConnectFail("Sec-WebSocket-Accept Invalid"); OnConnectFail("Sec-WebSocket-Accept Invalid");
CloseClientSocket(); CloseClientSocket();
@@ -471,7 +470,7 @@ namespace linker.libs.websocket
/// 当前帧的数据类型 /// 当前帧的数据类型
/// </summary> /// </summary>
public WebSocketFrameInfo.EnumOpcode Opcode { get; set; } public WebSocketFrameInfo.EnumOpcode Opcode { get; set; }
public Memory<byte> SecWebSocketKey { get; set; } public string SecWebSocketKey { get; set; }
public byte[] PoolBuffer { get; set; } public byte[] PoolBuffer { get; set; }
public void Clear() public void Clear()

View File

@@ -1,6 +1,7 @@
using System; using System;
using System.Buffers; using System.Buffers;
using System.Buffers.Binary; using System.Buffers.Binary;
using System.Collections.Generic;
using System.Net; using System.Net;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
@@ -13,7 +14,7 @@ namespace linker.libs.websocket
public static class WebSocketParser public static class WebSocketParser
{ {
private readonly static SHA1 sha1 = SHA1.Create(); private readonly static SHA1 sha1 = SHA1.Create();
private readonly static Memory<byte> magicCode = Encoding.ASCII.GetBytes("258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); private readonly static Memory<byte> magicCode = Encoding.UTF8.GetBytes("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
/// <summary> /// <summary>
/// 构建连接数据 /// 构建连接数据
/// </summary> /// </summary>
@@ -21,21 +22,23 @@ namespace linker.libs.websocket
/// <returns></returns> /// <returns></returns>
public static byte[] BuildConnectData(WebsocketHeaderInfo header) public static byte[] BuildConnectData(WebsocketHeaderInfo header)
{ {
string path = header.Path.Length == 0 ? "/" : Encoding.UTF8.GetString(header.Path.Span); string path = header.Path.Length == 0 ? "/" : header.Path;
header.TryGetHeaderValue(WebsocketHeaderKey.SecWebSocketKey,out string key);
StringBuilder sb = new StringBuilder(10); StringBuilder sb = new StringBuilder(10);
sb.Append($"GET {path} HTTP/1.1\r\n"); sb.Append($"GET {path} HTTP/1.1\r\n");
sb.Append($"Upgrade: websocket\r\n"); sb.Append($"Upgrade: websocket\r\n");
sb.Append($"Connection: Upgrade\r\n"); sb.Append($"Connection: Upgrade\r\n");
sb.Append($"Sec-WebSocket-Version: 13\r\n"); sb.Append($"Sec-WebSocket-Version: 13\r\n");
sb.Append($"Sec-WebSocket-Key: {Encoding.UTF8.GetString(header.SecWebSocketKey.Span)}\r\n"); sb.Append($"Sec-WebSocket-Key: {key}\r\n");
if (header.SecWebSocketProtocol.Length > 0) if (header.TryGetHeaderValue(WebsocketHeaderKey.SecWebSocketProtocol, out string protocol))
{ {
sb.Append($"Sec-WebSocket-Protocol: {Encoding.UTF8.GetString(header.SecWebSocketProtocol.Span)}\r\n"); sb.Append($"Sec-WebSocket-Protocol: {protocol}\r\n");
} }
if (header.SecWebSocketExtensions.Length > 0) if (header.TryGetHeaderValue(WebsocketHeaderKey.SecWebSocketExtensions, out string extensions))
{ {
sb.Append($"Sec-WebSocket-Extensions: {Encoding.UTF8.GetString(header.SecWebSocketExtensions.Span)}\r\n"); sb.Append($"Sec-WebSocket-Extensions: {extensions}\r\n");
} }
sb.Append("\r\n"); sb.Append("\r\n");
@@ -48,30 +51,31 @@ namespace linker.libs.websocket
/// <returns></returns> /// <returns></returns>
public static byte[] BuildConnectResponseData(WebsocketHeaderInfo header) public static byte[] BuildConnectResponseData(WebsocketHeaderInfo header)
{ {
string acceptStr = BuildSecWebSocketAccept(header.SecWebSocketKey); header.TryGetHeaderValue(WebsocketHeaderKey.SecWebSocketKey,out string key);
string acceptStr = BuildSecWebSocketAccept(key);
StringBuilder sb = new StringBuilder(10); StringBuilder sb = new StringBuilder(10);
sb.Append($"HTTP/1.1 {(int)header.StatusCode} {AddSpace(header.StatusCode)}\r\n"); sb.Append($"HTTP/1.1 {(int)header.StatusCode} {AddSpace(header.StatusCode)}\r\n");
sb.Append($"Sec-WebSocket-Accept: {acceptStr}\r\n"); sb.Append($"Sec-WebSocket-Accept: {acceptStr}\r\n");
if (header.Connection.Length > 0) if (header.TryGetHeaderValue(WebsocketHeaderKey.Connection, out string str1))
{ {
sb.Append($"Connection: {Encoding.UTF8.GetString(header.Connection.Span)}\r\n"); sb.Append($"Connection: {str1}\r\n");
} }
if (header.Upgrade.Length > 0) if (header.TryGetHeaderValue(WebsocketHeaderKey.Upgrade, out str1))
{ {
sb.Append($"Upgrade: {Encoding.UTF8.GetString(header.Upgrade.Span)}\r\n"); sb.Append($"Upgrade: {str1}\r\n");
} }
if (header.SecWebSocketVersion.Length > 0) if (header.TryGetHeaderValue(WebsocketHeaderKey.SecWebSocketVersion, out str1))
{ {
sb.Append($"Sec-WebSocket-Version: {Encoding.UTF8.GetString(header.SecWebSocketVersion.Span)}\r\n"); sb.Append($"Sec-Websocket-Version: {str1}\r\n");
} }
if (header.SecWebSocketProtocol.Length > 0) if (header.TryGetHeaderValue(WebsocketHeaderKey.SecWebSocketProtocol, out str1))
{ {
sb.Append($"Sec-WebSocket-Protocol: {Encoding.UTF8.GetString(header.SecWebSocketProtocol.Span)}\r\n"); sb.Append($"Sec-WebSocket-Protocol: {str1}\r\n");
} }
if (header.SecWebSocketExtensions.Length > 0) if (header.TryGetHeaderValue(WebsocketHeaderKey.SecWebSocketExtensions, out str1))
{ {
sb.Append($"Sec-WebSocket-Extensions: {Encoding.UTF8.GetString(header.SecWebSocketExtensions.Span)}\r\n"); sb.Append($"Sec-WebSocket-Extensions: {str1}\r\n");
} }
sb.Append("\r\n"); sb.Append("\r\n");
@@ -81,7 +85,7 @@ namespace linker.libs.websocket
/// 生成随机key /// 生成随机key
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public static byte[] BuildSecWebSocketKey() public static string BuildSecWebSocketKey()
{ {
byte[] bytes = new byte[16]; byte[] bytes = new byte[16];
Random random = new Random(DateTime.Now.Ticks.GetHashCode()); Random random = new Random(DateTime.Now.Ticks.GetHashCode());
@@ -89,8 +93,7 @@ namespace linker.libs.websocket
{ {
bytes[i] = (byte)random.Next(0, 255); bytes[i] = (byte)random.Next(0, 255);
} }
byte[] res = Encoding.UTF8.GetBytes(Convert.ToBase64String(bytes)); return Convert.ToBase64String(bytes);
return res;
} }
/// <summary> /// <summary>
/// 构建mask数据 /// 构建mask数据
@@ -113,12 +116,12 @@ namespace linker.libs.websocket
/// </summary> /// </summary>
/// <param name="key"></param> /// <param name="key"></param>
/// <returns></returns> /// <returns></returns>
private static string BuildSecWebSocketAccept(Memory<byte> key) private static string BuildSecWebSocketAccept(string key)
{ {
int keyLength = key.Length + magicCode.Length; int keyLength = key.Length + magicCode.Length;
byte[] acceptBytes = new byte[keyLength]; byte[] acceptBytes = new byte[keyLength];
key.CopyTo(acceptBytes); Encoding.UTF8.GetBytes(key).AsMemory().CopyTo(acceptBytes);
magicCode.CopyTo(acceptBytes.AsMemory(key.Length)); magicCode.CopyTo(acceptBytes.AsMemory(key.Length));
string acceptStr = Convert.ToBase64String(sha1.ComputeHash(acceptBytes, 0, keyLength)); string acceptStr = Convert.ToBase64String(sha1.ComputeHash(acceptBytes, 0, keyLength));
@@ -131,10 +134,10 @@ namespace linker.libs.websocket
/// <param name="key"></param> /// <param name="key"></param>
/// <param name="accept"></param> /// <param name="accept"></param>
/// <returns></returns> /// <returns></returns>
public static bool VerifySecWebSocketAccept(Memory<byte> key, Memory<byte> accept) public static bool VerifySecWebSocketAccept(string key, string accept)
{ {
string acceptStr = BuildSecWebSocketAccept(key); string acceptStr = BuildSecWebSocketAccept(key);
return acceptStr == Encoding.UTF8.GetString(accept.Span); return acceptStr == accept;
} }
/// <summary> /// <summary>
@@ -536,113 +539,108 @@ namespace linker.libs.websocket
/// </summary> /// </summary>
public sealed class WebsocketHeaderInfo public sealed class WebsocketHeaderInfo
{ {
static byte[][] bytes = new byte[][] {
Encoding.ASCII.GetBytes("Connection: "),
Encoding.ASCII.GetBytes("Upgrade: "),
Encoding.ASCII.GetBytes("Origin: "),
Encoding.ASCII.GetBytes("Sec-WebSocket-Version: "),
Encoding.ASCII.GetBytes("Sec-WebSocket-Key: "),
Encoding.ASCII.GetBytes("Sec-WebSocket-Extensions: "),
Encoding.ASCII.GetBytes("Sec-WebSocket-Protocol: "),
Encoding.ASCII.GetBytes("Sec-WebSocket-Accept: ")
};
static byte[] httpBytes = Encoding.UTF8.GetBytes("HTTP/"); static byte[] httpBytes = Encoding.UTF8.GetBytes("HTTP/");
static byte[] endBytes = Encoding.UTF8.GetBytes("\r\n");
static byte[] splitBytes = Encoding.UTF8.GetBytes(": ");
public HttpStatusCode StatusCode { get; set; } = HttpStatusCode.SwitchingProtocols;
public Memory<byte> Method { get; private set; }
private string _pathSet { get; set; }
/// <summary> /// <summary>
/// 用这个设置path值 /// 状态码
/// </summary> /// </summary>
public string PathSet public HttpStatusCode StatusCode { get; set; } = HttpStatusCode.SwitchingProtocols;
/// <summary>
/// 方法
/// </summary>
public string Method { get; private set; }
/// <summary>
/// 路径
/// </summary>
public string Path { get; set; }
/// <summary>
/// 请求头
/// </summary>
public Dictionary<string, string> Headers { get; private set; } = new Dictionary<string, string>();
/// <summary>
/// 获取请求头
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public bool TryGetHeaderValue(string key, out string value)
{ {
get return Headers.TryGetValue(key, out value) && string.IsNullOrWhiteSpace(value) == false;
{
return _pathSet;
}
set
{
_pathSet = value;
Path = Encoding.UTF8.GetBytes(_pathSet);
}
} }
/// <summary> /// <summary>
/// 如果 仅1个字符那就是 / /// 设置请求头
/// </summary> /// </summary>
public Memory<byte> Path { get; private set; } /// <param name="key"></param>
public Memory<byte> Connection { get; private set; } /// <param name="value"></param>
public Memory<byte> Upgrade { get; private set; } public void SetHeaderValue(string key, string value)
public Memory<byte> Origin { get; private set; } {
public Memory<byte> SecWebSocketVersion { get; private set; } Headers[key] = value;
public Memory<byte> SecWebSocketKey { get; set; } }
public Memory<byte> SecWebSocketExtensions { get; set; }
public Memory<byte> SecWebSocketProtocol { get; set; } /// <summary>
public Memory<byte> SecWebSocketAccept { get; set; } /// 解析websocket请求头
/// </summary>
/// <param name="header"></param>
/// <returns></returns>
public static WebsocketHeaderInfo Parse(Memory<byte> header) public static WebsocketHeaderInfo Parse(Memory<byte> header)
{ {
Span<byte> span = header.Span; Span<byte> span = header.Span;
int flag = 0xff;
int bit = 0x01;
ulong[] res = new ulong[bytes.Length]; Span<byte> temp = span;
WebsocketHeaderInfo headerInfo = new WebsocketHeaderInfo();
for (int i = 0, len = span.Length; i < len; i++) //跳过头
temp = temp.Slice(temp.IndexOf(endBytes) + 2);
int splitIndex = 0;
//还有分割线
while ((splitIndex = temp.IndexOf(splitBytes)) >= 0)
{ {
if (span[i] == 13 && span[i + 1] == 10 && span[i + 2] == 13 && span[i + 3] == 10) //取到key
{ string key = Encoding.UTF8.GetString(temp.Slice(0, splitIndex)).ToLowerInvariant();
break; //跳过key
} temp = temp.Slice(splitIndex + 2);
if (span[i] == 13 && span[i + 1] == 10)
{
int startIndex = i + 2;
for (int k = 0; k < bytes.Length; k++)
{
if ((flag >> k & 1) == 1 && span[startIndex] == bytes[k][0])
{
if (span.Slice(startIndex, bytes[k].Length).SequenceEqual(bytes[k]))
{
int index = span.Slice(startIndex).IndexOf((byte)13);
flag &= ~(bit << k);
#pragma warning disable CS0675 // 对进行了带符号扩展的操作数使用了按位或运算符 //取到value
res[k] = (ulong)(startIndex + bytes[k].Length) << 32 | (ulong)(index - bytes[k].Length); int endIndex = temp.IndexOf(endBytes);
#pragma warning restore CS0675 // 对进行了带符号扩展的操作数使用了按位或运算符 string value = Encoding.UTF8.GetString(temp.Slice(0, endIndex));
//跳过value
temp = temp.Slice(endIndex + 2);
i += index + 1; headerInfo.Headers[key] = value;
break;
}
}
}
}
} }
WebsocketHeaderInfo headerInfo = new WebsocketHeaderInfo
{
Connection = header.Slice((int)(res[0] >> 32), (int)(res[0] & 0xffffffff)),
Upgrade = header.Slice((int)(res[1] >> 32), (int)(res[1] & 0xffffffff)),
Origin = header.Slice((int)(res[2] >> 32), (int)(res[2] & 0xffffffff)),
SecWebSocketVersion = header.Slice((int)(res[3] >> 32), (int)(res[3] & 0xffffffff)),
SecWebSocketKey = header.Slice((int)(res[4] >> 32), (int)(res[4] & 0xffffffff)),
SecWebSocketExtensions = header.Slice((int)(res[5] >> 32), (int)(res[5] & 0xffffffff)),
SecWebSocketProtocol = header.Slice((int)(res[6] >> 32), (int)(res[6] & 0xffffffff)),
SecWebSocketAccept = header.Slice((int)(res[7] >> 32), (int)(res[7] & 0xffffffff)),
};
int pathIndex = span.IndexOf((byte)32); int pathIndex = span.IndexOf((byte)32);
int pathIndex1 = span.Slice(pathIndex + 1).IndexOf((byte)32); int pathIndex1 = span.Slice(pathIndex + 1).IndexOf((byte)32);
//响应的,获取状态码
if (header.Slice(0, httpBytes.Length).Span.SequenceEqual(httpBytes)) if (header.Slice(0, httpBytes.Length).Span.SequenceEqual(httpBytes))
{ {
int code = int.Parse(Encoding.UTF8.GetString(header.Slice(pathIndex + 1, pathIndex1).Span)); int code = int.Parse(Encoding.UTF8.GetString(header.Slice(pathIndex + 1, pathIndex1).Span));
headerInfo.StatusCode = (HttpStatusCode)code; headerInfo.StatusCode = (HttpStatusCode)code;
} }
//请求的,获取路径和方法
else else
{ {
headerInfo.Path = header.Slice(pathIndex + 1, pathIndex1); headerInfo.Path = Encoding.UTF8.GetString(span.Slice(pathIndex + 1, pathIndex1));
headerInfo.Method = header.Slice(0, pathIndex); headerInfo.Method = Encoding.UTF8.GetString(span.Slice(0, pathIndex));
} }
return headerInfo; return headerInfo;
} }
}
public sealed class WebsocketHeaderKey
{
public static string Connection = "connection";
public static string Upgrade = "upgrade";
public static string Origin = "origin";
public static string SecWebSocketVersion = "sec-websocket-version";
public static string SecWebSocketKey = "sec-websocket-key";
public static string SecWebSocketExtensions = "sec-websocket-extensions";
public static string SecWebSocketProtocol = "sec-websocket-protocol";
public static string SecWebSocketAccept = "sec-websocket-accept";
} }
} }

View File

@@ -25,7 +25,7 @@ namespace linker.libs.websocket
/// </summary> /// </summary>
public Func<WebsocketConnection, WebsocketHeaderInfo, bool> OnConnecting = (connection, header) => public Func<WebsocketConnection, WebsocketHeaderInfo, bool> OnConnecting = (connection, header) =>
{ {
header.SecWebSocketExtensions = Helper.EmptyArray; return true; header.SetHeaderValue(WebsocketHeaderKey.SecWebSocketExtensions, string.Empty); return true;
}; };
/// <summary> /// <summary>
/// 已断开连接,没有收到关闭帧 /// 已断开连接,没有收到关闭帧
@@ -351,7 +351,7 @@ namespace linker.libs.websocket
private void HandleConnect(AsyncUserToken token, Memory<byte> data) private void HandleConnect(AsyncUserToken token, Memory<byte> data)
{ {
WebsocketHeaderInfo header = WebsocketHeaderInfo.Parse(data); WebsocketHeaderInfo header = WebsocketHeaderInfo.Parse(data);
if (header.SecWebSocketKey.Length == 0) if (header.TryGetHeaderValue(WebsocketHeaderKey.SecWebSocketKey,out string key) == false)
{ {
header.StatusCode = HttpStatusCode.MethodNotAllowed; header.StatusCode = HttpStatusCode.MethodNotAllowed;
token.Connectrion.ConnectResponse(header); token.Connectrion.ConnectResponse(header);

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<project ver="10" name="linker.tray.win" libEmbed="true" icon="..\linker\favicon.ico" ui="win" output="linker.tray.win.exe" CompanyName="snltty" FileDescription="linker.tray.win" LegalCopyright="Copyright (C) snltty 2024" ProductName="linker.tray.win" InternalName="linker.install.win" FileVersion="0.0.0.175" ProductVersion="0.0.0.175" publishDir="/dist/" dstrip="false" local="false" ignored="false"> <project ver="10" name="linker.tray.win" libEmbed="true" icon="..\linker\favicon.ico" ui="win" output="linker.tray.win.exe" CompanyName="snltty" FileDescription="linker.tray.win" LegalCopyright="Copyright (C) snltty 2024" ProductName="linker.tray.win" InternalName="linker.install.win" FileVersion="0.0.0.178" ProductVersion="0.0.0.178" publishDir="/dist/" dstrip="false" local="false" ignored="false">
<file name="main.aardio" path="main.aardio" comment="main.aardio"/> <file name="main.aardio" path="main.aardio" comment="main.aardio"/>
<folder name="资源文件" path="res" embed="true" local="false" ignored="false"> <folder name="资源文件" path="res" embed="true" local="false" ignored="false">
<file name="favicon.ico" path="res\favicon.ico" comment="res\favicon.ico"/> <file name="favicon.ico" path="res\favicon.ico" comment="res\favicon.ico"/>

Binary file not shown.

View File

@@ -16,9 +16,9 @@
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl> <PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl> <RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
<PackageReleaseNotes>linker tun</PackageReleaseNotes> <PackageReleaseNotes>linker tun</PackageReleaseNotes>
<Version>1.5.9</Version> <Version>1.6.0</Version>
<AssemblyVersion>1.5.9</AssemblyVersion> <AssemblyVersion>1.6.0</AssemblyVersion>
<FileVersion>1.5.9</FileVersion> <FileVersion>1.6.0</FileVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">

View File

@@ -16,9 +16,9 @@
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl> <PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl> <RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
<PackageReleaseNotes>linker tunnel</PackageReleaseNotes> <PackageReleaseNotes>linker tunnel</PackageReleaseNotes>
<Version>1.5.9</Version> <Version>1.6.0</Version>
<AssemblyVersion>1.5.9</AssemblyVersion> <AssemblyVersion>1.6.0</AssemblyVersion>
<FileVersion>1.5.9</FileVersion> <FileVersion>1.6.0</FileVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">

View File

@@ -1,4 +1,6 @@
using System.Net; using linker.libs.extends;
using System.Net;
using System.Text;
namespace linker.tunnel.wanport namespace linker.tunnel.wanport
{ {
@@ -16,6 +18,7 @@ namespace linker.tunnel.wanport
/// <param name="server">服务器</param> /// <param name="server">服务器</param>
/// <returns></returns> /// <returns></returns>
public Task<TunnelWanPortEndPoint> GetAsync(IPAddress inter, IPEndPoint server); public Task<TunnelWanPortEndPoint> GetAsync(IPAddress inter, IPEndPoint server);
} }
public sealed class TunnelWanPortEndPoint public sealed class TunnelWanPortEndPoint

View File

@@ -3,6 +3,7 @@ using linker.libs.extends;
using System.Buffers; using System.Buffers;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text;
namespace linker.tunnel.wanport namespace linker.tunnel.wanport
{ {
@@ -23,36 +24,37 @@ namespace linker.tunnel.wanport
udpClient.Client.ReuseBind(new IPEndPoint(localIP, 0)); udpClient.Client.ReuseBind(new IPEndPoint(localIP, 0));
udpClient.Client.WindowsUdpBug(); udpClient.Client.WindowsUdpBug();
byte[] buffer = ArrayPool<byte>.Shared.Rent(1024);
try try
{ {
for (int i = 0; i < 5; i++) await udpClient.SendAsync(BuildSendData(buffer, 0), server).ConfigureAwait(false);
TimerHelper.Async(async () =>
{ {
try for (byte i = 1; i < 10; i++)
{
await udpClient.SendAsync(new byte[1] { 0 }, server).ConfigureAwait(false);
UdpReceiveResult result = await udpClient.ReceiveAsync().WaitAsync(TimeSpan.FromMilliseconds(2000)).ConfigureAwait(false);
if (result.Buffer.Length == 0)
{
return null;
}
for (int j = 0; j < result.Buffer.Length; j++)
{
result.Buffer[j] = (byte)(result.Buffer[j] ^ byte.MaxValue);
}
AddressFamily addressFamily = (AddressFamily)result.Buffer[0];
int length = addressFamily == AddressFamily.InterNetwork ? 4 : 16;
IPAddress ip = new IPAddress(result.Buffer.AsSpan(1, length));
ushort port = result.Buffer.AsMemory(1 + length).ToUInt16();
IPEndPoint remoteEP = new IPEndPoint(ip, port);
return new TunnelWanPortEndPoint { Local = udpClient.Client.LocalEndPoint as IPEndPoint, Remote = remoteEP };
}
catch (Exception)
{ {
await Task.Delay(15);
await udpClient.SendAsync(BuildSendData(buffer, i), server).ConfigureAwait(false);
} }
});
UdpReceiveResult result = await udpClient.ReceiveAsync().WaitAsync(TimeSpan.FromMilliseconds(2000)).ConfigureAwait(false);
if (result.Buffer.Length == 0)
{
return null;
} }
for (int j = 0; j < result.Buffer.Length; j++)
{
result.Buffer[j] = (byte)(result.Buffer[j] ^ byte.MaxValue);
}
AddressFamily addressFamily = (AddressFamily)result.Buffer[0];
int length = addressFamily == AddressFamily.InterNetwork ? 4 : 16;
IPAddress ip = new IPAddress(result.Buffer.AsSpan(1, length));
ushort port = result.Buffer.AsMemory(1 + length).ToUInt16();
IPEndPoint remoteEP = new IPEndPoint(ip, port);
return new TunnelWanPortEndPoint { Local = udpClient.Client.LocalEndPoint as IPEndPoint, Remote = remoteEP };
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -61,11 +63,21 @@ namespace linker.tunnel.wanport
} }
finally finally
{ {
ArrayPool<byte>.Shared.Return(buffer);
udpClient.Close(); udpClient.Close();
} }
return null; return null;
} }
private Memory<byte> BuildSendData(byte[] buffer, byte i)
{
byte[] temp = Encoding.UTF8.GetBytes(Environment.TickCount64.ToString().Md5().SubStr(0, new Random().Next(16, 32)));
temp.AsMemory().CopyTo(buffer);
buffer[0] = 0;
buffer[1] = i;
return buffer.AsMemory(0, temp.Length);
}
} }
@@ -82,13 +94,15 @@ namespace linker.tunnel.wanport
public async Task<TunnelWanPortEndPoint> GetAsync(IPAddress localIP, IPEndPoint server) public async Task<TunnelWanPortEndPoint> GetAsync(IPAddress localIP, IPEndPoint server)
{ {
byte[] buffer = ArrayPool<byte>.Shared.Rent(20); byte[] buffer = ArrayPool<byte>.Shared.Rent(1024);
try try
{ {
Socket socket = new Socket(server.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); Socket socket = new Socket(server.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
socket.ReuseBind(new IPEndPoint(localIP, 0)); socket.ReuseBind(new IPEndPoint(localIP, 0));
await socket.ConnectAsync(server).ConfigureAwait(false); await socket.ConnectAsync(server).ConfigureAwait(false);
await socket.SendAsync(new byte[] { 0 });
await socket.SendAsync(BuildSendData(buffer, (byte)new Random().Next(0, 255)));
int length = await socket.ReceiveAsync(buffer.AsMemory(), SocketFlags.None).ConfigureAwait(false); int length = await socket.ReceiveAsync(buffer.AsMemory(), SocketFlags.None).ConfigureAwait(false);
for (int j = 0; j < length; j++) for (int j = 0; j < length; j++)
{ {
@@ -118,5 +132,15 @@ namespace linker.tunnel.wanport
return null; return null;
} }
private Memory<byte> BuildSendData(byte[] buffer, byte i)
{
byte[] temp = Encoding.UTF8.GetBytes(Environment.TickCount64.ToString().Md5().SubStr(0, new Random().Next(16, 32)));
temp.AsMemory().CopyTo(buffer);
buffer[0] = 0;
buffer[1] = i;
return buffer.AsMemory(0, temp.Length);
}
} }
} }

View File

@@ -4,7 +4,6 @@ using linker.startup;
using linker.config; using linker.config;
using System.ServiceProcess; using System.ServiceProcess;
using System.Diagnostics; using System.Diagnostics;
using linker.libs.extends;
namespace linker namespace linker
{ {

View File

@@ -174,6 +174,7 @@ namespace linker.config
} }
} }
[JsonAotAttribute]
public sealed partial class ConfigCommonInfo : IConfig public sealed partial class ConfigCommonInfo : IConfig
{ {
public ConfigCommonInfo() { } public ConfigCommonInfo() { }
@@ -223,4 +224,8 @@ namespace linker.config
return text.DeJson<ConfigCommonInfo>(); return text.DeJson<ConfigCommonInfo>();
} }
} }
[AttributeUsage(AttributeTargets.Class)]
public class JsonAotAttribute : Attribute { }
} }

View File

@@ -21,17 +21,16 @@
<Title>linker</Title> <Title>linker</Title>
<Authors>snltty</Authors> <Authors>snltty</Authors>
<Company>snltty</Company> <Company>snltty</Company>
<Description>1. 优化UI <Description>1. 优化websocket(某些代理环境下可能请求头key名称不规范)
2. 优化网卡 2. 尝试解决UDP获取外网IP端口失败的问题
3. 修复网卡禁用自动重启 3. 测试中</Description>
4. 增加一键安装脚本</Description>
<Copyright>snltty</Copyright> <Copyright>snltty</Copyright>
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl> <PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl> <RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
<PackageReleaseNotes>linker</PackageReleaseNotes> <PackageReleaseNotes>linker</PackageReleaseNotes>
<Version>1.5.9</Version> <Version>1.6.0</Version>
<AssemblyVersion>1.5.9</AssemblyVersion> <AssemblyVersion>1.6.0</AssemblyVersion>
<FileVersion>1.5.9</FileVersion> <FileVersion>1.6.0</FileVersion>
</PropertyGroup> </PropertyGroup>
@@ -76,4 +75,7 @@
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />
<PackageReference Include="System.ServiceProcess.ServiceController" Version="8.0.1" /> <PackageReference Include="System.ServiceProcess.ServiceController" Version="8.0.1" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="plugins\pcp\" />
</ItemGroup>
</Project> </Project>

View File

@@ -7,6 +7,7 @@ using linker.plugins.client;
using linker.plugins.tunnel; using linker.plugins.tunnel;
using linker.plugins.messenger; using linker.plugins.messenger;
using linker.plugins.relay.client; using linker.plugins.relay.client;
using linker.client.config;
namespace linker.plugins.forward.proxy namespace linker.plugins.forward.proxy
{ {
@@ -18,8 +19,8 @@ namespace linker.plugins.forward.proxy
protected override string TransactionId => "forward"; protected override string TransactionId => "forward";
public ForwardProxy(FileConfig config, TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, ClientSignInTransfer clientSignInTransfer, ClientSignInState clientSignInState) public ForwardProxy(FileConfig config, TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, ClientSignInTransfer clientSignInTransfer, ClientSignInState clientSignInState, RunningConfig runningConfig)
: base(config, tunnelTransfer, relayTransfer, clientSignInTransfer, clientSignInState) : base(config, tunnelTransfer, relayTransfer, clientSignInTransfer, clientSignInState, runningConfig)
{ {
TaskUdp(); TaskUdp();
} }

View File

@@ -52,6 +52,8 @@ namespace linker.plugins.relay.client.transport
relayInfo.FlowingId = relayAskResultInfo.FlowingId; relayInfo.FlowingId = relayAskResultInfo.FlowingId;
if (relayInfo.FlowingId == 0 || relayAskResultInfo.Nodes.Count == 0) if (relayInfo.FlowingId == 0 || relayAskResultInfo.Nodes.Count == 0)
{ {
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Error($"relay ask fail,flowid:{relayInfo.FlowingId},nodes:{relayAskResultInfo.Nodes.Count}");
return null; return null;
} }
@@ -65,12 +67,16 @@ namespace linker.plugins.relay.client.transport
Socket socket = await ConnectNodeServer(relayInfo, relayAskResultInfo.Nodes); Socket socket = await ConnectNodeServer(relayInfo, relayAskResultInfo.Nodes);
if (socket == null) if (socket == null)
{ {
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Error($"relay connect server fail,flowid:{relayInfo.FlowingId},nodes:{relayAskResultInfo.Nodes.Count}");
return null; return null;
} }
//让对方确认中继 //让对方确认中继
if (await RelayConfirm(relayInfo) == false) if (await RelayConfirm(relayInfo) == false)
{ {
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Error($"relay confirm fail,flowid:{relayInfo.FlowingId},nodes:{relayAskResultInfo.Nodes.Count}");
return null; return null;
} }
@@ -212,9 +218,8 @@ namespace linker.plugins.relay.client.transport
} }
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Debug($"connect relay server {ep}"); LoggerHelper.Instance.Debug($"connect relay server {ep}");
}
//连接中继服务器 //连接中继服务器
Socket socket = new Socket(ep.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); Socket socket = new Socket(ep.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
socket.KeepAlive(); socket.KeepAlive();
@@ -232,8 +237,13 @@ namespace linker.plugins.relay.client.transport
await socket.SendAsync(new byte[] { (byte)ResolverType.Relay }); await socket.SendAsync(new byte[] { (byte)ResolverType.Relay });
await socket.SendAsync(MemoryPackSerializer.Serialize(relayMessage)); await socket.SendAsync(MemoryPackSerializer.Serialize(relayMessage));
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Debug($"relay connected {ep}");
//是否允许连接 //是否允许连接
int length = await socket.ReceiveAsync(buffer); int length = await socket.ReceiveAsync(buffer.AsMemory(0, 1));
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Debug($"relay connected {ep}->{buffer[0]}");
if (buffer[0] == 0) if (buffer[0] == 0)
{ {
relayInfo.Server = node.EndPoint; relayInfo.Server = node.EndPoint;

View File

@@ -5,6 +5,8 @@ using System.Collections.Concurrent;
using linker.plugins.resolver; using linker.plugins.resolver;
using System.Net; using System.Net;
using MemoryPack; using MemoryPack;
using linker.config;
using linker.libs;
namespace linker.plugins.relay.server namespace linker.plugins.relay.server
{ {
@@ -25,7 +27,7 @@ namespace linker.plugins.relay.server
private readonly ConcurrentDictionary<ulong, RelayWrap> relayDic = new ConcurrentDictionary<ulong, RelayWrap>(); private readonly ConcurrentDictionary<ulong, RelayWrap> relayDic = new ConcurrentDictionary<ulong, RelayWrap>();
public virtual void AddReceive(string key, string from, string to,string groupid, ulong bytes) public virtual void AddReceive(string key, string from, string to, string groupid, ulong bytes)
{ {
} }
public virtual void AddSendt(string key, string from, string to, string groupid, ulong bytes) public virtual void AddSendt(string key, string from, string to, string groupid, ulong bytes)
@@ -51,10 +53,12 @@ namespace linker.plugins.relay.server
int length = await socket.ReceiveAsync(buffer.AsMemory(), SocketFlags.None).ConfigureAwait(false); int length = await socket.ReceiveAsync(buffer.AsMemory(), SocketFlags.None).ConfigureAwait(false);
RelayMessage relayMessage = MemoryPackSerializer.Deserialize<RelayMessage>(buffer.AsMemory(0, length).Span); RelayMessage relayMessage = MemoryPackSerializer.Deserialize<RelayMessage>(buffer.AsMemory(0, length).Span);
if (relayMessage.Type == RelayMessengerType.Ask) if (relayMessage.Type == RelayMessengerType.Ask && relayMessage.NodeId != RelayNodeInfo.MASTER_NODE_ID)
{ {
if (relayServerNodeTransfer.Invalid()) if (relayServerNodeTransfer.Validate() == false)
{ {
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Debug($"relay Validate false,flowid:{relayMessage.FlowId}");
await socket.SendAsync(new byte[] { 1 }); await socket.SendAsync(new byte[] { 1 });
socket.SafeClose(); socket.SafeClose();
return; return;

View File

@@ -75,9 +75,9 @@ namespace linker.plugins.relay.server
/// 无效请求 /// 无效请求
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public bool Invalid() public bool Validate()
{ {
return ValidateConnection() == false || ValidateBytes() == false; return ValidateConnection() && ValidateBytes();
} }
/// <summary> /// <summary>
@@ -100,7 +100,11 @@ namespace linker.plugins.relay.server
/// <returns></returns> /// <returns></returns>
public bool ValidateConnection() public bool ValidateConnection()
{ {
return fileConfig.Data.Server.Relay.Distributed.Node.MaxConnection == 0 || fileConfig.Data.Server.Relay.Distributed.Node.MaxConnection * 2 > connectionNum; bool res = fileConfig.Data.Server.Relay.Distributed.Node.MaxConnection == 0 || fileConfig.Data.Server.Relay.Distributed.Node.MaxConnection * 2 > connectionNum;
if (res == false && LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Debug($"relay ValidateConnection false,{connectionNum}/{fileConfig.Data.Server.Relay.Distributed.Node.MaxConnection*2}");
return res;
} }
/// <summary> /// <summary>
@@ -109,8 +113,13 @@ namespace linker.plugins.relay.server
/// <returns></returns> /// <returns></returns>
public bool ValidateBytes() public bool ValidateBytes()
{ {
return fileConfig.Data.Server.Relay.Distributed.Node.MaxGbTotal == 0 bool res= fileConfig.Data.Server.Relay.Distributed.Node.MaxGbTotal == 0
|| (fileConfig.Data.Server.Relay.Distributed.Node.MaxGbTotal > 0 && fileConfig.Data.Server.Relay.Distributed.Node.MaxGbTotalLastBytes > 0); || (fileConfig.Data.Server.Relay.Distributed.Node.MaxGbTotal > 0 && fileConfig.Data.Server.Relay.Distributed.Node.MaxGbTotalLastBytes > 0);
if (res == false && LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Debug($"relay ValidateBytes false,{fileConfig.Data.Server.Relay.Distributed.Node.MaxGbTotalLastBytes}bytes/{fileConfig.Data.Server.Relay.Distributed.Node.MaxGbTotal}gb");
return res;
} }
/// <summary> /// <summary>
/// 添加流量 /// 添加流量

View File

@@ -13,6 +13,7 @@ using linker.plugins.socks5.config;
using System.Text; using System.Text;
using System.Collections.Generic; using System.Collections.Generic;
using linker.plugins.relay.client; using linker.plugins.relay.client;
using linker.client.config;
namespace linker.plugins.socks5 namespace linker.plugins.socks5
{ {
@@ -25,8 +26,8 @@ namespace linker.plugins.socks5
protected override string TransactionId => "socks5"; protected override string TransactionId => "socks5";
public TunnelProxy(FileConfig config, TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, ClientSignInTransfer clientSignInTransfer, ClientSignInState clientSignInState) public TunnelProxy(FileConfig config, TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, ClientSignInTransfer clientSignInTransfer, ClientSignInState clientSignInState, RunningConfig runningConfig)
: base(config, tunnelTransfer, relayTransfer, clientSignInTransfer, clientSignInState) : base(config, tunnelTransfer, relayTransfer, clientSignInTransfer, clientSignInState, runningConfig)
{ {
TaskUdp(); TaskUdp();
} }

View File

@@ -3,6 +3,9 @@ using System.Net;
using System.Buffers; using System.Buffers;
using linker.libs.extends; using linker.libs.extends;
using linker.plugins.resolver; using linker.plugins.resolver;
using linker.libs;
using System.Text;
using System;
namespace linker.plugins.tunnel namespace linker.plugins.tunnel
{ {
@@ -28,6 +31,8 @@ namespace linker.plugins.tunnel
/// <returns></returns> /// <returns></returns>
public async Task Resolve(Socket socket, IPEndPoint ep, Memory<byte> memory) public async Task Resolve(Socket socket, IPEndPoint ep, Memory<byte> memory)
{ {
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Debug($"{ep} get udp external port");
AddReceive((ulong)memory.Length); AddReceive((ulong)memory.Length);
byte[] sendData = ArrayPool<byte>.Shared.Rent(20); byte[] sendData = ArrayPool<byte>.Shared.Rent(20);
try try
@@ -36,8 +41,9 @@ namespace linker.plugins.tunnel
AddSendt((ulong)send.Length); AddSendt((ulong)send.Length);
await socket.SendToAsync(send, SocketFlags.None, ep).ConfigureAwait(false); await socket.SendToAsync(send, SocketFlags.None, ep).ConfigureAwait(false);
} }
catch (Exception) catch (Exception ex)
{ {
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Error(ex);
} }
finally finally
{ {
@@ -51,15 +57,17 @@ namespace linker.plugins.tunnel
/// <returns></returns> /// <returns></returns>
public async Task Resolve(Socket socket, Memory<byte> memory) public async Task Resolve(Socket socket, Memory<byte> memory)
{ {
byte[] sendData = ArrayPool<byte>.Shared.Rent(20); if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Debug($"{socket.RemoteEndPoint} get tcp external port");
byte[] sendData = ArrayPool<byte>.Shared.Rent(1024);
try try
{ {
memory = BuildSendData(sendData, socket.RemoteEndPoint as IPEndPoint); memory = BuildSendData(sendData, socket.RemoteEndPoint as IPEndPoint);
AddSendt((ulong)memory.Length); AddSendt((ulong)memory.Length);
await socket.SendAsync(memory, SocketFlags.None).ConfigureAwait(false); await socket.SendAsync(memory, SocketFlags.None).ConfigureAwait(false);
} }
catch (Exception) catch (Exception ex)
{ {
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) LoggerHelper.Instance.Error(ex);
} }
finally finally
{ {
@@ -78,7 +86,11 @@ namespace linker.plugins.tunnel
{ {
data[i] = (byte)(data[i] ^ byte.MaxValue); data[i] = (byte)(data[i] ^ byte.MaxValue);
} }
return data.AsMemory(0, 1 + length + 2);
byte[] temp = Encoding.UTF8.GetBytes(Environment.TickCount64.ToString().Md5().SubStr(0, new Random().Next(16, 32)));
temp.AsMemory().CopyTo(data.AsMemory(1 + length + 2));
return data.AsMemory(0, 1 + length + 2 + temp.Length);
} }
} }

View File

@@ -6,6 +6,7 @@ using linker.tunnel;
using linker.tunnel.connection; using linker.tunnel.connection;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using linker.plugins.relay.client; using linker.plugins.relay.client;
using linker.client.config;
namespace linker.plugins.tunnel namespace linker.plugins.tunnel
{ {
@@ -21,16 +22,18 @@ namespace linker.plugins.tunnel
private readonly RelayTransfer relayTransfer; private readonly RelayTransfer relayTransfer;
private readonly ClientSignInTransfer clientSignInTransfer; private readonly ClientSignInTransfer clientSignInTransfer;
private readonly ClientSignInState clientSignInState; private readonly ClientSignInState clientSignInState;
private readonly RunningConfig runningConfig;
private uint maxTimes = 3; private uint maxTimes = 3;
public TunnelBase(FileConfig config, TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, ClientSignInTransfer clientSignInTransfer, ClientSignInState clientSignInState) public TunnelBase(FileConfig config, TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, ClientSignInTransfer clientSignInTransfer, ClientSignInState clientSignInState, RunningConfig runningConfig)
{ {
this.config = config; this.config = config;
this.tunnelTransfer = tunnelTransfer; this.tunnelTransfer = tunnelTransfer;
this.relayTransfer = relayTransfer; this.relayTransfer = relayTransfer;
this.clientSignInTransfer = clientSignInTransfer; this.clientSignInTransfer = clientSignInTransfer;
this.clientSignInState = clientSignInState; this.clientSignInState = clientSignInState;
this.runningConfig = runningConfig;
//监听打洞成功 //监听打洞成功
tunnelTransfer.SetConnectedCallback(TransactionId, OnConnected); tunnelTransfer.SetConnectedCallback(TransactionId, OnConnected);

View File

@@ -4,7 +4,6 @@ using linker.libs;
using linker.plugins.client; using linker.plugins.client;
using linker.plugins.decenter; using linker.plugins.decenter;
using linker.plugins.messenger; using linker.plugins.messenger;
using linker.plugins.tunnel.messenger;
using linker.tunnel; using linker.tunnel;
using linker.tunnel.adapter; using linker.tunnel.adapter;
using MemoryPack; using MemoryPack;

View File

@@ -29,6 +29,7 @@ namespace linker.client.config
public int PortMapWan { get; set; } public int PortMapWan { get; set; }
public int PortMapLan { get; set; } public int PortMapLan { get; set; }
} }
[MemoryPackable] [MemoryPackable]

View File

@@ -32,7 +32,7 @@ namespace linker.plugins.tuntap
private readonly ClientSignInState clientSignInState; private readonly ClientSignInState clientSignInState;
public TuntapProxy(FileConfig config, RunningConfig runningConfig, TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, ClientSignInTransfer clientSignInTransfer, LinkerTunDeviceAdapter linkerTunDeviceAdapter, ClientSignInState clientSignInState) public TuntapProxy(FileConfig config, RunningConfig runningConfig, TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, ClientSignInTransfer clientSignInTransfer, LinkerTunDeviceAdapter linkerTunDeviceAdapter, ClientSignInState clientSignInState)
: base(config, tunnelTransfer, relayTransfer, clientSignInTransfer, clientSignInState) : base(config, tunnelTransfer, relayTransfer, clientSignInTransfer, clientSignInState, runningConfig)
{ {
this.config = config; this.config = config;
this.runningConfig = runningConfig; this.runningConfig = runningConfig;

View File

@@ -33,16 +33,16 @@ do
fi fi
done done
cd public/publish/docker/linux-${p}-x64/${f} cd public/publish/docker/linux-${p}-x64/${f}
docker buildx build -f ${target}/public/publish/docker/linux-${p}-x64/${f}/Dockerfile-${p} --platform="linux/x86_64" --force-rm -t "${image}-${p}-x64:latest" -t "${image}-${p}-x64:v1.5.9" . --push docker buildx build -f ${target}/public/publish/docker/linux-${p}-x64/${f}/Dockerfile-${p} --platform="linux/x86_64" --force-rm -t "${image}-${p}-x64:latest" -t "${image}-${p}-x64:v1.6.0" . --push
cd ../../../../../ cd ../../../../../
cd public/publish/docker/linux-${p}-arm64/${f} cd public/publish/docker/linux-${p}-arm64/${f}
docker buildx build -f ${target}/public/publish/docker/linux-${p}-arm64/${f}/Dockerfile-${p} --platform="linux/arm64" --force-rm -t "${image}-${p}-arm64:latest" -t "${image}-${p}-arm64:v1.5.9" . --push docker buildx build -f ${target}/public/publish/docker/linux-${p}-arm64/${f}/Dockerfile-${p} --platform="linux/arm64" --force-rm -t "${image}-${p}-arm64:latest" -t "${image}-${p}-arm64:v1.6.0" . --push
cd ../../../../../ cd ../../../../../
cd public/publish/docker/linux-${p}-arm/${f} cd public/publish/docker/linux-${p}-arm/${f}
docker buildx build -f ${target}/public/publish/docker/linux-${p}-arm/${f}/Dockerfile-${p} --platform="linux/arm/v7" --force-rm -t "${image}-${p}-arm:latest" -t "${image}-${p}-arm:v1.5.9" . --push docker buildx build -f ${target}/public/publish/docker/linux-${p}-arm/${f}/Dockerfile-${p} --platform="linux/arm/v7" --force-rm -t "${image}-${p}-arm:latest" -t "${image}-${p}-arm:v1.6.0" . --push
cd ../../../../../ cd ../../../../../
done done
done done

View File

@@ -1,6 +1,5 @@
v1.5.9 v1.6.0
2024-11-22 17:23:21 2024-11-29 00:49:22
1. 优化UI 1. 优化websocket(某些代理环境下可能请求头key名称不规范)
2. 优化网卡 2. 尝试解决UDP获取外网IP端口失败的问题
3. 修复网卡禁用自动重启 3. 测试中
4. 增加一键安装脚本