mirror of
https://github.com/snltty/linker.git
synced 2025-09-28 14:02:13 +08:00
182
This commit is contained in:
2
.github/workflows/dotnet.yml
vendored
2
.github/workflows/dotnet.yml
vendored
@@ -37,7 +37,7 @@ jobs:
|
|||||||
release_name: v1.8.2.${{ steps.date.outputs.today }}
|
release_name: v1.8.2.${{ steps.date.outputs.today }}
|
||||||
draft: false
|
draft: false
|
||||||
prerelease: false
|
prerelease: false
|
||||||
body: "1. 一些累计更新\r\n2. 测试发布,请使用1.8.2"
|
body: "1. 一些累计更新\r\n2. 重建权限存储,ulong改为BitArray,同组所有客户端需保持版本一致\r\n3. 增加唤醒功能,支持WOL,COM继电器,HID继电器\r\n4. 基于One-KVM包装docker镜像集成linker\r\n5. 管理端口改为1804,一个端口托管Web+Websocket"
|
||||||
- name: publish projects
|
- name: publish projects
|
||||||
run: ./publish.bat "C:\\Android\\android-sdk"
|
run: ./publish.bat "C:\\Android\\android-sdk"
|
||||||
- name: upload-win-x86-oss
|
- name: upload-win-x86-oss
|
||||||
|
@@ -20,7 +20,7 @@ namespace linker.app
|
|||||||
MainThread.BeginInvokeOnMainThread(() =>
|
MainThread.BeginInvokeOnMainThread(() =>
|
||||||
{
|
{
|
||||||
IApiStore apiStore = LinkerMessengerEntry.GetService<IApiStore>();
|
IApiStore apiStore = LinkerMessengerEntry.GetService<IApiStore>();
|
||||||
webview.Source = new Uri($"http://127.0.0.1:{apiStore.Info.WebPort}?t={DateTime.Now.Ticks}/#/?api={apiStore.Info.ApiPort}&psd={Helper.GlobalString}");
|
webview.Source = new Uri($"http://127.0.0.1:{apiStore.Info.WebPort}?t={DateTime.Now.Ticks}/#/?api={apiStore.Info.WebPort}&psd={Helper.GlobalString}");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -9,7 +9,7 @@ sidebar_position: 0
|
|||||||
:::
|
:::
|
||||||
|
|
||||||
:::tip[客户端]
|
:::tip[客户端]
|
||||||
1. 客户端模式 监听端口 `1803(TCP)`websocket管理接口,`1804(TCP)`管理UI端口
|
1. 客户端模式 管理接口`1804(TCP)`
|
||||||
2. 运行起来后可以使用`http://127.0.0.1:1804`打开管理页面,如果是windows,也可以在`linker.tray.win.exe`托盘程序里打开管理页面
|
2. 运行起来后可以使用`http://127.0.0.1:1804`打开管理页面,如果是windows,也可以在`linker.tray.win.exe`托盘程序里打开管理页面
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
@@ -31,7 +31,7 @@ sc delete 服务名
|
|||||||
|
|
||||||
1. 由于linker使用当前目录下的`configs`文件夹里的配置文件,所以不能使用同一程序多开,需要使用多份程序,**不要把`configs`文件夹也复制过去**
|
1. 由于linker使用当前目录下的`configs`文件夹里的配置文件,所以不能使用同一程序多开,需要使用多份程序,**不要把`configs`文件夹也复制过去**
|
||||||
2. 客户端托盘无法多开,所以需要客户端多开时,**需要你手动安装服务**,不能使用托盘安装服务
|
2. 客户端托盘无法多开,所以需要客户端多开时,**需要你手动安装服务**,不能使用托盘安装服务
|
||||||
3. 客户端会监听两个端口,默认为`1803` 管理接口,`1804`网页服务,所以,在初始化时,你需要各个客户端**使用不同的端口**
|
3. 客户端会监听`1804` 管理接口,所以,在初始化时,你需要各个客户端**使用不同的端口**
|
||||||
|
|
||||||
#### 在初始化时,`接口端口`,和`网页端口`,需要各个客户端设置为不一样的端口
|
#### 在初始化时,`接口端口`,和`网页端口`,需要各个客户端设置为不一样的端口
|
||||||

|

|
||||||
|
@@ -25,19 +25,16 @@ chmod +x linker-install.sh
|
|||||||
|
|
||||||
:::tip[说明]
|
:::tip[说明]
|
||||||
|
|
||||||
1. 服务端端口 `1802` TCP+UDP
|
1. 服务端端口 `1802` TCP+UDP、客户端端口 `1804` TCP
|
||||||
2. 客户端端口 `1804`、`1803` TCP
|
2. 配置文件夹 `./configs`、日志文件夹 `./logs`
|
||||||
3. 配置文件夹 `./configs`
|
3. 镜像清单 `snltty/linker-debian`、`snltty/linker-musl`、`snltty/linker-kvm` 或者 `snltty/linker-debian-{arch}`、`snltty/linker-musl-{arch}`、`snltty/linker-kvm-{arch}`,`{arch}`可以是`x64`、`arm64`、`arm`
|
||||||
4. 日志文件夹 `./logs`
|
4. `bridge`模式,需要映射一些端口比如`-p 18000-18010:18000-18010`,用于端口转发,或者直接使用host`--network host`,**建议使用host,点对网,网对网,端口转发都方便**
|
||||||
5. 镜像清单 `snltty/linker-debian`、`snltty/linker-musl`、`snltty/linker-kvm`
|
5. 如果你使用的是KVM镜像,那么会多需要几个端口`1806 http`、`1807 https`、`5900 VNC`、`623 ipmi`
|
||||||
6. 特定平台 `snltty/linker-debian-{arch}`、`snltty/linker-musl-{arch}`、`snltty/linker-kvm-{arch}`,`{arch}`可以是`x64`、`arm64`、`arm`
|
|
||||||
7. `bridge`模式,需要映射一些端口比如`-p 18000-18010:18000-18010`,用于端口转发
|
|
||||||
8. `host`模式,或者直接使用host`--network host`,**建议使用host,点对网,网对网,端口转发都方便**
|
|
||||||
|
|
||||||
#### 客户端-bridge
|
#### 客户端-bridge
|
||||||
```
|
```
|
||||||
docker run -it -d --name linker \
|
docker run -it -d --name linker \
|
||||||
-p 1804:1804/tcp -p 1803:1803/tcp \
|
-p 1804:1804/tcp \
|
||||||
-p 18000-18010:18000-18010/tcp \
|
-p 18000-18010:18000-18010/tcp \
|
||||||
-p 18000-18010:18000-18010/udp \
|
-p 18000-18010:18000-18010/udp \
|
||||||
-v /usr/local/linker-docker/configs:/app/configs \
|
-v /usr/local/linker-docker/configs:/app/configs \
|
||||||
@@ -47,6 +44,41 @@ docker run -it -d --name linker \
|
|||||||
--privileged=true \
|
--privileged=true \
|
||||||
snltty/linker-musl
|
snltty/linker-musl
|
||||||
```
|
```
|
||||||
|
#### 客户端-bridge-kvm
|
||||||
|
|
||||||
|
1. 基于[One-KVM](https://one-kvm.mofeng.run/start_install/docker_install/)的docker镜像包装,集成linker
|
||||||
|
2. 在linker参数的基础上,再加上KVM的参数,根据自己的需求修改一下参数即可
|
||||||
|
3. 使用 1806 端口打开KVM管理页面
|
||||||
|
|
||||||
|
```
|
||||||
|
docker run --name linker-kvm -itd \
|
||||||
|
-p 1804:1804/tcp \
|
||||||
|
-p 18000-18010:18000-18010/tcp \
|
||||||
|
-p 18000-18010:18000-18010/udp \
|
||||||
|
-v /usr/local/linker-docker/configs:/app/configs \
|
||||||
|
-v /usr/local/linker-docker/logs:/app/logs \
|
||||||
|
--device /dev/net/tun \
|
||||||
|
--restart=always \
|
||||||
|
--privileged=true \
|
||||||
|
--network host \
|
||||||
|
-p 1806:1806/tcp -p 1806:1806/udp \ #网页http端口
|
||||||
|
-p 1807:1807/tcp -p 1807:1807/udp \ #网页https端口
|
||||||
|
-p 5900:5900/tcp -p 5900:5900/udp \ #vnc端口
|
||||||
|
-p 623:623/tcp -p 623:623/udp \ #ipmi端口
|
||||||
|
--device /dev/video0:/dev/video0 \ #采集卡
|
||||||
|
--device /dev/snd:/dev/snd -e AUDIONUM=0 \ #声卡
|
||||||
|
--device /dev/hidraw1:/dev/hidraw1 -e ATX=USBRELAY_HID \ #HID继电器
|
||||||
|
--device /dev/ttyUSB0:/dev/ttyUSB0 -e CH9329SPEED=9600 \ #CH9329键盘鼠标
|
||||||
|
-v /usr/local/linker-docker/kvmd:/etc/kvmd \ #映射配置目录
|
||||||
|
-e USERNAME=snltty -e PASSWORD=snltty -e NOAUTH=1 \ #账号密码,禁用认证
|
||||||
|
-e NOVNC=1 \ #禁用vnc
|
||||||
|
-e NOIPMI=1 \ #禁用ipmi
|
||||||
|
-e NOWEBTERM=1 -e NOWEBTERMWRITE=1 \ #禁用webterm
|
||||||
|
-e NOSSL=1 \ #禁用ssl
|
||||||
|
snltty/linker-kvm
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
#### 客户端-host
|
#### 客户端-host
|
||||||
```
|
```
|
||||||
docker run -it -d --name linker \
|
docker run -it -d --name linker \
|
||||||
@@ -58,6 +90,32 @@ docker run -it -d --name linker \
|
|||||||
--network host \
|
--network host \
|
||||||
snltty/linker-musl
|
snltty/linker-musl
|
||||||
```
|
```
|
||||||
|
#### 客户端-host-kvm
|
||||||
|
|
||||||
|
1. 基于[One-KVM](https://one-kvm.mofeng.run/start_install/docker_install/)的docker镜像包装,集成linker
|
||||||
|
2. 在linker参数的基础上,再加上KVM的参数,根据自己的需求修改一下参数即可
|
||||||
|
3. 使用 1806 端口打开KVM管理页面
|
||||||
|
|
||||||
|
```
|
||||||
|
docker run --name linker-kvm -itd \
|
||||||
|
-v /usr/local/linker-docker/configs:/app/configs \
|
||||||
|
-v /usr/local/linker-docker/logs:/app/logs \
|
||||||
|
--device /dev/net/tun \
|
||||||
|
--restart=always \
|
||||||
|
--privileged=true \
|
||||||
|
--network host \
|
||||||
|
--device /dev/video0:/dev/video0 \ #采集卡
|
||||||
|
--device /dev/snd:/dev/snd -e AUDIONUM=0 \ #声卡
|
||||||
|
--device /dev/hidraw1:/dev/hidraw1 -e ATX=USBRELAY_HID \ #HID继电器
|
||||||
|
--device /dev/ttyUSB0:/dev/ttyUSB0 -e CH9329SPEED=9600 \ #CH9329键盘鼠标
|
||||||
|
-v /usr/local/linker-docker/kvmd:/etc/kvmd \ #映射配置目录
|
||||||
|
-e USERNAME=snltty -e PASSWORD=snltty -e NOAUTH=1 \ #账号密码,禁用认证
|
||||||
|
-e NOVNC=1 \ #禁用vnc
|
||||||
|
-e NOIPMI=1 \ #禁用ipmi
|
||||||
|
-e NOWEBTERM=1 -e NOWEBTERMWRITE=1 \ #禁用webterm
|
||||||
|
-e NOSSL=1 \ #禁用ssl
|
||||||
|
snltty/linker-kvm
|
||||||
|
```
|
||||||
|
|
||||||
#### 服务端-bridge
|
#### 服务端-bridge
|
||||||
```
|
```
|
||||||
|
@@ -19,9 +19,8 @@ sidebar_position: 8
|
|||||||
```
|
```
|
||||||
{
|
{
|
||||||
"Name": "A", //客户端名
|
"Name": "A", //客户端名
|
||||||
"Access": 4503599627370495, //权限值,可以看`src/linker.messenger.api/Config.cs`里的`AccessValue`枚举
|
"AccessBits": '11111111111', //按下标,1有权限,0无权限,可以看`src/linker.messenger.api/Config.cs`里的`AccessValue`枚举
|
||||||
"CApi": {
|
"CApi": {
|
||||||
"ApiPort": 1803, //api接口
|
|
||||||
"ApiPassword": "snltty", //api密码
|
"ApiPassword": "snltty", //api密码
|
||||||
"WebPort": 1804, //web端口
|
"WebPort": 1804, //web端口
|
||||||
"WebRoot": "./web/" //web根目录
|
"WebRoot": "./web/" //web根目录
|
||||||
|
@@ -17,7 +17,7 @@ sidebar_position: 6
|
|||||||
### 1.2、动态配置示例
|
### 1.2、动态配置示例
|
||||||
以javascript 为例,设置参数方法:
|
以javascript 为例,设置参数方法:
|
||||||
```
|
```
|
||||||
const ws = new WebSocket(`ws://127.0.0.1:1803`, ['接口密钥']);
|
const ws = new WebSocket(`ws://127.0.0.1:1804`, ['接口密钥']);
|
||||||
ws.onopen = () => {
|
ws.onopen = () => {
|
||||||
const json = {Key:'token',Value:'snltty'}; //你的参数内容,json格式,任意内容,将原样post到ActionUrl
|
const json = {Key:'token',Value:'snltty'}; //你的参数内容,json格式,任意内容,将原样post到ActionUrl
|
||||||
ws.send(JSON.stringify({
|
ws.send(JSON.stringify({
|
||||||
|
@@ -1,202 +0,0 @@
|
|||||||
using linker.libs.extends;
|
|
||||||
using linker.libs.websocket;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace linker.libs.api
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 前段接口服务
|
|
||||||
/// </summary>
|
|
||||||
public class ApiServer : IApiServer
|
|
||||||
{
|
|
||||||
protected readonly Dictionary<string, PluginPathCacheInfo> plugins = new();
|
|
||||||
protected readonly ConcurrentDictionary<uint, ConnectionTimeInfo> connectionTimes = new();
|
|
||||||
public uint OnlineNum = 0;
|
|
||||||
private string password = string.Empty;
|
|
||||||
|
|
||||||
private WebSocketServer server;
|
|
||||||
|
|
||||||
public ApiServer()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 开启websockt
|
|
||||||
/// </summary>
|
|
||||||
public void Websocket(int port, string password = "")
|
|
||||||
{
|
|
||||||
this.password = password;
|
|
||||||
server = new WebSocketServer();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
server.Start(port);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
LoggerHelper.Instance.Error(ex);
|
|
||||||
}
|
|
||||||
server.OnConnecting = (connection, header) =>
|
|
||||||
{
|
|
||||||
bool res = string.IsNullOrWhiteSpace(this.password) || (header.TryGetHeaderValue(WebsocketHeaderKey.SecWebSocketProtocol, out string _password) && string.Equals(_password, this.password));
|
|
||||||
if (res)
|
|
||||||
{
|
|
||||||
header.SetHeaderValue(WebsocketHeaderKey.SecWebSocketExtensions, string.Empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
|
||||||
{
|
|
||||||
header.TryGetHeaderValue(WebsocketHeaderKey.SecWebSocketProtocol, out string _password1);
|
|
||||||
LoggerHelper.Instance.Info($"websocket client password {_password1} eq {password}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
};
|
|
||||||
server.OnOpen = (connection) =>
|
|
||||||
{
|
|
||||||
Interlocked.Increment(ref OnlineNum);
|
|
||||||
connectionTimes.TryAdd(connection.Id, new ConnectionTimeInfo());
|
|
||||||
};
|
|
||||||
server.OnDisConnectd = (connection) =>
|
|
||||||
{
|
|
||||||
Interlocked.Decrement(ref OnlineNum);
|
|
||||||
if (OnlineNum < 0) Interlocked.Exchange(ref OnlineNum, 0);
|
|
||||||
connectionTimes.TryRemove(connection.Id, out _);
|
|
||||||
};
|
|
||||||
server.OnMessage = (connection, frame, message) =>
|
|
||||||
{
|
|
||||||
if (connectionTimes.TryGetValue(connection.Id, out ConnectionTimeInfo timeInfo))
|
|
||||||
{
|
|
||||||
timeInfo.DateTime = DateTime.Now;
|
|
||||||
}
|
|
||||||
var req = message.DeJson<ApiControllerRequestInfo>();
|
|
||||||
req.Connection = connection;
|
|
||||||
OnMessage(req).ContinueWith((result) =>
|
|
||||||
{
|
|
||||||
var resp = result.Result.ToJson().ToBytes();
|
|
||||||
connection.SendFrameText(resp);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
public void SetPassword(string password)
|
|
||||||
{
|
|
||||||
this.password = password;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 收到消息
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="model"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<ApiControllerResponseInfo> OnMessage(ApiControllerRequestInfo model)
|
|
||||||
{
|
|
||||||
model.Path = model.Path.ToLower();
|
|
||||||
if (plugins.TryGetValue(model.Path, out PluginPathCacheInfo plugin) == false)
|
|
||||||
{
|
|
||||||
return new ApiControllerResponseInfo
|
|
||||||
{
|
|
||||||
Content = $"{model.Path} not exists",
|
|
||||||
RequestId = model.RequestId,
|
|
||||||
Path = model.Path,
|
|
||||||
Code = ApiControllerResponseCodes.NotFound
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (plugin.HasAccess(plugin.Access) == false)
|
|
||||||
{
|
|
||||||
return new ApiControllerResponseInfo
|
|
||||||
{
|
|
||||||
Content = "no permission",
|
|
||||||
RequestId = model.RequestId,
|
|
||||||
Path = model.Path,
|
|
||||||
Code = ApiControllerResponseCodes.Error
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ApiControllerParamsInfo param = new ApiControllerParamsInfo
|
|
||||||
{
|
|
||||||
RequestId = model.RequestId,
|
|
||||||
Content = model.Content,
|
|
||||||
Connection = model.Connection
|
|
||||||
};
|
|
||||||
dynamic resultAsync = plugin.Method.Invoke(plugin.Target, new object[] { param });
|
|
||||||
object resultObject = null;
|
|
||||||
if (plugin.IsVoid == false)
|
|
||||||
{
|
|
||||||
if (plugin.IsTask)
|
|
||||||
{
|
|
||||||
await resultAsync.ConfigureAwait(false);
|
|
||||||
if (plugin.IsTaskResult)
|
|
||||||
{
|
|
||||||
resultObject = resultAsync.Result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
resultObject = resultAsync;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new ApiControllerResponseInfo
|
|
||||||
{
|
|
||||||
Code = param.Code,
|
|
||||||
Content = param.Code != ApiControllerResponseCodes.Error ? resultObject : param.ErrorMessage,
|
|
||||||
RequestId = model.RequestId,
|
|
||||||
Path = model.Path,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
LoggerHelper.Instance.Error($"{model.Path} -> {ex.Message}");
|
|
||||||
return new ApiControllerResponseInfo
|
|
||||||
{
|
|
||||||
Content = ex.Message,
|
|
||||||
RequestId = model.RequestId,
|
|
||||||
Path = model.Path,
|
|
||||||
Code = ApiControllerResponseCodes.Error
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class ConnectionTimeInfo
|
|
||||||
{
|
|
||||||
public DateTime DateTime { get; set; } = DateTime.Now;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 前段接口缓存
|
|
||||||
/// </summary>
|
|
||||||
public struct PluginPathCacheInfo
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 对象
|
|
||||||
/// </summary>
|
|
||||||
public object Target { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// 方法
|
|
||||||
/// </summary>
|
|
||||||
public MethodInfo Method { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// 是否void
|
|
||||||
/// </summary>
|
|
||||||
public bool IsVoid { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// 是否task
|
|
||||||
/// </summary>
|
|
||||||
public bool IsTask { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// 是否task result
|
|
||||||
/// </summary>
|
|
||||||
public bool IsTaskResult { get; set; }
|
|
||||||
|
|
||||||
public int Access { get; set; }
|
|
||||||
public Func<int, bool> HasAccess { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,15 +0,0 @@
|
|||||||
namespace linker.libs.api
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 前端接口服务
|
|
||||||
/// </summary>
|
|
||||||
public interface IApiServer
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// websocket
|
|
||||||
/// </summary>
|
|
||||||
public void Websocket(int port,string password);
|
|
||||||
public void SetPassword(string password);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,8 +1,9 @@
|
|||||||
using linker.libs.websocket;
|
using linker.libs.websocket;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Net.WebSockets;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace linker.libs.api
|
namespace linker.libs.web
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 前段接口
|
/// 前段接口
|
||||||
@@ -38,7 +39,7 @@ namespace linker.libs.api
|
|||||||
public sealed class ApiControllerRequestInfo
|
public sealed class ApiControllerRequestInfo
|
||||||
{
|
{
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public WebsocketConnection Connection { get; set; }
|
public WebSocket Connection { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 路径
|
/// 路径
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -58,7 +59,7 @@ namespace linker.libs.api
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class ApiControllerParamsInfo
|
public sealed class ApiControllerParamsInfo
|
||||||
{
|
{
|
||||||
public WebsocketConnection Connection { get; set; }
|
public WebSocket Connection { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 请求id
|
/// 请求id
|
||||||
/// </summary>
|
/// </summary>
|
@@ -1,4 +1,6 @@
|
|||||||
namespace linker.libs.web
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace linker.libs.web
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// web服务
|
/// web服务
|
||||||
@@ -8,7 +10,8 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 开始
|
/// 开始
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Start(int port, string root);
|
public void Start(int port, string root,string password);
|
||||||
|
public void SetPassword(string password);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,12 @@
|
|||||||
using System;
|
using linker.libs.extends;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.WebSockets;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace linker.libs.web
|
namespace linker.libs.web
|
||||||
@@ -12,6 +17,8 @@ namespace linker.libs.web
|
|||||||
public class WebServer : IWebServer
|
public class WebServer : IWebServer
|
||||||
{
|
{
|
||||||
private string root = "";
|
private string root = "";
|
||||||
|
private string password = Helper.GlobalString;
|
||||||
|
protected readonly Dictionary<string, PluginPathCacheInfo> plugins = new();
|
||||||
|
|
||||||
private readonly IWebServerFileReader fileReader;
|
private readonly IWebServerFileReader fileReader;
|
||||||
public WebServer(IWebServerFileReader fileReader)
|
public WebServer(IWebServerFileReader fileReader)
|
||||||
@@ -22,10 +29,11 @@ namespace linker.libs.web
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 开启web
|
/// 开启web
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Start(int port, string root)
|
public void Start(int port, string root, string password)
|
||||||
{
|
{
|
||||||
this.root = root;
|
this.root = root;
|
||||||
Task.Factory.StartNew(() =>
|
this.password = password;
|
||||||
|
Task.Factory.StartNew(async () =>
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -34,7 +42,25 @@ namespace linker.libs.web
|
|||||||
http.Prefixes.Add($"http://+:{port}/");
|
http.Prefixes.Add($"http://+:{port}/");
|
||||||
http.Start();
|
http.Start();
|
||||||
|
|
||||||
http.BeginGetContext(Callback, http);
|
while (true)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
HttpListenerContext context = await http.GetContextAsync();
|
||||||
|
if (context.Request.IsWebSocketRequest)
|
||||||
|
{
|
||||||
|
HttpListenerWebSocketContext wsContext = await context.AcceptWebSocketAsync(null);
|
||||||
|
HandleWs(wsContext.WebSocket);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HandleWeb(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -42,13 +68,11 @@ namespace linker.libs.web
|
|||||||
}
|
}
|
||||||
}, TaskCreationOptions.LongRunning);
|
}, TaskCreationOptions.LongRunning);
|
||||||
}
|
}
|
||||||
private void Callback(IAsyncResult result)
|
|
||||||
|
private void HandleWeb(HttpListenerContext context)
|
||||||
{
|
{
|
||||||
HttpListener http = result.AsyncState as HttpListener;
|
|
||||||
HttpListenerContext context = http.EndGetContext(result);
|
|
||||||
HttpListenerRequest request = context.Request;
|
HttpListenerRequest request = context.Request;
|
||||||
HttpListenerResponse response = context.Response;
|
HttpListenerResponse response = context.Response;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
response.Headers.Set("Server", Helper.GlobalString);
|
response.Headers.Set("Server", Helper.GlobalString);
|
||||||
@@ -99,11 +123,7 @@ namespace linker.libs.web
|
|||||||
}
|
}
|
||||||
|
|
||||||
response.Close();
|
response.Close();
|
||||||
|
|
||||||
http.BeginGetContext(Callback, http);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private Dictionary<string, string> types = new Dictionary<string, string> {
|
private Dictionary<string, string> types = new Dictionary<string, string> {
|
||||||
{ ".webp","image/webp"},
|
{ ".webp","image/webp"},
|
||||||
{ ".png","image/png"},
|
{ ".png","image/png"},
|
||||||
@@ -127,6 +147,133 @@ namespace linker.libs.web
|
|||||||
}
|
}
|
||||||
return "application/octet-stream";
|
return "application/octet-stream";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetPassword(string password)
|
||||||
|
{
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
private async void HandleWs(WebSocket websocket)
|
||||||
|
{
|
||||||
|
byte[] buffer = new byte[8 * 1024];
|
||||||
|
try
|
||||||
|
{
|
||||||
|
WebSocketReceiveResult result = await websocket.ReceiveAsync(buffer, CancellationToken.None);
|
||||||
|
if (result.MessageType != WebSocketMessageType.Text)
|
||||||
|
{
|
||||||
|
await websocket.CloseAsync(WebSocketCloseStatus.ProtocolError, "password fail", CancellationToken.None);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ApiControllerRequestInfo req = Encoding.UTF8.GetString(buffer.AsMemory(0, result.Count).Span).DeJson<ApiControllerRequestInfo>();
|
||||||
|
if (req.Path != "password" || req.Content != this.password)
|
||||||
|
{
|
||||||
|
await websocket.CloseAsync(WebSocketCloseStatus.ProtocolError, "password fail", CancellationToken.None);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await websocket.SendAsync(new ApiControllerResponseInfo
|
||||||
|
{
|
||||||
|
Code = ApiControllerResponseCodes.Success,
|
||||||
|
Path = req.Path,
|
||||||
|
RequestId = req.RequestId,
|
||||||
|
Content = "password ok",
|
||||||
|
}.ToJson().ToBytes(), WebSocketMessageType.Text, true, CancellationToken.None);
|
||||||
|
|
||||||
|
while (websocket.State == WebSocketState.Open)
|
||||||
|
{
|
||||||
|
result = await websocket.ReceiveAsync(buffer, CancellationToken.None);
|
||||||
|
switch (result.MessageType)
|
||||||
|
{
|
||||||
|
case WebSocketMessageType.Text:
|
||||||
|
{
|
||||||
|
req = Encoding.UTF8.GetString(buffer.AsMemory(0, result.Count).Span).DeJson<ApiControllerRequestInfo>();
|
||||||
|
req.Connection = websocket;
|
||||||
|
ApiControllerResponseInfo resp = await OnMessage(req);
|
||||||
|
await websocket.SendAsync(resp.ToJson().ToBytes(), WebSocketMessageType.Text, true, CancellationToken.None);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WebSocketMessageType.Binary:
|
||||||
|
break;
|
||||||
|
case WebSocketMessageType.Close:
|
||||||
|
await websocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closed by client", CancellationToken.None);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LoggerHelper.Instance.Error(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private async Task<ApiControllerResponseInfo> OnMessage(ApiControllerRequestInfo model)
|
||||||
|
{
|
||||||
|
model.Path = model.Path.ToLower();
|
||||||
|
if (plugins.TryGetValue(model.Path, out PluginPathCacheInfo plugin) == false)
|
||||||
|
{
|
||||||
|
return new ApiControllerResponseInfo
|
||||||
|
{
|
||||||
|
Content = $"{model.Path} not exists",
|
||||||
|
RequestId = model.RequestId,
|
||||||
|
Path = model.Path,
|
||||||
|
Code = ApiControllerResponseCodes.NotFound
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (plugin.HasAccess(plugin.Access) == false)
|
||||||
|
{
|
||||||
|
return new ApiControllerResponseInfo
|
||||||
|
{
|
||||||
|
Content = "no permission",
|
||||||
|
RequestId = model.RequestId,
|
||||||
|
Path = model.Path,
|
||||||
|
Code = ApiControllerResponseCodes.Error
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ApiControllerParamsInfo param = new ApiControllerParamsInfo
|
||||||
|
{
|
||||||
|
RequestId = model.RequestId,
|
||||||
|
Content = model.Content,
|
||||||
|
Connection = model.Connection
|
||||||
|
};
|
||||||
|
dynamic resultAsync = plugin.Method.Invoke(plugin.Target, new object[] { param });
|
||||||
|
object resultObject = null;
|
||||||
|
if (plugin.IsVoid == false)
|
||||||
|
{
|
||||||
|
if (plugin.IsTask)
|
||||||
|
{
|
||||||
|
await resultAsync.ConfigureAwait(false);
|
||||||
|
if (plugin.IsTaskResult)
|
||||||
|
{
|
||||||
|
resultObject = resultAsync.Result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resultObject = resultAsync;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new ApiControllerResponseInfo
|
||||||
|
{
|
||||||
|
Code = param.Code,
|
||||||
|
Content = param.Code != ApiControllerResponseCodes.Error ? resultObject : param.ErrorMessage,
|
||||||
|
RequestId = model.RequestId,
|
||||||
|
Path = model.Path,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LoggerHelper.Instance.Error($"{model.Path} -> {ex.Message}");
|
||||||
|
return new ApiControllerResponseInfo
|
||||||
|
{
|
||||||
|
Content = ex.Message,
|
||||||
|
RequestId = model.RequestId,
|
||||||
|
Path = model.Path,
|
||||||
|
Code = ApiControllerResponseCodes.Error
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -143,4 +290,31 @@ namespace linker.libs.web
|
|||||||
return File.ReadAllBytes(fileName);
|
return File.ReadAllBytes(fileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct PluginPathCacheInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 对象
|
||||||
|
/// </summary>
|
||||||
|
public object Target { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 方法
|
||||||
|
/// </summary>
|
||||||
|
public MethodInfo Method { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 是否void
|
||||||
|
/// </summary>
|
||||||
|
public bool IsVoid { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 是否task
|
||||||
|
/// </summary>
|
||||||
|
public bool IsTask { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 是否task result
|
||||||
|
/// </summary>
|
||||||
|
public bool IsTaskResult { get; set; }
|
||||||
|
|
||||||
|
public int Access { get; set; }
|
||||||
|
public Func<int, bool> HasAccess { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,11 +1,10 @@
|
|||||||
using linker.libs.api;
|
using linker.libs.extends;
|
||||||
using linker.libs.extends;
|
|
||||||
using linker.libs;
|
using linker.libs;
|
||||||
using linker.messenger.signin;
|
using linker.messenger.signin;
|
||||||
using linker.messenger.api;
|
using linker.messenger.api;
|
||||||
using IApiServer = linker.messenger.api.IApiServer;
|
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using linker.libs.web;
|
||||||
|
|
||||||
namespace linker.messenger.access
|
namespace linker.messenger.access
|
||||||
{
|
{
|
||||||
@@ -18,9 +17,10 @@ namespace linker.messenger.access
|
|||||||
private readonly ISerializer serializer;
|
private readonly ISerializer serializer;
|
||||||
private readonly IAccessStore accessStore;
|
private readonly IAccessStore accessStore;
|
||||||
private readonly IApiStore apiStore;
|
private readonly IApiStore apiStore;
|
||||||
private readonly IApiServer apiServer;
|
private readonly linker.messenger.api.IWebServer apiServer;
|
||||||
|
|
||||||
public AccessApiController(IMessengerSender sender, SignInClientState signInClientState, AccessDecenter accessDecenter, ISignInClientStore signInClientStore, ISerializer serializer, IAccessStore accessStore, IApiStore apiStore, IApiServer apiServer)
|
public AccessApiController(IMessengerSender sender, SignInClientState signInClientState, AccessDecenter accessDecenter,
|
||||||
|
ISignInClientStore signInClientStore, ISerializer serializer, IAccessStore accessStore, IApiStore apiStore, linker.messenger.api.IWebServer apiServer)
|
||||||
{
|
{
|
||||||
this.sender = sender;
|
this.sender = sender;
|
||||||
this.signInClientState = signInClientState;
|
this.signInClientState = signInClientState;
|
||||||
|
@@ -1,8 +1,6 @@
|
|||||||
using linker.libs;
|
using linker.libs;
|
||||||
using linker.libs.api;
|
|
||||||
using linker.messenger.api;
|
using linker.messenger.api;
|
||||||
using linker.messenger.signin;
|
using linker.messenger.signin;
|
||||||
using IApiServer = linker.messenger.api.IApiServer;
|
|
||||||
|
|
||||||
namespace linker.messenger.access
|
namespace linker.messenger.access
|
||||||
{
|
{
|
||||||
@@ -96,8 +94,8 @@ namespace linker.messenger.access
|
|||||||
private readonly IAccessStore accessStore;
|
private readonly IAccessStore accessStore;
|
||||||
private readonly ISerializer serializer;
|
private readonly ISerializer serializer;
|
||||||
private readonly IApiStore apiStore;
|
private readonly IApiStore apiStore;
|
||||||
private readonly IApiServer apiServer;
|
private readonly linker.messenger.api.IWebServer apiServer;
|
||||||
public AccessClientMessenger(IAccessStore accessStore, ISerializer serializer, IApiStore apiStore, IApiServer apiServer)
|
public AccessClientMessenger(IAccessStore accessStore, ISerializer serializer, IApiStore apiStore, linker.messenger.api.IWebServer apiServer)
|
||||||
{
|
{
|
||||||
this.accessStore = accessStore;
|
this.accessStore = accessStore;
|
||||||
this.serializer = serializer;
|
this.serializer = serializer;
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using linker.messenger.access;
|
using linker.libs.web;
|
||||||
|
using linker.messenger.access;
|
||||||
using linker.messenger.decenter;
|
using linker.messenger.decenter;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
namespace linker.messenger.api
|
namespace linker.messenger.api
|
||||||
@@ -14,8 +15,8 @@ namespace linker.messenger.api
|
|||||||
}
|
}
|
||||||
public static ServiceProvider UseAccessClient(this ServiceProvider serviceProvider)
|
public static ServiceProvider UseAccessClient(this ServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
IApiServer apiServer = serviceProvider.GetService<IApiServer>();
|
linker.messenger.api.IWebServer apiServer = serviceProvider.GetService<linker.messenger.api.IWebServer>();
|
||||||
apiServer.AddPlugins(new List<libs.api.IApiController> { serviceProvider.GetService<AccessApiController>() });
|
apiServer.AddPlugins(new List<IApiController> { serviceProvider.GetService<AccessApiController>() });
|
||||||
|
|
||||||
DecenterClientTransfer decenterClientTransfer = serviceProvider.GetService<DecenterClientTransfer>();
|
DecenterClientTransfer decenterClientTransfer = serviceProvider.GetService<DecenterClientTransfer>();
|
||||||
decenterClientTransfer.AddDecenters(new List<IDecenter> { serviceProvider.GetService<AccessDecenter>() });
|
decenterClientTransfer.AddDecenters(new List<IDecenter> { serviceProvider.GetService<AccessDecenter>() });
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
using linker.libs.api;
|
using linker.libs.extends;
|
||||||
using linker.libs.extends;
|
using linker.libs.web;
|
||||||
using linker.messenger.api;
|
using linker.messenger.api;
|
||||||
|
|
||||||
namespace linker.messenger.action
|
namespace linker.messenger.action
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using linker.messenger.action;
|
using linker.libs.web;
|
||||||
|
using linker.messenger.action;
|
||||||
using linker.messenger.relay.server.validator;
|
using linker.messenger.relay.server.validator;
|
||||||
using linker.messenger.sforward.server.validator;
|
using linker.messenger.sforward.server.validator;
|
||||||
using linker.messenger.signin.args;
|
using linker.messenger.signin.args;
|
||||||
@@ -17,8 +18,8 @@ namespace linker.messenger.api
|
|||||||
}
|
}
|
||||||
public static ServiceProvider UseActionClient(this ServiceProvider serviceProvider)
|
public static ServiceProvider UseActionClient(this ServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
IApiServer apiServer = serviceProvider.GetService<IApiServer>();
|
linker.messenger.api.IWebServer apiServer = serviceProvider.GetService<linker.messenger.api.IWebServer>();
|
||||||
apiServer.AddPlugins(new List<libs.api.IApiController> { serviceProvider.GetService<ActionApiController>() });
|
apiServer.AddPlugins(new List<IApiController> { serviceProvider.GetService<ActionApiController>() });
|
||||||
|
|
||||||
SignInArgsTransfer signInArgsTransfer = serviceProvider.GetService<SignInArgsTransfer>();
|
SignInArgsTransfer signInArgsTransfer = serviceProvider.GetService<SignInArgsTransfer>();
|
||||||
signInArgsTransfer.AddArgs(new List<ISignInArgs> { serviceProvider.GetService<SignInArgsAction>() });
|
signInArgsTransfer.AddArgs(new List<ISignInArgs> { serviceProvider.GetService<SignInArgsAction>() });
|
||||||
|
@@ -1,62 +0,0 @@
|
|||||||
using linker.libs;
|
|
||||||
using linker.libs.api;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace linker.messenger.api
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 前段接口服务
|
|
||||||
/// </summary>
|
|
||||||
public sealed partial class ApiServer : libs.api.ApiServer, IApiServer
|
|
||||||
{
|
|
||||||
private readonly IAccessStore accessStore;
|
|
||||||
public ApiServer(IAccessStore accessStore)
|
|
||||||
{
|
|
||||||
this.accessStore = accessStore;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 加载插件
|
|
||||||
/// </summary>
|
|
||||||
public void AddPlugins(List<IApiController> list)
|
|
||||||
{
|
|
||||||
Type voidType = typeof(void);
|
|
||||||
|
|
||||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
|
||||||
LoggerHelper.Instance.Info($"add api {string.Join(",", list.Select(c => c.GetType().Name))}");
|
|
||||||
|
|
||||||
foreach (IApiController obj in list)
|
|
||||||
{
|
|
||||||
Type type = obj.GetType();
|
|
||||||
string path = type.Name.Replace("ApiController", "").Replace("ApiController", "");
|
|
||||||
foreach (MethodInfo method in type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
|
|
||||||
{
|
|
||||||
string key = $"{path}/{method.Name}".ToLower();
|
|
||||||
if (plugins.ContainsKey(key) == false)
|
|
||||||
{
|
|
||||||
bool istask = method.ReturnType.GetProperty("IsCompleted") != null && method.ReturnType.GetMethod("GetAwaiter") != null;
|
|
||||||
bool isTaskResult = method.ReturnType.GetProperty("Result") != null;
|
|
||||||
|
|
||||||
AccessAttribute accessAttr = method.GetCustomAttribute<AccessAttribute>();
|
|
||||||
int access = (int)(accessAttr?.Value ?? 0);
|
|
||||||
|
|
||||||
plugins.TryAdd(key, new PluginPathCacheInfo
|
|
||||||
{
|
|
||||||
IsVoid = method.ReturnType == voidType,
|
|
||||||
Method = method,
|
|
||||||
Target = obj,
|
|
||||||
IsTask = istask,
|
|
||||||
IsTaskResult = isTaskResult,
|
|
||||||
Access = access,
|
|
||||||
HasAccess = HasAccess,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private bool HasAccess(int access)
|
|
||||||
{
|
|
||||||
return accessStore.HasAccess((AccessValue)access);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -7,7 +7,6 @@ namespace linker.messenger.api
|
|||||||
{
|
{
|
||||||
public static ServiceCollection AddApiClient(this ServiceCollection serviceCollection)
|
public static ServiceCollection AddApiClient(this ServiceCollection serviceCollection)
|
||||||
{
|
{
|
||||||
serviceCollection.AddSingleton<IApiServer, ApiServer>();
|
|
||||||
serviceCollection.AddSingleton<IWebServer, WebServer>();
|
serviceCollection.AddSingleton<IWebServer, WebServer>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IWebServerFileReader, WebServerFileReader>();
|
serviceCollection.AddSingleton<IWebServerFileReader, WebServerFileReader>();
|
||||||
@@ -18,21 +17,12 @@ namespace linker.messenger.api
|
|||||||
{
|
{
|
||||||
IApiStore apiStore = serviceProvider.GetService<IApiStore>();
|
IApiStore apiStore = serviceProvider.GetService<IApiStore>();
|
||||||
IAccessStore accessStore = serviceProvider.GetService<IAccessStore>();
|
IAccessStore accessStore = serviceProvider.GetService<IAccessStore>();
|
||||||
if (apiStore.Info.ApiPort > 0 && accessStore.HasAccess(AccessValue.Api))
|
|
||||||
{
|
|
||||||
LoggerHelper.Instance.Info($"start client api");
|
|
||||||
IApiServer server = serviceProvider.GetService<IApiServer>();
|
|
||||||
server.Websocket(apiStore.Info.ApiPort, apiStore.Info.ApiPassword);
|
|
||||||
LoggerHelper.Instance.Warning($"client api listen:{apiStore.Info.ApiPort}");
|
|
||||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
|
||||||
LoggerHelper.Instance.Warning($"client api password:{apiStore.Info.ApiPassword}");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (apiStore.Info.WebPort > 0 && accessStore.HasAccess(AccessValue.Web))
|
if (apiStore.Info.WebPort > 0 && accessStore.HasAccess(AccessValue.Web))
|
||||||
{
|
{
|
||||||
LoggerHelper.Instance.Info($"start client web");
|
LoggerHelper.Instance.Info($"start client web");
|
||||||
IWebServer webServer = serviceProvider.GetService<IWebServer>();
|
IWebServer webServer = serviceProvider.GetService<IWebServer>();
|
||||||
webServer.Start(apiStore.Info.WebPort, apiStore.Info.WebRoot);
|
webServer.Start(apiStore.Info.WebPort, apiStore.Info.WebRoot, apiStore.Info.ApiPassword);
|
||||||
LoggerHelper.Instance.Warning($"client web listen:{apiStore.Info.WebPort}");
|
LoggerHelper.Instance.Warning($"client web listen:{apiStore.Info.WebPort}");
|
||||||
}
|
}
|
||||||
return serviceProvider;
|
return serviceProvider;
|
||||||
|
@@ -1,10 +0,0 @@
|
|||||||
using linker.libs.api;
|
|
||||||
|
|
||||||
namespace linker.messenger.api
|
|
||||||
{
|
|
||||||
public interface IApiServer : libs.api.IApiServer
|
|
||||||
{
|
|
||||||
public void AddPlugins(List<IApiController> list);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -3,15 +3,10 @@ namespace linker.messenger.api
|
|||||||
{
|
{
|
||||||
public sealed class ApiClientInfo
|
public sealed class ApiClientInfo
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// 管理接口端口
|
|
||||||
/// </summary>
|
|
||||||
public int ApiPort { get; set; } = 1803;
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 管理接口密码
|
/// 管理接口密码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string ApiPassword { get; set; } = Helper.GlobalString;
|
public string ApiPassword { get; set; } = Helper.GlobalString;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 网站端口
|
/// 网站端口
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -33,12 +28,6 @@ namespace linker.messenger.api
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public bool Set(ApiClientInfo info);
|
public bool Set(ApiClientInfo info);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设置接口端口
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="port"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public bool SetApiPort(int port);
|
|
||||||
/// <summary>
|
|
||||||
/// 设置接口密码
|
/// 设置接口密码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="password"></param>
|
/// <param name="password"></param>
|
||||||
|
@@ -1,15 +1,69 @@
|
|||||||
using linker.libs.web;
|
using linker.libs;
|
||||||
|
using linker.libs.web;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
namespace linker.messenger.api
|
namespace linker.messenger.api
|
||||||
{
|
{
|
||||||
|
public interface IWebServer : libs.web.IWebServer
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 加载插件
|
||||||
|
/// </summary>
|
||||||
|
void AddPlugins(List<IApiController> list);
|
||||||
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 本地web管理端服务器
|
/// 本地web管理端服务器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class WebServer : libs.web.WebServer, IWebServer
|
public sealed class WebServer : libs.web.WebServer, IWebServer
|
||||||
{
|
{
|
||||||
public WebServer(IWebServerFileReader webServerFileReader) : base(webServerFileReader)
|
private readonly IAccessStore accessStore;
|
||||||
|
public WebServer(IWebServerFileReader webServerFileReader, IAccessStore accessStore) : base(webServerFileReader)
|
||||||
{
|
{
|
||||||
|
this.accessStore = accessStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 加载插件
|
||||||
|
/// </summary>
|
||||||
|
public void AddPlugins(List<IApiController> list)
|
||||||
|
{
|
||||||
|
Type voidType = typeof(void);
|
||||||
|
|
||||||
|
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||||
|
LoggerHelper.Instance.Info($"add api {string.Join(",", list.Select(c => c.GetType().Name))}");
|
||||||
|
|
||||||
|
foreach (IApiController obj in list)
|
||||||
|
{
|
||||||
|
Type type = obj.GetType();
|
||||||
|
string path = type.Name.Replace("ApiController", "").Replace("ApiController", "");
|
||||||
|
foreach (MethodInfo method in type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
|
||||||
|
{
|
||||||
|
string key = $"{path}/{method.Name}".ToLower();
|
||||||
|
if (plugins.ContainsKey(key) == false)
|
||||||
|
{
|
||||||
|
bool istask = method.ReturnType.GetProperty("IsCompleted") != null && method.ReturnType.GetMethod("GetAwaiter") != null;
|
||||||
|
bool isTaskResult = method.ReturnType.GetProperty("Result") != null;
|
||||||
|
|
||||||
|
AccessAttribute accessAttr = method.GetCustomAttribute<AccessAttribute>();
|
||||||
|
int access = (int)(accessAttr?.Value ?? 0);
|
||||||
|
|
||||||
|
plugins.TryAdd(key, new PluginPathCacheInfo
|
||||||
|
{
|
||||||
|
IsVoid = method.ReturnType == voidType,
|
||||||
|
Method = method,
|
||||||
|
Target = obj,
|
||||||
|
IsTask = istask,
|
||||||
|
IsTaskResult = isTaskResult,
|
||||||
|
Access = access,
|
||||||
|
HasAccess = HasAccess,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private bool HasAccess(int access)
|
||||||
|
{
|
||||||
|
return accessStore.HasAccess(AccessValue.Api) && accessStore.HasAccess((AccessValue)access);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
using linker.messenger.api;
|
using linker.libs.web;
|
||||||
using linker.snat;
|
using linker.snat;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
@@ -23,8 +23,8 @@ namespace linker.messenger.firewall
|
|||||||
IMessengerResolver messengerResolver = serviceProvider.GetService<IMessengerResolver>();
|
IMessengerResolver messengerResolver = serviceProvider.GetService<IMessengerResolver>();
|
||||||
messengerResolver.AddMessenger(new List<IMessenger> { serviceProvider.GetService<FirewallClientMessenger>() });
|
messengerResolver.AddMessenger(new List<IMessenger> { serviceProvider.GetService<FirewallClientMessenger>() });
|
||||||
|
|
||||||
IApiServer apiServer = serviceProvider.GetService<IApiServer>();
|
linker.messenger.api.IWebServer apiServer = serviceProvider.GetService<linker.messenger.api.IWebServer>();
|
||||||
apiServer.AddPlugins(new List<libs.api.IApiController> { serviceProvider.GetService<FirewallApiController>() });
|
apiServer.AddPlugins(new List<IApiController> { serviceProvider.GetService<FirewallApiController>() });
|
||||||
|
|
||||||
return serviceProvider;
|
return serviceProvider;
|
||||||
}
|
}
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
using linker.libs.api;
|
using linker.libs.extends;
|
||||||
using linker.libs.extends;
|
|
||||||
using linker.libs;
|
using linker.libs;
|
||||||
using linker.messenger.signin;
|
using linker.messenger.signin;
|
||||||
using linker.messenger.api;
|
using linker.messenger.api;
|
||||||
|
using linker.libs.web;
|
||||||
|
|
||||||
namespace linker.messenger.firewall
|
namespace linker.messenger.firewall
|
||||||
{
|
{
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using linker.messenger.api;
|
using linker.libs.web;
|
||||||
|
using linker.messenger.api;
|
||||||
using linker.messenger.flow.messenger;
|
using linker.messenger.flow.messenger;
|
||||||
using linker.messenger.relay.server;
|
using linker.messenger.relay.server;
|
||||||
using linker.messenger.tunnel;
|
using linker.messenger.tunnel;
|
||||||
@@ -22,8 +23,8 @@ namespace linker.messenger.flow
|
|||||||
}
|
}
|
||||||
public static ServiceProvider UseFlowClient(this ServiceProvider serviceProvider)
|
public static ServiceProvider UseFlowClient(this ServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
IApiServer apiServer = serviceProvider.GetService<IApiServer>();
|
linker.messenger.api.IWebServer apiServer = serviceProvider.GetService<linker.messenger.api.IWebServer>();
|
||||||
apiServer.AddPlugins(new List<libs.api.IApiController> { serviceProvider.GetService<FlowApiController>() });
|
apiServer.AddPlugins(new List<IApiController> { serviceProvider.GetService<FlowApiController>() });
|
||||||
|
|
||||||
FlowTransfer flowTransfer = serviceProvider.GetService<FlowTransfer>();
|
FlowTransfer flowTransfer = serviceProvider.GetService<FlowTransfer>();
|
||||||
flowTransfer.AddFlows(new List<IFlow> { serviceProvider.GetService<MessengerFlow>() });
|
flowTransfer.AddFlows(new List<IFlow> { serviceProvider.GetService<MessengerFlow>() });
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
using linker.libs;
|
using linker.libs;
|
||||||
using linker.libs.api;
|
|
||||||
using linker.libs.extends;
|
using linker.libs.extends;
|
||||||
|
using linker.libs.web;
|
||||||
using linker.messenger.api;
|
using linker.messenger.api;
|
||||||
using linker.messenger.flow.messenger;
|
using linker.messenger.flow.messenger;
|
||||||
using linker.messenger.relay.client;
|
using linker.messenger.relay.client;
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using linker.messenger.api;
|
using linker.libs.web;
|
||||||
|
using linker.messenger.api;
|
||||||
using linker.messenger.decenter;
|
using linker.messenger.decenter;
|
||||||
using linker.messenger.forward.proxy;
|
using linker.messenger.forward.proxy;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
@@ -23,8 +24,8 @@ namespace linker.messenger.forward
|
|||||||
}
|
}
|
||||||
public static ServiceProvider UseForwardClient(this ServiceProvider serviceProvider)
|
public static ServiceProvider UseForwardClient(this ServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
IApiServer apiServer = serviceProvider.GetService<IApiServer>();
|
linker.messenger.api.IWebServer apiServer = serviceProvider.GetService<linker.messenger.api.IWebServer>();
|
||||||
apiServer.AddPlugins(new List<libs.api.IApiController> { serviceProvider.GetService<ForwardApiController>() });
|
apiServer.AddPlugins(new List<IApiController> { serviceProvider.GetService<ForwardApiController>() });
|
||||||
|
|
||||||
ForwardTransfer forwardTransfer = serviceProvider.GetService<ForwardTransfer>();
|
ForwardTransfer forwardTransfer = serviceProvider.GetService<ForwardTransfer>();
|
||||||
|
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
using linker.libs.api;
|
using linker.libs.extends;
|
||||||
using linker.libs.extends;
|
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using linker.libs;
|
using linker.libs;
|
||||||
using linker.tunnel.connection;
|
using linker.tunnel.connection;
|
||||||
@@ -7,6 +6,7 @@ using System.Collections.Concurrent;
|
|||||||
using linker.messenger.signin;
|
using linker.messenger.signin;
|
||||||
using linker.messenger.forward.proxy;
|
using linker.messenger.forward.proxy;
|
||||||
using linker.messenger.api;
|
using linker.messenger.api;
|
||||||
|
using linker.libs.web;
|
||||||
|
|
||||||
namespace linker.messenger.forward
|
namespace linker.messenger.forward
|
||||||
{
|
{
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
using linker.libs;
|
using linker.libs;
|
||||||
using linker.libs.timer;
|
using linker.libs.timer;
|
||||||
|
using linker.libs.web;
|
||||||
using linker.messenger.api;
|
using linker.messenger.api;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
namespace linker.messenger.logger
|
namespace linker.messenger.logger
|
||||||
@@ -25,8 +26,8 @@ namespace linker.messenger.logger
|
|||||||
}
|
}
|
||||||
public static ServiceProvider UseLoggerClient(this ServiceProvider serviceProvider)
|
public static ServiceProvider UseLoggerClient(this ServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
IApiServer apiServer = serviceProvider.GetService<IApiServer>();
|
linker.messenger.api.IWebServer apiServer = serviceProvider.GetService<linker.messenger.api.IWebServer>();
|
||||||
apiServer.AddPlugins(new List<libs.api.IApiController> { serviceProvider.GetService<LoggerApiController>() });
|
apiServer.AddPlugins(new List<IApiController> { serviceProvider.GetService<LoggerApiController>() });
|
||||||
|
|
||||||
IAccessStore accessStore= serviceProvider.GetService<IAccessStore>();
|
IAccessStore accessStore= serviceProvider.GetService<IAccessStore>();
|
||||||
ILoggerStore loggerStore= serviceProvider.GetService<ILoggerStore>();
|
ILoggerStore loggerStore= serviceProvider.GetService<ILoggerStore>();
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
using linker.libs.extends;
|
using linker.libs.extends;
|
||||||
using linker.libs.api;
|
|
||||||
using linker.libs;
|
using linker.libs;
|
||||||
using linker.messenger.api;
|
using linker.messenger.api;
|
||||||
|
using linker.libs.web;
|
||||||
|
|
||||||
namespace linker.messenger.logger
|
namespace linker.messenger.logger
|
||||||
{
|
{
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
|
|
||||||
|
using linker.libs.web;
|
||||||
using linker.messenger.api;
|
using linker.messenger.api;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
@@ -21,8 +22,8 @@ namespace linker.messenger.plan
|
|||||||
IMessengerResolver messengerResolver = serviceProvider.GetService<IMessengerResolver>();
|
IMessengerResolver messengerResolver = serviceProvider.GetService<IMessengerResolver>();
|
||||||
messengerResolver.AddMessenger(new List<IMessenger> { serviceProvider.GetService<PlanClientMessenger>() });
|
messengerResolver.AddMessenger(new List<IMessenger> { serviceProvider.GetService<PlanClientMessenger>() });
|
||||||
|
|
||||||
IApiServer apiServer = serviceProvider.GetService<IApiServer>();
|
linker.messenger.api.IWebServer apiServer = serviceProvider.GetService<linker.messenger.api.IWebServer>();
|
||||||
apiServer.AddPlugins(new List<libs.api.IApiController> { serviceProvider.GetService<PlanApiController>() });
|
apiServer.AddPlugins(new List<IApiController> { serviceProvider.GetService<PlanApiController>() });
|
||||||
|
|
||||||
return serviceProvider;
|
return serviceProvider;
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
using linker.libs;
|
using linker.libs;
|
||||||
using linker.libs.api;
|
|
||||||
using linker.libs.extends;
|
using linker.libs.extends;
|
||||||
|
using linker.libs.web;
|
||||||
using linker.messenger.signin;
|
using linker.messenger.signin;
|
||||||
|
|
||||||
namespace linker.messenger.plan
|
namespace linker.messenger.plan
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
using linker.messenger.api;
|
using linker.libs.web;
|
||||||
using linker.messenger.relay.client;
|
using linker.messenger.relay.client;
|
||||||
using linker.messenger.relay.messenger;
|
using linker.messenger.relay.messenger;
|
||||||
using linker.messenger.relay.server;
|
using linker.messenger.relay.server;
|
||||||
@@ -31,8 +31,8 @@ namespace linker.messenger.relay
|
|||||||
SyncTreansfer syncTreansfer = serviceProvider.GetService<SyncTreansfer>();
|
SyncTreansfer syncTreansfer = serviceProvider.GetService<SyncTreansfer>();
|
||||||
syncTreansfer.AddSyncs(new List<ISync> { serviceProvider.GetService<RelaySyncSecretKey>() });
|
syncTreansfer.AddSyncs(new List<ISync> { serviceProvider.GetService<RelaySyncSecretKey>() });
|
||||||
|
|
||||||
IApiServer apiServer = serviceProvider.GetService<IApiServer>();
|
linker.messenger.api.IWebServer apiServer = serviceProvider.GetService<linker.messenger.api.IWebServer>();
|
||||||
apiServer.AddPlugins(new List<libs.api.IApiController> { serviceProvider.GetService<RelayApiController>() });
|
apiServer.AddPlugins(new List<IApiController> { serviceProvider.GetService<RelayApiController>() });
|
||||||
|
|
||||||
RelayClientTestTransfer relayClientTestTransfer = serviceProvider.GetService<RelayClientTestTransfer>();
|
RelayClientTestTransfer relayClientTestTransfer = serviceProvider.GetService<RelayClientTestTransfer>();
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
using linker.libs;
|
using linker.libs;
|
||||||
using linker.libs.api;
|
|
||||||
using linker.libs.extends;
|
using linker.libs.extends;
|
||||||
|
using linker.libs.web;
|
||||||
using linker.messenger.api;
|
using linker.messenger.api;
|
||||||
using linker.messenger.relay.client;
|
using linker.messenger.relay.client;
|
||||||
using linker.messenger.relay.client.transport;
|
using linker.messenger.relay.client.transport;
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using linker.messenger.api;
|
using linker.libs.web;
|
||||||
|
using linker.messenger.api;
|
||||||
using linker.messenger.decenter;
|
using linker.messenger.decenter;
|
||||||
using linker.messenger.plan;
|
using linker.messenger.plan;
|
||||||
using linker.messenger.sforward.client;
|
using linker.messenger.sforward.client;
|
||||||
@@ -33,8 +34,8 @@ namespace linker.messenger.sforward
|
|||||||
}
|
}
|
||||||
public static ServiceProvider UseSForwardClient(this ServiceProvider serviceProvider)
|
public static ServiceProvider UseSForwardClient(this ServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
IApiServer apiServer = serviceProvider.GetService<IApiServer>();
|
linker.messenger.api.IWebServer apiServer = serviceProvider.GetService<linker.messenger.api.IWebServer>();
|
||||||
apiServer.AddPlugins(new List<libs.api.IApiController> { serviceProvider.GetService<SForwardApiController>() });
|
apiServer.AddPlugins(new List<IApiController> { serviceProvider.GetService<SForwardApiController>() });
|
||||||
|
|
||||||
SForwardClientTransfer sForwardClientTransfer = serviceProvider.GetService<SForwardClientTransfer>();
|
SForwardClientTransfer sForwardClientTransfer = serviceProvider.GetService<SForwardClientTransfer>();
|
||||||
|
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
using linker.libs.api;
|
using linker.libs.extends;
|
||||||
using linker.libs.extends;
|
|
||||||
using linker.plugins.sforward.messenger;
|
using linker.plugins.sforward.messenger;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using linker.messenger.signin;
|
using linker.messenger.signin;
|
||||||
using linker.libs;
|
using linker.libs;
|
||||||
using linker.messenger.api;
|
using linker.messenger.api;
|
||||||
|
using linker.libs.web;
|
||||||
|
|
||||||
namespace linker.messenger.sforward.client
|
namespace linker.messenger.sforward.client
|
||||||
{
|
{
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
using linker.libs;
|
using linker.libs;
|
||||||
using linker.libs.api;
|
using linker.libs.web;
|
||||||
using linker.messenger.exroute;
|
using linker.messenger.exroute;
|
||||||
using linker.messenger.signin.args;
|
using linker.messenger.signin.args;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
@@ -36,7 +36,7 @@ namespace linker.messenger.signin
|
|||||||
serviceProvider.GetService<SignInArgsVersionClient>(),
|
serviceProvider.GetService<SignInArgsVersionClient>(),
|
||||||
});
|
});
|
||||||
|
|
||||||
linker.messenger.api.IApiServer apiServer = serviceProvider.GetService<linker.messenger.api.IApiServer>();
|
linker.messenger.api.IWebServer apiServer = serviceProvider.GetService<linker.messenger.api.IWebServer>();
|
||||||
apiServer.AddPlugins(new List<IApiController> {
|
apiServer.AddPlugins(new List<IApiController> {
|
||||||
serviceProvider.GetService<SignInApiController>()
|
serviceProvider.GetService<SignInApiController>()
|
||||||
});
|
});
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
using linker.libs;
|
using linker.libs;
|
||||||
using linker.libs.api;
|
|
||||||
using linker.libs.extends;
|
using linker.libs.extends;
|
||||||
|
using linker.libs.web;
|
||||||
using linker.messenger.api;
|
using linker.messenger.api;
|
||||||
|
|
||||||
namespace linker.messenger.signin
|
namespace linker.messenger.signin
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using linker.messenger.api;
|
using linker.libs.web;
|
||||||
|
using linker.messenger.api;
|
||||||
using linker.messenger.decenter;
|
using linker.messenger.decenter;
|
||||||
using linker.messenger.exroute;
|
using linker.messenger.exroute;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
@@ -28,8 +29,8 @@ namespace linker.messenger.socks5
|
|||||||
IMessengerResolver messengerResolver = serviceProvider.GetService<IMessengerResolver>();
|
IMessengerResolver messengerResolver = serviceProvider.GetService<IMessengerResolver>();
|
||||||
messengerResolver.AddMessenger(new List<IMessenger> { serviceProvider.GetService<Socks5ClientMessenger>() });
|
messengerResolver.AddMessenger(new List<IMessenger> { serviceProvider.GetService<Socks5ClientMessenger>() });
|
||||||
|
|
||||||
IApiServer apiServer = serviceProvider.GetService<IApiServer>();
|
linker.messenger.api.IWebServer apiServer = serviceProvider.GetService<linker.messenger.api.IWebServer>();
|
||||||
apiServer.AddPlugins(new List<libs.api.IApiController> { serviceProvider.GetService<Socks5ApiController>() });
|
apiServer.AddPlugins(new List<IApiController> { serviceProvider.GetService<Socks5ApiController>() });
|
||||||
|
|
||||||
DecenterClientTransfer decenterClientTransfer = serviceProvider.GetService<DecenterClientTransfer>();
|
DecenterClientTransfer decenterClientTransfer = serviceProvider.GetService<DecenterClientTransfer>();
|
||||||
decenterClientTransfer.AddDecenters(new List<IDecenter> { serviceProvider.GetService<Socks5Decenter>() });
|
decenterClientTransfer.AddDecenters(new List<IDecenter> { serviceProvider.GetService<Socks5Decenter>() });
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
using linker.libs.api;
|
using linker.libs.extends;
|
||||||
using linker.libs.extends;
|
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using linker.tunnel.connection;
|
using linker.tunnel.connection;
|
||||||
using linker.messenger.signin;
|
using linker.messenger.signin;
|
||||||
using linker.libs;
|
using linker.libs;
|
||||||
using linker.messenger.api;
|
using linker.messenger.api;
|
||||||
|
using linker.libs.web;
|
||||||
|
|
||||||
namespace linker.messenger.socks5
|
namespace linker.messenger.socks5
|
||||||
{
|
{
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
using linker.libs.api;
|
using linker.libs.extends;
|
||||||
using linker.libs.extends;
|
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
using linker.libs;
|
using linker.libs;
|
||||||
using linker.messenger.signin;
|
using linker.messenger.signin;
|
||||||
@@ -8,6 +7,7 @@ using System.Text;
|
|||||||
using linker.messenger.relay.client.transport;
|
using linker.messenger.relay.client.transport;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using linker.libs.web;
|
||||||
namespace linker.messenger.store.file
|
namespace linker.messenger.store.file
|
||||||
{
|
{
|
||||||
public sealed class ConfigApiController : IApiController
|
public sealed class ConfigApiController : IApiController
|
||||||
@@ -48,7 +48,6 @@ namespace linker.messenger.store.file
|
|||||||
config.Data.Client.Name = info.Client.Name;
|
config.Data.Client.Name = info.Client.Name;
|
||||||
config.Data.Client.Groups = new SignInClientGroupInfo[] { new SignInClientGroupInfo { Id = info.Client.GroupId, Name = info.Client.GroupId, Password = info.Client.GroupPassword } };
|
config.Data.Client.Groups = new SignInClientGroupInfo[] { new SignInClientGroupInfo { Id = info.Client.GroupId, Name = info.Client.GroupId, Password = info.Client.GroupPassword } };
|
||||||
config.Data.Client.CApi.WebPort = info.Client.Web;
|
config.Data.Client.CApi.WebPort = info.Client.Web;
|
||||||
config.Data.Client.CApi.ApiPort = info.Client.Api;
|
|
||||||
config.Data.Client.CApi.ApiPassword = info.Client.Password;
|
config.Data.Client.CApi.ApiPassword = info.Client.Password;
|
||||||
|
|
||||||
if (info.Client.HasServer)
|
if (info.Client.HasServer)
|
||||||
@@ -258,7 +257,6 @@ namespace linker.messenger.store.file
|
|||||||
client.CApi.ApiPassword = configExportInfo.ApiPassword;
|
client.CApi.ApiPassword = configExportInfo.ApiPassword;
|
||||||
}
|
}
|
||||||
client.CApi.WebPort = configExportInfo.WebPort;
|
client.CApi.WebPort = configExportInfo.WebPort;
|
||||||
client.CApi.ApiPort = configExportInfo.ApiPort;
|
|
||||||
|
|
||||||
client.AccessBits = accessStore.AssignAccess(configExportInfo.Access);
|
client.AccessBits = accessStore.AssignAccess(configExportInfo.Access);
|
||||||
|
|
||||||
@@ -321,7 +319,6 @@ namespace linker.messenger.store.file
|
|||||||
public string GroupId { get; set; }
|
public string GroupId { get; set; }
|
||||||
public string GroupPassword { get; set; }
|
public string GroupPassword { get; set; }
|
||||||
|
|
||||||
public int Api { get; set; }
|
|
||||||
public int Web { get; set; }
|
public int Web { get; set; }
|
||||||
public string Password { get; set; }
|
public string Password { get; set; }
|
||||||
|
|
||||||
@@ -370,7 +367,6 @@ namespace linker.messenger.store.file
|
|||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string ApiPassword { get; set; }
|
public string ApiPassword { get; set; }
|
||||||
public int WebPort { get; set; }
|
public int WebPort { get; set; }
|
||||||
public int ApiPort { get; set; }
|
|
||||||
public bool Single { get; set; }
|
public bool Single { get; set; }
|
||||||
public BitArray Access { get; set; }
|
public BitArray Access { get; set; }
|
||||||
|
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using linker.libs;
|
using linker.libs;
|
||||||
|
using linker.libs.web;
|
||||||
using linker.messenger.action;
|
using linker.messenger.action;
|
||||||
using linker.messenger.api;
|
using linker.messenger.api;
|
||||||
using linker.messenger.firewall;
|
using linker.messenger.firewall;
|
||||||
@@ -126,8 +127,8 @@ namespace linker.messenger.store.file
|
|||||||
fileConfig.Save(config);
|
fileConfig.Save(config);
|
||||||
RunningConfig runningConfig = serviceProvider.GetService<RunningConfig>();
|
RunningConfig runningConfig = serviceProvider.GetService<RunningConfig>();
|
||||||
|
|
||||||
IApiServer apiServer = serviceProvider.GetService<IApiServer>();
|
linker.messenger.api.IWebServer apiServer = serviceProvider.GetService<linker.messenger.api.IWebServer>();
|
||||||
apiServer.AddPlugins(new List<libs.api.IApiController> { serviceProvider.GetService<ConfigApiController>() });
|
apiServer.AddPlugins(new List<IApiController> { serviceProvider.GetService<ConfigApiController>() });
|
||||||
|
|
||||||
SyncTreansfer syncTreansfer = serviceProvider.GetService<SyncTreansfer>();
|
SyncTreansfer syncTreansfer = serviceProvider.GetService<SyncTreansfer>();
|
||||||
syncTreansfer.AddSyncs(new List<ISync> {
|
syncTreansfer.AddSyncs(new List<ISync> {
|
||||||
|
@@ -24,12 +24,6 @@ namespace linker.messenger.store.file.api
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SetApiPort(int port)
|
|
||||||
{
|
|
||||||
fileConfig.Data.Client.CApi.ApiPort = port;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool SetApiPassword(string password)
|
public bool SetApiPassword(string password)
|
||||||
{
|
{
|
||||||
fileConfig.Data.Client.CApi.ApiPassword = password;
|
fileConfig.Data.Client.CApi.ApiPassword = password;
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
using linker.libs.api;
|
using linker.libs.web;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using IApiServer = linker.messenger.api.IApiServer;
|
|
||||||
namespace linker.messenger.sync
|
namespace linker.messenger.sync
|
||||||
{
|
{
|
||||||
public static class Entry
|
public static class Entry
|
||||||
@@ -17,7 +16,7 @@ namespace linker.messenger.sync
|
|||||||
IMessengerResolver messengerResolver= serviceProvider.GetService<IMessengerResolver>();
|
IMessengerResolver messengerResolver= serviceProvider.GetService<IMessengerResolver>();
|
||||||
messengerResolver.AddMessenger(new List<IMessenger> { serviceProvider.GetService<SyncClientMessenger>() });
|
messengerResolver.AddMessenger(new List<IMessenger> { serviceProvider.GetService<SyncClientMessenger>() });
|
||||||
|
|
||||||
IApiServer apiServer = serviceProvider.GetService<IApiServer>();
|
linker.messenger.api.IWebServer apiServer = serviceProvider.GetService<linker.messenger.api.IWebServer>();
|
||||||
apiServer.AddPlugins(new List<IApiController> { serviceProvider.GetService<SyncApiController>() });
|
apiServer.AddPlugins(new List<IApiController> { serviceProvider.GetService<SyncApiController>() });
|
||||||
|
|
||||||
return serviceProvider;
|
return serviceProvider;
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
using linker.libs.api;
|
using linker.libs.extends;
|
||||||
using linker.libs.extends;
|
using linker.libs.web;
|
||||||
using linker.messenger.api;
|
using linker.messenger.api;
|
||||||
namespace linker.messenger.sync
|
namespace linker.messenger.sync
|
||||||
{
|
{
|
||||||
|
@@ -8,6 +8,7 @@ using System.Text.Json;
|
|||||||
using linker.tunnel.connection;
|
using linker.tunnel.connection;
|
||||||
using linker.messenger.signin.args;
|
using linker.messenger.signin.args;
|
||||||
using linker.messenger.sync;
|
using linker.messenger.sync;
|
||||||
|
using linker.libs.web;
|
||||||
namespace linker.messenger.tunnel
|
namespace linker.messenger.tunnel
|
||||||
{
|
{
|
||||||
public static class Entry
|
public static class Entry
|
||||||
@@ -55,8 +56,8 @@ namespace linker.messenger.tunnel
|
|||||||
DecenterClientTransfer decenterClientTransfer = serviceProvider.GetService<DecenterClientTransfer>();
|
DecenterClientTransfer decenterClientTransfer = serviceProvider.GetService<DecenterClientTransfer>();
|
||||||
decenterClientTransfer.AddDecenters(new List<IDecenter> { serviceProvider.GetService<TunnelDecenter>() });
|
decenterClientTransfer.AddDecenters(new List<IDecenter> { serviceProvider.GetService<TunnelDecenter>() });
|
||||||
|
|
||||||
IApiServer apiServer = serviceProvider.GetService<IApiServer>();
|
linker.messenger.api.IWebServer apiServer = serviceProvider.GetService<linker.messenger.api.IWebServer>();
|
||||||
apiServer.AddPlugins(new List<libs.api.IApiController> { serviceProvider.GetService<TunnelApiController>() });
|
apiServer.AddPlugins(new List<IApiController> { serviceProvider.GetService<TunnelApiController>() });
|
||||||
|
|
||||||
|
|
||||||
ExRouteTransfer exRouteTransfer = serviceProvider.GetService<ExRouteTransfer>();
|
ExRouteTransfer exRouteTransfer = serviceProvider.GetService<ExRouteTransfer>();
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
using linker.tunnel.transport;
|
using linker.tunnel.transport;
|
||||||
using linker.libs.api;
|
|
||||||
using linker.libs.extends;
|
using linker.libs.extends;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using linker.messenger.signin;
|
using linker.messenger.signin;
|
||||||
@@ -7,6 +6,7 @@ using linker.libs;
|
|||||||
using linker.messenger.api;
|
using linker.messenger.api;
|
||||||
using linker.tunnel.connection;
|
using linker.tunnel.connection;
|
||||||
using linker.tunnel;
|
using linker.tunnel;
|
||||||
|
using linker.libs.web;
|
||||||
|
|
||||||
namespace linker.messenger.tunnel
|
namespace linker.messenger.tunnel
|
||||||
{
|
{
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
using linker.libs;
|
using linker.libs;
|
||||||
using linker.libs.extends;
|
using linker.libs.extends;
|
||||||
|
using linker.libs.web;
|
||||||
using linker.messenger.api;
|
using linker.messenger.api;
|
||||||
using linker.messenger.decenter;
|
using linker.messenger.decenter;
|
||||||
using linker.messenger.exroute;
|
using linker.messenger.exroute;
|
||||||
@@ -61,8 +62,8 @@ namespace linker.messenger.tuntap
|
|||||||
IMessengerResolver messengerResolver = serviceProvider.GetService<IMessengerResolver>();
|
IMessengerResolver messengerResolver = serviceProvider.GetService<IMessengerResolver>();
|
||||||
messengerResolver.AddMessenger(new List<IMessenger> { serviceProvider.GetService<TuntapClientMessenger>() });
|
messengerResolver.AddMessenger(new List<IMessenger> { serviceProvider.GetService<TuntapClientMessenger>() });
|
||||||
|
|
||||||
IApiServer apiServer = serviceProvider.GetService<IApiServer>();
|
linker.messenger.api.IWebServer apiServer = serviceProvider.GetService<linker.messenger.api.IWebServer>();
|
||||||
apiServer.AddPlugins(new List<libs.api.IApiController> { serviceProvider.GetService<TuntapApiController>() });
|
apiServer.AddPlugins(new List<IApiController> { serviceProvider.GetService<TuntapApiController>() });
|
||||||
|
|
||||||
ExRouteTransfer exRouteTransfer = serviceProvider.GetService<ExRouteTransfer>();
|
ExRouteTransfer exRouteTransfer = serviceProvider.GetService<ExRouteTransfer>();
|
||||||
exRouteTransfer.AddExRoutes(new List<IExRoute> { serviceProvider.GetService<TuntapExRoute>() });
|
exRouteTransfer.AddExRoutes(new List<IExRoute> { serviceProvider.GetService<TuntapExRoute>() });
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
using linker.libs.api;
|
using linker.libs.extends;
|
||||||
using linker.libs.extends;
|
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using linker.tunnel.connection;
|
using linker.tunnel.connection;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
@@ -8,6 +7,7 @@ using linker.messenger.signin;
|
|||||||
using linker.messenger.tuntap.lease;
|
using linker.messenger.tuntap.lease;
|
||||||
using linker.messenger.api;
|
using linker.messenger.api;
|
||||||
using linker.messenger.tuntap.messenger;
|
using linker.messenger.tuntap.messenger;
|
||||||
|
using linker.libs.web;
|
||||||
|
|
||||||
namespace linker.messenger.tuntap
|
namespace linker.messenger.tuntap
|
||||||
{
|
{
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
using linker.messenger.api;
|
using linker.libs.web;
|
||||||
using linker.messenger.sync;
|
using linker.messenger.sync;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
namespace linker.messenger.updater
|
namespace linker.messenger.updater
|
||||||
@@ -30,8 +30,8 @@ namespace linker.messenger.updater
|
|||||||
SyncTreansfer syncTransfer = serviceProvider.GetService<SyncTreansfer>();
|
SyncTreansfer syncTransfer = serviceProvider.GetService<SyncTreansfer>();
|
||||||
syncTransfer.AddSyncs(new List<ISync> { serviceProvider.GetService<UpdaterConfigSyncSecretKey>() });
|
syncTransfer.AddSyncs(new List<ISync> { serviceProvider.GetService<UpdaterConfigSyncSecretKey>() });
|
||||||
|
|
||||||
IApiServer apiServer = serviceProvider.GetService<IApiServer>();
|
linker.messenger.api.IWebServer apiServer = serviceProvider.GetService<linker.messenger.api.IWebServer>();
|
||||||
apiServer.AddPlugins(new List<libs.api.IApiController> { serviceProvider.GetService<UpdaterApiController>() });
|
apiServer.AddPlugins(new List<IApiController> { serviceProvider.GetService<UpdaterApiController>() });
|
||||||
|
|
||||||
return serviceProvider;
|
return serviceProvider;
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
using linker.libs.api;
|
using linker.libs.extends;
|
||||||
using linker.libs.extends;
|
|
||||||
using linker.libs;
|
using linker.libs;
|
||||||
using linker.messenger.signin;
|
using linker.messenger.signin;
|
||||||
|
using linker.libs.web;
|
||||||
|
|
||||||
namespace linker.messenger.updater
|
namespace linker.messenger.updater
|
||||||
{
|
{
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
|
|
||||||
|
using linker.libs.web;
|
||||||
using linker.messenger.api;
|
using linker.messenger.api;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
namespace linker.messenger.wakeup
|
namespace linker.messenger.wakeup
|
||||||
@@ -21,8 +22,8 @@ namespace linker.messenger.wakeup
|
|||||||
IMessengerResolver messengerResolver = serviceProvider.GetService<IMessengerResolver>();
|
IMessengerResolver messengerResolver = serviceProvider.GetService<IMessengerResolver>();
|
||||||
messengerResolver.AddMessenger(new List<IMessenger> { serviceProvider.GetService<WakeupClientMessenger>() });
|
messengerResolver.AddMessenger(new List<IMessenger> { serviceProvider.GetService<WakeupClientMessenger>() });
|
||||||
|
|
||||||
IApiServer apiServer = serviceProvider.GetService<IApiServer>();
|
linker.messenger.api.IWebServer apiServer = serviceProvider.GetService<linker.messenger.api.IWebServer>();
|
||||||
apiServer.AddPlugins(new List<libs.api.IApiController> { serviceProvider.GetService<WakeupApiController>() });
|
apiServer.AddPlugins(new List<IApiController> { serviceProvider.GetService<WakeupApiController>() });
|
||||||
|
|
||||||
return serviceProvider;
|
return serviceProvider;
|
||||||
}
|
}
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
using linker.libs.api;
|
using linker.libs;
|
||||||
using linker.libs;
|
|
||||||
using linker.messenger.signin;
|
using linker.messenger.signin;
|
||||||
using linker.messenger.api;
|
using linker.messenger.api;
|
||||||
using linker.libs.extends;
|
using linker.libs.extends;
|
||||||
|
using linker.libs.web;
|
||||||
|
|
||||||
namespace linker.messenger.wakeup
|
namespace linker.messenger.wakeup
|
||||||
{
|
{
|
||||||
|
@@ -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.281" ProductVersion="0.0.0.281" 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.283" ProductVersion="0.0.0.283" 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"/>
|
||||||
@@ -51,5 +51,6 @@
|
|||||||
<file name="app.842662e0.js" path="web\js\app.842662e0.js" comment="web\js\app.842662e0.js"/>
|
<file name="app.842662e0.js" path="web\js\app.842662e0.js" comment="web\js\app.842662e0.js"/>
|
||||||
<file name="chunk-vendors.710dc716.js" path="web\js\chunk-vendors.710dc716.js" comment="web\js\chunk-vendors.710dc716.js"/>
|
<file name="chunk-vendors.710dc716.js" path="web\js\chunk-vendors.710dc716.js" comment="web\js\chunk-vendors.710dc716.js"/>
|
||||||
</folder>
|
</folder>
|
||||||
|
<file name="test.html" path="web\test.html" comment="web\test.html"/>
|
||||||
</folder>
|
</folder>
|
||||||
</project>
|
</project>
|
||||||
|
BIN
src/linker.tray.win/dist/linker.tray.win.exe
vendored
BIN
src/linker.tray.win/dist/linker.tray.win.exe
vendored
Binary file not shown.
@@ -1,6 +1,6 @@
|
|||||||
import win.ui;
|
import win.ui;
|
||||||
/*DSG{{*/
|
/*DSG{{*/
|
||||||
var winform = win.form(text="linker 管理";right=849;bottom=739;max=false;min=1;topmost=1)
|
var winform = win.form(text="linker 管理";right=849;bottom=739;max=false;topmost=1)
|
||||||
winform.add()
|
winform.add()
|
||||||
/*}}*/
|
/*}}*/
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import win.ui;
|
import win.ui;
|
||||||
/*DSG{{*/
|
/*DSG{{*/
|
||||||
var winform = win.form(text="linker 管理(简单)";right=399;bottom=639;border="thin";max=false;min=1;topmost=1)
|
var winform = win.form(text="linker 管理(简单)";right=399;bottom=639;border="thin";max=false;topmost=1)
|
||||||
winform.add()
|
winform.add()
|
||||||
/*}}*/
|
/*}}*/
|
||||||
|
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
<!doctype html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon.ico"><title>linker.web</title><link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin=""/><script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script><script defer="defer" src="js/chunk-vendors.81af7d4e.js"></script><script defer="defer" src="js/app.2201faad.js"></script><link href="css/chunk-vendors.d8267b33.css" rel="stylesheet"><link href="css/app.bb3197c7.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but linker.web doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
|
<!doctype html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon.ico"><title>linker.web</title><link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin=""/><script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script><script defer="defer" src="js/chunk-vendors.81af7d4e.js"></script><script defer="defer" src="js/app.ca5c5474.js"></script><link href="css/chunk-vendors.d8267b33.css" rel="stylesheet"><link href="css/app.af897554.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but linker.web doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
|
File diff suppressed because one or more lines are too long
1
src/linker.tray.win/web/js/226.e53f663b.js
Normal file
1
src/linker.tray.win/web/js/226.e53f663b.js
Normal file
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
"use strict";(self["webpackChunklinker_web"]=self["webpackChunklinker_web"]||[]).push([[663],{7332:function(e,n,a){a.r(n),a.d(n,{default:function(){return O}});var t=a(56768);const s={class:"net-wrap app-wrap"},l={class:"inner absolute flex flex-column flex-nowrap"},i={class:"head"},o={class:"body flex-1 relative"},c={class:"status"};function r(e,n,a,r,u,d){const g=(0,t.g2)("Head"),p=(0,t.g2)("List"),v=(0,t.g2)("Status");return(0,t.uX)(),(0,t.CE)("div",s,[(0,t.Lk)("div",l,[(0,t.Lk)("div",i,[(0,t.bF)(g)]),(0,t.Lk)("div",o,[(0,t.bF)(p)]),(0,t.Lk)("div",c,[(0,t.bF)(v,{config:!1})])])])}a(44114);var u=a(24232);const d=e=>((0,t.Qi)("data-v-6bfe19a3"),e=e(),(0,t.jt)(),e),g={class:"head-wrap"},p={class:"tools flex"},v={class:"label"},h=d((()=>(0,t.Lk)("span",{class:"flex-1"},null,-1))),f={style:{"margin-left":"1rem"}};function k(e,n,a,s,l,i){const o=(0,t.g2)("Refresh"),c=(0,t.g2)("el-icon"),r=(0,t.g2)("el-button"),d=(0,t.g2)("Background");return(0,t.uX)(),(0,t.CE)("div",g,[(0,t.Lk)("div",p,[(0,t.Lk)("span",v,"分组 : "+(0,u.v_)(s.state.group),1),h,(0,t.bF)(r,{size:"small",onClick:s.handleRefresh},{default:(0,t.k6)((()=>[(0,t.eW)(" 刷新(F5)"),(0,t.bF)(c,null,{default:(0,t.k6)((()=>[(0,t.bF)(o)])),_:1})])),_:1},8,["onClick"]),(0,t.Lk)("div",f,[(0,t.bF)(d,{name:"net"})])])])}var C=a(53830),m=a(90144),b=a(57477),L=a(5096),_={components:{Edit:b.ffu,Refresh:b.C42,Background:L.A},setup(){const e=(0,C.B)(),n=(0,m.Kh)({server:(0,t.EW)((()=>e.value.config.Client.Server.Host)),group:(0,t.EW)((()=>e.value.config.Client.Group.Name))}),a=()=>{window.location.reload()};return{state:n,handleRefresh:a}}},w=a(71241);const S=(0,w.A)(_,[["render",k],["__scopeId","data-v-6bfe19a3"]]);var F=S;const x=e=>((0,t.Qi)("data-v-68d1c30a"),e=e(),(0,t.jt)(),e),T={class:"net-list-wrap flex flex-column absolute"},z={class:"flex-1 scrollbar"},E={class:"flex"},A=x((()=>(0,t.Lk)("div",{class:"flex-1"},null,-1))),I={class:"tuntap"},P={class:"page t-c"},B={class:"page-wrap t-c"};function R(e,n,a,s,l,i){const o=(0,t.g2)("DeviceName"),c=(0,t.g2)("UpdaterBtn"),r=(0,t.g2)("TuntapShow"),u=(0,t.g2)("el-pagination");return(0,t.uX)(),(0,t.CE)("div",T,[(0,t.Lk)("div",z,[(0,t.Lk)("ul",null,[((0,t.uX)(!0),(0,t.CE)(t.FK,null,(0,t.pI)(s.devices.page.List,((e,n)=>((0,t.uX)(),(0,t.CE)("li",{key:n},[(0,t.Lk)("dl",null,[(0,t.Lk)("dt",E,[(0,t.Lk)("div",null,[(0,t.bF)(o,{item:e},null,8,["item"])]),A,(0,t.Lk)("div",null,[(0,t.bF)(c,{config:!1,item:e},null,8,["item"])])]),(0,t.Lk)("dd",I,[s.tuntap.list[e.MachineId]?((0,t.uX)(),(0,t.Wv)(r,{key:0,item:e},null,8,["item"])):(0,t.Q3)("",!0)])])])))),128))])]),(0,t.Lk)("div",P,[(0,t.Lk)("div",B,[(0,t.bF)(u,{size:"small",background:"",layout:"prev,pager, next","pager-count":5,total:s.devices.page.Count,"page-size":s.devices.page.Request.Size,"current-page":s.devices.page.Request.Page,onCurrentChange:s.handlePageChange,onSizeChange:s.handlePageSizeChange,"page-sizes":[10,20,50,100,255]},null,8,["total","page-size","current-page","onCurrentChange","onSizeChange"])])])])}var D=a(98104),X=a(27985),y=a(39383),N=a(62956),U=a(27569),Q=a(57671),W=a(99983),H={components:{StarFilled:b.BQ2,UpdaterBtn:N.A,DeviceName:U.A,TuntapShow:Q.A},setup(e){(0,C.B)();const n=(0,m.Kh)({}),{devices:a,machineId:s,_getSignList:l,_getSignList1:i,handleDeviceEdit:o,handlePageChange:c,handlePageSizeChange:r,handleDel:u,clearDevicesTimeout:d}=(0,X.r)(),{tuntap:g,_getTuntapInfo:p,handleTuntapRefresh:v,clearTuntapTimeout:h,handleTuntapEdit:f,sortTuntapIP:k}=(0,D.O)(),{_getUpdater:b,_subscribeUpdater:L,clearUpdaterTimeout:_}=(0,y.d)(),{connections:w,forwardConnections:S,_getForwardConnections:F,tuntapConnections:x,_getTuntapConnections:T,socks5Connections:z,_getSocks5Connections:E,handleTunnelConnections:A,clearConnectionsTimeout:I}=(0,W.L2)();return(0,t.sV)((()=>{c(),v(),l(),i(),p(),b(),L()})),(0,t.hi)((()=>{d(),h(),_()})),{state:n,devices:a,machineId:s,handlePageChange:c,handlePageSizeChange:r,tuntap:g}}};const K=(0,w.A)(H,[["render",R],["__scopeId","data-v-68d1c30a"]]);var j=K,q=a(24722),M=a(81387),V={components:{Head:F,List:j,Status:q.A},setup(){document.addEventListener("contextmenu",(function(e){e.preventDefault()}));const e=(0,C.B)(),n=(0,M.rd)();return(0,t.sV)((()=>{0==e.value.hasAccess("NetManager")&&n.push({name:"NoPermission"})})),{}}};const G=(0,w.A)(V,[["render",r],["__scopeId","data-v-6a3f3b43"]]);var O=G}}]);
|
"use strict";(self["webpackChunklinker_web"]=self["webpackChunklinker_web"]||[]).push([[519],{7332:function(e,n,a){a.r(n),a.d(n,{default:function(){return O}});var t=a(56768);const s={class:"net-wrap app-wrap"},l={class:"inner absolute flex flex-column flex-nowrap"},i={class:"head"},o={class:"body flex-1 relative"},c={class:"status"};function r(e,n,a,r,u,d){const g=(0,t.g2)("Head"),p=(0,t.g2)("List"),v=(0,t.g2)("Status");return(0,t.uX)(),(0,t.CE)("div",s,[(0,t.Lk)("div",l,[(0,t.Lk)("div",i,[(0,t.bF)(g)]),(0,t.Lk)("div",o,[(0,t.bF)(p)]),(0,t.Lk)("div",c,[(0,t.bF)(v,{config:!1})])])])}a(44114);var u=a(24232);const d=e=>((0,t.Qi)("data-v-6bfe19a3"),e=e(),(0,t.jt)(),e),g={class:"head-wrap"},p={class:"tools flex"},v={class:"label"},h=d((()=>(0,t.Lk)("span",{class:"flex-1"},null,-1))),f={style:{"margin-left":"1rem"}};function k(e,n,a,s,l,i){const o=(0,t.g2)("Refresh"),c=(0,t.g2)("el-icon"),r=(0,t.g2)("el-button"),d=(0,t.g2)("Background");return(0,t.uX)(),(0,t.CE)("div",g,[(0,t.Lk)("div",p,[(0,t.Lk)("span",v,"分组 : "+(0,u.v_)(s.state.group),1),h,(0,t.bF)(r,{size:"small",onClick:s.handleRefresh},{default:(0,t.k6)((()=>[(0,t.eW)(" 刷新(F5)"),(0,t.bF)(c,null,{default:(0,t.k6)((()=>[(0,t.bF)(o)])),_:1})])),_:1},8,["onClick"]),(0,t.Lk)("div",f,[(0,t.bF)(d,{name:"net"})])])])}var C=a(53830),m=a(90144),b=a(57477),L=a(5096),_={components:{Edit:b.ffu,Refresh:b.C42,Background:L.A},setup(){const e=(0,C.B)(),n=(0,m.Kh)({server:(0,t.EW)((()=>e.value.config.Client.Server.Host)),group:(0,t.EW)((()=>e.value.config.Client.Group.Name))}),a=()=>{window.location.reload()};return{state:n,handleRefresh:a}}},w=a(71241);const S=(0,w.A)(_,[["render",k],["__scopeId","data-v-6bfe19a3"]]);var F=S;const x=e=>((0,t.Qi)("data-v-68d1c30a"),e=e(),(0,t.jt)(),e),T={class:"net-list-wrap flex flex-column absolute"},z={class:"flex-1 scrollbar"},E={class:"flex"},A=x((()=>(0,t.Lk)("div",{class:"flex-1"},null,-1))),I={class:"tuntap"},P={class:"page t-c"},B={class:"page-wrap t-c"};function R(e,n,a,s,l,i){const o=(0,t.g2)("DeviceName"),c=(0,t.g2)("UpdaterBtn"),r=(0,t.g2)("TuntapShow"),u=(0,t.g2)("el-pagination");return(0,t.uX)(),(0,t.CE)("div",T,[(0,t.Lk)("div",z,[(0,t.Lk)("ul",null,[((0,t.uX)(!0),(0,t.CE)(t.FK,null,(0,t.pI)(s.devices.page.List,((e,n)=>((0,t.uX)(),(0,t.CE)("li",{key:n},[(0,t.Lk)("dl",null,[(0,t.Lk)("dt",E,[(0,t.Lk)("div",null,[(0,t.bF)(o,{item:e},null,8,["item"])]),A,(0,t.Lk)("div",null,[(0,t.bF)(c,{config:!1,item:e},null,8,["item"])])]),(0,t.Lk)("dd",I,[s.tuntap.list[e.MachineId]?((0,t.uX)(),(0,t.Wv)(r,{key:0,item:e},null,8,["item"])):(0,t.Q3)("",!0)])])])))),128))])]),(0,t.Lk)("div",P,[(0,t.Lk)("div",B,[(0,t.bF)(u,{size:"small",background:"",layout:"prev,pager, next","pager-count":5,total:s.devices.page.Count,"page-size":s.devices.page.Request.Size,"current-page":s.devices.page.Request.Page,onCurrentChange:s.handlePageChange,onSizeChange:s.handlePageSizeChange,"page-sizes":[10,20,50,100,255]},null,8,["total","page-size","current-page","onCurrentChange","onSizeChange"])])])])}var D=a(98104),X=a(27985),y=a(39383),N=a(62956),U=a(27569),Q=a(57671),W=a(99983),H={components:{StarFilled:b.BQ2,UpdaterBtn:N.A,DeviceName:U.A,TuntapShow:Q.A},setup(e){(0,C.B)();const n=(0,m.Kh)({}),{devices:a,machineId:s,_getSignList:l,_getSignList1:i,handleDeviceEdit:o,handlePageChange:c,handlePageSizeChange:r,handleDel:u,clearDevicesTimeout:d}=(0,X.r)(),{tuntap:g,_getTuntapInfo:p,handleTuntapRefresh:v,clearTuntapTimeout:h,handleTuntapEdit:f,sortTuntapIP:k}=(0,D.O)(),{_getUpdater:b,_subscribeUpdater:L,clearUpdaterTimeout:_}=(0,y.d)(),{connections:w,forwardConnections:S,_getForwardConnections:F,tuntapConnections:x,_getTuntapConnections:T,socks5Connections:z,_getSocks5Connections:E,handleTunnelConnections:A,clearConnectionsTimeout:I}=(0,W.L2)();return(0,t.sV)((()=>{c(),v(),l(),i(),p(),b(),L()})),(0,t.hi)((()=>{d(),h(),_()})),{state:n,devices:a,machineId:s,handlePageChange:c,handlePageSizeChange:r,tuntap:g}}};const K=(0,w.A)(H,[["render",R],["__scopeId","data-v-68d1c30a"]]);var j=K,q=a(44453),M=a(81387),V={components:{Head:F,List:j,Status:q.A},setup(){document.addEventListener("contextmenu",(function(e){e.preventDefault()}));const e=(0,C.B)(),n=(0,M.rd)();return(0,t.sV)((()=>{0==e.value.hasAccess("NetManager")&&n.push({name:"NoPermission"})})),{}}};const G=(0,w.A)(V,[["render",r],["__scopeId","data-v-6a3f3b43"]]);var O=G}}]);
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
src/linker.tray.win/web/js/app.ca5c5474.js
Normal file
1
src/linker.tray.win/web/js/app.ca5c5474.js
Normal file
File diff suppressed because one or more lines are too long
@@ -1,28 +1,15 @@
|
|||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
|
|
||||||
let requestId = 0, ws = null, wsUrl = '', index = 1, apiPassword = '';
|
let requestId = 0, ws = null, wsUrl = '', index = 1, apiPassword = 'snltty';
|
||||||
//请求缓存,等待回调
|
|
||||||
const requests = {};
|
const requests = {};
|
||||||
const queues = [];
|
|
||||||
export const websocketState = { connected: false, connecting: false };
|
export const websocketState = { connected: false, connecting: false };
|
||||||
|
|
||||||
const sendQueueMsg = () => {
|
|
||||||
if (queues.length > 0 && websocketState.connected && ws && ws.readyState == 1) {
|
|
||||||
try {
|
|
||||||
ws.send(queues.shift());
|
|
||||||
} catch (e) { }
|
|
||||||
}
|
|
||||||
setTimeout(sendQueueMsg, 1000 / 60);
|
|
||||||
}
|
|
||||||
//sendQueueMsg();
|
|
||||||
|
|
||||||
|
|
||||||
const sendTimeout = () => {
|
const sendTimeout = () => {
|
||||||
const time = Date.now();
|
const time = Date.now();
|
||||||
for (let j in requests) {
|
for (let j in requests) {
|
||||||
const item = requests[j];
|
const item = requests[j];
|
||||||
if (time - item.time > item.timeout) {
|
if (time - item.time > item.timeout) {
|
||||||
item.reject('超时~');
|
item.reject(`超时:${JSON.stringify(item)}`);
|
||||||
delete requests[j];
|
delete requests[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -30,8 +17,6 @@ const sendTimeout = () => {
|
|||||||
}
|
}
|
||||||
sendTimeout();
|
sendTimeout();
|
||||||
|
|
||||||
|
|
||||||
//发布订阅
|
|
||||||
export const pushListener = {
|
export const pushListener = {
|
||||||
subs: {
|
subs: {
|
||||||
},
|
},
|
||||||
@@ -59,10 +44,10 @@ export const pushListener = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//消息处理
|
|
||||||
const onWebsocketOpen = () => {
|
const onWebsocketOpen = () => {
|
||||||
websocketState.connected = true;
|
websocketState.connected = true;
|
||||||
websocketState.connecting = false;
|
websocketState.connecting = false;
|
||||||
|
sendWebsocketMsg('password',apiPassword || 'snltty');
|
||||||
pushListener.push(websocketStateChangeKey, websocketState.connected);
|
pushListener.push(websocketStateChangeKey, websocketState.connected);
|
||||||
}
|
}
|
||||||
const onWebsocketClose = (e) => {
|
const onWebsocketClose = (e) => {
|
||||||
@@ -125,8 +110,7 @@ export const initWebsocket = (url = wsUrl, password = apiPassword) => {
|
|||||||
ws.close();
|
ws.close();
|
||||||
}
|
}
|
||||||
websocketState.connecting = true;
|
websocketState.connecting = true;
|
||||||
const protocol = password || 'snltty';
|
ws = new WebSocket(wsUrl);
|
||||||
ws = new WebSocket(wsUrl, [protocol]);
|
|
||||||
ws.iddd = ++index;
|
ws.iddd = ++index;
|
||||||
ws.onopen = onWebsocketOpen;
|
ws.onopen = onWebsocketOpen;
|
||||||
ws.onclose = onWebsocketClose
|
ws.onclose = onWebsocketClose
|
||||||
@@ -140,8 +124,6 @@ export const closeWebsocket = () => {
|
|||||||
ws.close();
|
ws.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//发送消息
|
|
||||||
export const sendWebsocketMsg = (path, msg = {}, errHandle = false, timeout = 15000) => {
|
export const sendWebsocketMsg = (path, msg = {}, errHandle = false, timeout = 15000) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let id = ++requestId;
|
let id = ++requestId;
|
||||||
@@ -165,7 +147,6 @@ export const sendWebsocketMsg = (path, msg = {}, errHandle = false, timeout = 15
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const websocketStateChangeKey = Symbol();
|
const websocketStateChangeKey = Symbol();
|
||||||
export const subWebsocketState = (callback) => {
|
export const subWebsocketState = (callback) => {
|
||||||
pushListener.add(websocketStateChangeKey, callback);
|
pushListener.add(websocketStateChangeKey, callback);
|
||||||
|
@@ -66,9 +66,9 @@ export default {
|
|||||||
'status.exportSingle': '单设备',
|
'status.exportSingle': '单设备',
|
||||||
'status.exportName': '设备名',
|
'status.exportName': '设备名',
|
||||||
'status.exportNamePlease': '请输入设备名',
|
'status.exportNamePlease': '请输入设备名',
|
||||||
'status.exportApiPassword': '接口密码',
|
'status.exportApiPassword': '管理密码',
|
||||||
'status.exportApiPasswordPlease': '请输入接口密码',
|
'status.exportApiPasswordPlease': '请输入接口密码',
|
||||||
'status.exportWebport': '网页端口',
|
'status.exportWebport': '管理端口',
|
||||||
'status.exportWebportPlease': '请输入网页端口',
|
'status.exportWebportPlease': '请输入网页端口',
|
||||||
'status.exportApiport': '接口端口',
|
'status.exportApiport': '接口端口',
|
||||||
'status.exportApiportPlease': '请输入接口端口',
|
'status.exportApiportPlease': '请输入接口端口',
|
||||||
|
@@ -32,8 +32,9 @@ export default {
|
|||||||
const globalData = injectGlobalData();
|
const globalData = injectGlobalData();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
const defaultInfo = {api:`${window.location.hostname}:1803`,psd:'snltty'};
|
const api = process.env.NODE_ENV == 'development' ? `${window.location.hostname}:1804` : window.location.host;
|
||||||
|
const defaultInfo = {api:api,psd:'snltty'};
|
||||||
const queryCache = JSON.parse(sessionStorage.getItem('api-cache') || localStorage.getItem('api-cache') || JSON.stringify(defaultInfo));
|
const queryCache = JSON.parse(sessionStorage.getItem('api-cache') || localStorage.getItem('api-cache') || JSON.stringify(defaultInfo));
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
api:queryCache.api,
|
api:queryCache.api,
|
||||||
|
@@ -7,35 +7,30 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="" label-width="0">
|
<el-form-item label="" label-width="0">
|
||||||
<el-row>
|
<el-row class="w-100">
|
||||||
<el-col :sm="12" :xs="24">
|
<el-col :sm="12" :xs="24">
|
||||||
<el-form-item label="机器名" prop="name">
|
<el-form-item label="机器名" prop="name">
|
||||||
<el-input v-model="state.form.name" maxlength="32" show-word-limit />
|
<el-input v-model="state.form.name" maxlength="32" show-word-limit />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :sm="12" :xs="24" v-if="globalData.isPc">
|
|
||||||
<el-form-item label="网页端口" prop="web">
|
|
||||||
<el-input v-model="state.form.web" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="" label-width="0" v-if="globalData.isPc">
|
<el-form-item label="" label-width="0" v-if="globalData.isPc">
|
||||||
<el-row>
|
<el-row class="w-100">
|
||||||
<el-col :sm="12" :xs="24">
|
<el-col :sm="12" :xs="24" v-if="globalData.isPc">
|
||||||
<el-form-item label="接口端口" prop="api">
|
<el-form-item label="管理端口" prop="web">
|
||||||
<el-input v-model="state.form.api" />
|
<el-input v-model="state.form.web" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :sm="12" :xs="24">
|
<el-col :sm="12" :xs="24">
|
||||||
<el-form-item label="接口密码" prop="password">
|
<el-form-item label="管理密码" prop="password">
|
||||||
<el-input type="password" v-model="state.form.password" show-password maxlength="36" show-word-limit/>
|
<el-input type="password" v-model="state.form.password" show-password maxlength="36" show-word-limit/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="" label-width="0">
|
<el-form-item label="" label-width="0">
|
||||||
<el-row>
|
<el-row class="w-100">
|
||||||
<el-col :sm="12" :xs="24">
|
<el-col :sm="12" :xs="24">
|
||||||
<el-form-item label="分组名" prop="groupid">
|
<el-form-item label="分组名" prop="groupid">
|
||||||
<el-input v-model="state.form.groupid" maxlength="36" show-word-limit />
|
<el-input v-model="state.form.groupid" maxlength="36" show-word-limit />
|
||||||
@@ -49,7 +44,7 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="" label-width="0">
|
<el-form-item label="" label-width="0">
|
||||||
<el-row>
|
<el-row class="w-100">
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-form-item label-width="8rem" prop="hasServer">
|
<el-form-item label-width="8rem" prop="hasServer">
|
||||||
<el-checkbox v-model="state.form.hasServer" label="我有服务器(私有部署)" size="large" />
|
<el-checkbox v-model="state.form.hasServer" label="我有服务器(私有部署)" size="large" />
|
||||||
@@ -59,7 +54,7 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="" label-width="0" v-if="state.form.hasServer">
|
<el-form-item label="" label-width="0" v-if="state.form.hasServer">
|
||||||
<el-row>
|
<el-row class="w-100">
|
||||||
<el-col :sm="12" :xs="24">
|
<el-col :sm="12" :xs="24">
|
||||||
<el-form-item label="信标服务" prop="server">
|
<el-form-item label="信标服务" prop="server">
|
||||||
<el-input v-model="state.form.server"/>
|
<el-input v-model="state.form.server"/>
|
||||||
@@ -74,7 +69,7 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="" label-width="0" v-if="state.form.hasServer">
|
<el-form-item label="" label-width="0" v-if="state.form.hasServer">
|
||||||
<el-row>
|
<el-row class="w-100">
|
||||||
<el-col :sm="12" :xs="24">
|
<el-col :sm="12" :xs="24">
|
||||||
<el-form-item label="穿透密钥" prop="sForwardSecretKey">
|
<el-form-item label="穿透密钥" prop="sForwardSecretKey">
|
||||||
<el-input v-model="state.form.sForwardSecretKey" maxlength="36" show-word-limit />
|
<el-input v-model="state.form.sForwardSecretKey" maxlength="36" show-word-limit />
|
||||||
@@ -88,7 +83,7 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="" label-width="0" v-if="state.form.hasServer">
|
<el-form-item label="" label-width="0" v-if="state.form.hasServer">
|
||||||
<el-row>
|
<el-row class="w-100">
|
||||||
<el-col :sm="12" :xs="24">
|
<el-col :sm="12" :xs="24">
|
||||||
<el-form-item label="更新密钥" prop="updaterSecretKey">
|
<el-form-item label="更新密钥" prop="updaterSecretKey">
|
||||||
<el-input v-model="state.form.updaterSecretKey" maxlength="36" show-word-limit />
|
<el-input v-model="state.form.updaterSecretKey" maxlength="36" show-word-limit />
|
||||||
@@ -118,7 +113,6 @@ export default {
|
|||||||
name:step.value.form.client.name || globalData.value.config.Client.Name,
|
name:step.value.form.client.name || globalData.value.config.Client.Name,
|
||||||
groupid: step.value.form.client.groupid ||globalData.value.config.Client.Group.Id,
|
groupid: step.value.form.client.groupid ||globalData.value.config.Client.Group.Id,
|
||||||
groupPassword: step.value.form.client.groupPassword ||globalData.value.config.Client.Group.Password,
|
groupPassword: step.value.form.client.groupPassword ||globalData.value.config.Client.Group.Password,
|
||||||
api: step.value.form.client.api ||globalData.value.config.Client.CApi.ApiPort,
|
|
||||||
web: step.value.form.client.web ||globalData.value.config.Client.CApi.WebPort,
|
web: step.value.form.client.web ||globalData.value.config.Client.CApi.WebPort,
|
||||||
password:step.value.form.client.password || globalData.value.config.Client.CApi.ApiPassword,
|
password:step.value.form.client.password || globalData.value.config.Client.CApi.ApiPassword,
|
||||||
|
|
||||||
@@ -134,19 +128,6 @@ export default {
|
|||||||
groupid: [{ required: true, message: "必填", trigger: "blur" }],
|
groupid: [{ required: true, message: "必填", trigger: "blur" }],
|
||||||
groupPassword: [{ required: true, message: "必填", trigger: "blur" }],
|
groupPassword: [{ required: true, message: "必填", trigger: "blur" }],
|
||||||
password: [{ required: true, message: "必填", trigger: "blur" }],
|
password: [{ required: true, message: "必填", trigger: "blur" }],
|
||||||
api: [
|
|
||||||
{ required: true, message: "必填", trigger: "blur" },
|
|
||||||
{
|
|
||||||
type: "number",
|
|
||||||
min: 0,
|
|
||||||
max: 65535,
|
|
||||||
message: "数字 0-65535",
|
|
||||||
trigger: "blur",
|
|
||||||
transform(value) {
|
|
||||||
return Number(value);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
web: [
|
web: [
|
||||||
{ required: true, message: "必填", trigger: "blur" },
|
{ required: true, message: "必填", trigger: "blur" },
|
||||||
{
|
{
|
||||||
@@ -173,7 +154,6 @@ export default {
|
|||||||
name: state.form.name,
|
name: state.form.name,
|
||||||
groupid: state.form.groupid,
|
groupid: state.form.groupid,
|
||||||
groupPassword: state.form.groupPassword,
|
groupPassword: state.form.groupPassword,
|
||||||
api: +state.form.api,
|
|
||||||
web: +state.form.web,
|
web: +state.form.web,
|
||||||
password: state.form.password,
|
password: state.form.password,
|
||||||
|
|
||||||
|
@@ -15,21 +15,16 @@
|
|||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<div>
|
<div>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="24"><el-checkbox :disabled="onlyNode" v-model="state.single" :label="$t('status.exportSingle')" /></el-col>
|
<el-col :span="12"><el-checkbox :disabled="onlyNode" v-model="state.single" :label="$t('status.exportSingle')" /></el-col>
|
||||||
</el-row>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<el-row>
|
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<div class="flex flex-nowrap">
|
<div class="flex flex-nowrap">
|
||||||
<span style="width: 11rem;">{{$t('status.exportName')}} : </span><el-input :disabled="!state.single" v-model="state.name" maxlength="32" show-word-limit></el-input>
|
<span style="width: 11rem;">{{$t('status.exportName')}} : </span><el-input :disabled="!state.single" v-model="state.name" maxlength="32" show-word-limit></el-input>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
</el-row>
|
||||||
<div class="flex flex-nowrap">
|
</div>
|
||||||
<span style="width: 11rem;">{{$t('status.exportApiPassword')}} : </span><el-input type="password" show-password :disabled="onlyNode" v-model="state.apipassword" maxlength="36" show-word-limit></el-input>
|
<div>
|
||||||
</div>
|
<el-row>
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<div class="flex flex-nowrap mgt-1">
|
<div class="flex flex-nowrap mgt-1">
|
||||||
<span style="width: 11rem;">{{$t('status.exportWebport')}} : </span><el-input :disabled="onlyNode" v-model="state.webport"></el-input>
|
<span style="width: 11rem;">{{$t('status.exportWebport')}} : </span><el-input :disabled="onlyNode" v-model="state.webport"></el-input>
|
||||||
@@ -37,7 +32,7 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<div class="flex flex-nowrap mgt-1">
|
<div class="flex flex-nowrap mgt-1">
|
||||||
<span style="width: 11rem;">{{$t('status.exportApiport')}} : </span><el-input :disabled="onlyNode" v-model="state.apiport"></el-input>
|
<span style="width: 11rem;">{{$t('status.exportApiPassword')}} : </span><el-input type="password" show-password :disabled="onlyNode" v-model="state.apipassword" maxlength="36" show-word-limit></el-input>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -112,7 +107,6 @@ export default {
|
|||||||
single:true,
|
single:true,
|
||||||
name:'',
|
name:'',
|
||||||
apipassword:onlyNode.value? globalData.value.config.Client.CApi.ApiPassword :'',
|
apipassword:onlyNode.value? globalData.value.config.Client.CApi.ApiPassword :'',
|
||||||
apiport: globalData.value.config.Client.CApi.ApiPort,
|
|
||||||
webport: globalData.value.config.Client.CApi.WebPort,
|
webport: globalData.value.config.Client.CApi.WebPort,
|
||||||
|
|
||||||
relay:true,
|
relay:true,
|
||||||
@@ -143,7 +137,6 @@ export default {
|
|||||||
name:state.name,
|
name:state.name,
|
||||||
apipassword:state.apipassword,
|
apipassword:state.apipassword,
|
||||||
webport:+state.webport,
|
webport:+state.webport,
|
||||||
apiport:+state.apiport,
|
|
||||||
relay:state.relay,
|
relay:state.relay,
|
||||||
sforward:state.sforward,
|
sforward:state.sforward,
|
||||||
updater:state.updater,
|
updater:state.updater,
|
||||||
@@ -168,10 +161,6 @@ export default {
|
|||||||
ElMessage.error(t('status.exportWebportPlease'));
|
ElMessage.error(t('status.exportWebportPlease'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!json.apiport || isNaN(json.apiport) || json.apiport<=0 || json.apiport>65535){
|
|
||||||
ElMessage.error(t('status.exportApiportPlease'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
const download = ()=>{
|
const download = ()=>{
|
||||||
|
@@ -20,8 +20,6 @@ RUN apt update \
|
|||||||
|
|
||||||
EXPOSE 1802/tcp
|
EXPOSE 1802/tcp
|
||||||
EXPOSE 1802/udp
|
EXPOSE 1802/udp
|
||||||
EXPOSE 1803/tcp
|
|
||||||
EXPOSE 1803/udp
|
|
||||||
EXPOSE 1804/tcp
|
EXPOSE 1804/tcp
|
||||||
EXPOSE 1804/udp
|
EXPOSE 1804/udp
|
||||||
|
|
||||||
|
@@ -20,8 +20,6 @@ RUN apt update \
|
|||||||
|
|
||||||
EXPOSE 1802/tcp
|
EXPOSE 1802/tcp
|
||||||
EXPOSE 1802/udp
|
EXPOSE 1802/udp
|
||||||
EXPOSE 1803/tcp
|
|
||||||
EXPOSE 1803/udp
|
|
||||||
EXPOSE 1804/tcp
|
EXPOSE 1804/tcp
|
||||||
EXPOSE 1804/udp
|
EXPOSE 1804/udp
|
||||||
EXPOSE 1806/tcp
|
EXPOSE 1806/tcp
|
||||||
|
@@ -10,8 +10,6 @@ RUN echo "https://mirrors.ustc.edu.cn/alpine/latest-stable/main/" > /etc/apk/rep
|
|||||||
|
|
||||||
EXPOSE 1802/tcp
|
EXPOSE 1802/tcp
|
||||||
EXPOSE 1802/udp
|
EXPOSE 1802/udp
|
||||||
EXPOSE 1803/tcp
|
|
||||||
EXPOSE 1803/udp
|
|
||||||
EXPOSE 1804/tcp
|
EXPOSE 1804/tcp
|
||||||
EXPOSE 1804/udp
|
EXPOSE 1804/udp
|
||||||
|
|
||||||
|
@@ -21,7 +21,10 @@
|
|||||||
<Authors>snltty</Authors>
|
<Authors>snltty</Authors>
|
||||||
<Company>snltty</Company>
|
<Company>snltty</Company>
|
||||||
<Description>1. 一些累计更新
|
<Description>1. 一些累计更新
|
||||||
2. 测试发布,请使用1.8.2</Description>
|
2. 重建权限存储,ulong改为BitArray,同组所有客户端需保持版本一致
|
||||||
|
3. 增加唤醒功能,支持WOL,COM继电器,HID继电器
|
||||||
|
4. 基于One-KVM包装docker镜像集成linker
|
||||||
|
5. 管理端口改为1804,一个端口托管Web+Websocket</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>
|
||||||
|
@@ -1,4 +1,7 @@
|
|||||||
v1.8.2
|
v1.8.2
|
||||||
2025-06-05 10:48:49
|
2025-06-05 17:13:06
|
||||||
1. 一些累计更新
|
1. 一些累计更新
|
||||||
2. 测试发布,请使用1.8.2
|
2. 重建权限存储,ulong改为BitArray,同组所有客户端需保持版本一致
|
||||||
|
3. 增加唤醒功能,支持WOL,COM继电器,HID继电器
|
||||||
|
4. 基于One-KVM包装docker镜像集成linker
|
||||||
|
5. 管理端口改为1804,一个端口托管Web+Websocket
|
Reference in New Issue
Block a user