mirror of
https://github.com/snltty/linker.git
synced 2025-09-27 21:42:18 +08:00
计划任务
This commit is contained in:
10
README.md
10
README.md
@@ -24,6 +24,16 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
## Platforms
|
||||||
|
|
||||||
|
| | amd64 | x86 | arm64 | arm |
|
||||||
|
|-------|-------|-------|-------|-------|
|
||||||
|
| Windows | ✔ | ✔ |✔ |✔ |
|
||||||
|
| Linux | ✔ | |✔ |✔ |
|
||||||
|
| Linux Musl | ✔ | |✔ |✔ |
|
||||||
|
| Openwrt | ✔ | |✔ |✔ |
|
||||||
|
| Android(soon) | ✔ | | | |
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
Using P2P or server relay, connect multiple LANs to enable communication between any networked devices across these LANs.
|
Using P2P or server relay, connect multiple LANs to enable communication between any networked devices across these LANs.
|
||||||
|
12
README_zh.md
12
README_zh.md
@@ -24,6 +24,16 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
## 支持平台
|
||||||
|
|
||||||
|
| | amd64 | x86 | arm64 | arm |
|
||||||
|
|-------|-------|-------|-------|-------|
|
||||||
|
| Windows | ✔ | ✔ |✔ |✔ |
|
||||||
|
| Linux | ✔ | |✔ |✔ |
|
||||||
|
| Linux Musl | ✔ | |✔ |✔ |
|
||||||
|
| Openwrt | ✔ | |✔ |✔ |
|
||||||
|
| Android(soon) | ✔ | | | |
|
||||||
|
|
||||||
## 大概意思
|
## 大概意思
|
||||||
|
|
||||||
使用p2p或者服务器转发,让你的各个局域网连通起来,让各个局域网内的任意联网设备都可以相互连通
|
使用p2p或者服务器转发,让你的各个局域网连通起来,让各个局域网内的任意联网设备都可以相互连通
|
||||||
@@ -50,7 +60,7 @@
|
|||||||
- [x] 异地组网,使用虚拟网卡,将各个客户端组建为局域网络,`点对点`,`点对网`,`网对网`
|
- [x] 异地组网,使用虚拟网卡,将各个客户端组建为局域网络,`点对点`,`点对网`,`网对网`
|
||||||
- [x] 网卡类库,你可以使用`linker.tun` tun网卡库到你的项目中
|
- [x] 网卡类库,你可以使用`linker.tun` tun网卡库到你的项目中
|
||||||
- [x] 端口转发,将客户端的端口转发到其它客户端的端口
|
- [x] 端口转发,将客户端的端口转发到其它客户端的端口
|
||||||
- [x] 服务器穿透,在服务器注册端口或域名,通过访问服务器端口或域名,访问内网服务
|
- [x] 服务器穿透,在服务器注册端口或域名,通过访问服务器端口或域名,访问内网服务(支持计划任务,定时定长自动开启关闭)
|
||||||
- [x] 权限管理,主客户端拥有完全权限,可导出、配置子客户端配置,分配其管理权限
|
- [x] 权限管理,主客户端拥有完全权限,可导出、配置子客户端配置,分配其管理权限
|
||||||
- [x] 自定义验证,通过`HTTP POST`让你可以自定义认证是否允许`连接信标`,`中继`,`内网穿透`
|
- [x] 自定义验证,通过`HTTP POST`让你可以自定义认证是否允许`连接信标`,`中继`,`内网穿透`
|
||||||
- [x] 流量统计,统计服务器`信标`、`中继`、`内网穿透` 的流量情况
|
- [x] 流量统计,统计服务器`信标`、`中继`、`内网穿透` 的流量情况
|
||||||
|
@@ -26,9 +26,9 @@ namespace linker.messenger.entry
|
|||||||
{
|
{
|
||||||
private static ServiceCollection serviceCollection;
|
private static ServiceCollection serviceCollection;
|
||||||
private static ServiceProvider serviceProvider;
|
private static ServiceProvider serviceProvider;
|
||||||
private static OperatingManager inited = new OperatingManager();
|
private static readonly OperatingManager inited = new OperatingManager();
|
||||||
private static OperatingManager builded = new OperatingManager();
|
private static readonly OperatingManager builded = new OperatingManager();
|
||||||
private static OperatingManager setuped = new OperatingManager();
|
private static readonly OperatingManager setuped = new OperatingManager();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 开始初始化
|
/// 开始初始化
|
||||||
@@ -90,7 +90,7 @@ namespace linker.messenger.entry
|
|||||||
.AddSerializerMemoryPack()
|
.AddSerializerMemoryPack()
|
||||||
|
|
||||||
//计划任务
|
//计划任务
|
||||||
.AddPlan();
|
.AddPlanClient().AddPlanServer();
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 注入
|
/// 注入
|
||||||
@@ -145,7 +145,7 @@ namespace linker.messenger.entry
|
|||||||
if (modules.HasFlag(ExcludeModule.Logger) == false)
|
if (modules.HasFlag(ExcludeModule.Logger) == false)
|
||||||
serviceProvider.UseLogger();
|
serviceProvider.UseLogger();
|
||||||
|
|
||||||
serviceProvider.UseMessenger().UsePlan();
|
serviceProvider.UseMessenger();
|
||||||
|
|
||||||
if ((modules & ExcludeModule.StoreFile) != ExcludeModule.StoreFile)
|
if ((modules & ExcludeModule.StoreFile) != ExcludeModule.StoreFile)
|
||||||
serviceProvider.UseStoreFile(configDic);
|
serviceProvider.UseStoreFile(configDic);
|
||||||
@@ -171,6 +171,8 @@ namespace linker.messenger.entry
|
|||||||
.UseSignInServer().UseSyncServer().UseTunnelServer().UseFlowServer();
|
.UseSignInServer().UseSyncServer().UseTunnelServer().UseFlowServer();
|
||||||
|
|
||||||
serviceProvider.UseListen();
|
serviceProvider.UseListen();
|
||||||
|
|
||||||
|
serviceProvider.UsePlanServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((commonStore.Modes & CommonModes.Client) == CommonModes.Client)
|
if ((commonStore.Modes & CommonModes.Client) == CommonModes.Client)
|
||||||
@@ -193,6 +195,8 @@ namespace linker.messenger.entry
|
|||||||
serviceProvider.UseExRoute().UseAccessClient().UseDecenterClient().UsePcpClient().UseRelayClient().UseSyncClient().UseTunnelClient().UseFlowClient();
|
serviceProvider.UseExRoute().UseAccessClient().UseDecenterClient().UsePcpClient().UseRelayClient().UseSyncClient().UseTunnelClient().UseFlowClient();
|
||||||
|
|
||||||
serviceProvider.UseSignInClient();
|
serviceProvider.UseSignInClient();
|
||||||
|
|
||||||
|
serviceProvider.UsePlanClient();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,19 +1,41 @@
|
|||||||
|
|
||||||
|
using linker.messenger.api;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace linker.messenger.plan
|
namespace linker.messenger.plan
|
||||||
{
|
{
|
||||||
public static class Entry
|
public static class Entry
|
||||||
{
|
{
|
||||||
public static ServiceCollection AddPlan(this ServiceCollection serviceCollection)
|
public static ServiceCollection AddPlanClient(this ServiceCollection serviceCollection)
|
||||||
{
|
{
|
||||||
serviceCollection.AddSingleton<PlanTransfer>();
|
serviceCollection.AddSingleton<PlanTransfer>();
|
||||||
|
serviceCollection.AddSingleton<PlanApiController>();
|
||||||
|
serviceCollection.AddSingleton<PlanClientMessenger>();
|
||||||
|
|
||||||
return serviceCollection;
|
return serviceCollection;
|
||||||
}
|
}
|
||||||
public static ServiceProvider UsePlan(this ServiceProvider serviceProvider)
|
public static ServiceProvider UsePlanClient(this ServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
PlanTransfer planTransfer = serviceProvider.GetService<PlanTransfer>();
|
PlanTransfer planTransfer = serviceProvider.GetService<PlanTransfer>();
|
||||||
|
|
||||||
|
MessengerResolver messengerResolver = serviceProvider.GetService<MessengerResolver>();
|
||||||
|
messengerResolver.AddMessenger(new List<IMessenger> { serviceProvider.GetService<PlanClientMessenger>() });
|
||||||
|
|
||||||
|
IApiServer apiServer = serviceProvider.GetService<IApiServer>();
|
||||||
|
apiServer.AddPlugins(new List<libs.api.IApiController> { serviceProvider.GetService<PlanApiController>() });
|
||||||
|
|
||||||
|
return serviceProvider;
|
||||||
|
}
|
||||||
|
public static ServiceCollection AddPlanServer(this ServiceCollection serviceCollection)
|
||||||
|
{
|
||||||
|
serviceCollection.AddSingleton<PlanServerMessenger>();
|
||||||
|
|
||||||
|
return serviceCollection;
|
||||||
|
}
|
||||||
|
public static ServiceProvider UsePlanServer(this ServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
MessengerResolver messengerResolver = serviceProvider.GetService<MessengerResolver>();
|
||||||
|
messengerResolver.AddMessenger(new List<IMessenger> { serviceProvider.GetService<PlanClientMessenger>() });
|
||||||
return serviceProvider;
|
return serviceProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,10 +2,10 @@
|
|||||||
{
|
{
|
||||||
public interface IPlanStore
|
public interface IPlanStore
|
||||||
{
|
{
|
||||||
public bool Add(PlanStoreInfo info);
|
public bool Add(PlanInfo info);
|
||||||
public IEnumerable<PlanStoreInfo> Get();
|
public IEnumerable<PlanInfo> Get();
|
||||||
public IEnumerable<PlanStoreInfo> Get(string category);
|
public IEnumerable<PlanInfo> Get(string category);
|
||||||
public PlanStoreInfo Get(string category, string key);
|
public PlanInfo Get(string category, string key);
|
||||||
public bool Remove(int id);
|
public bool Remove(int id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
public Task HandleAsync(string handle, string key, string value);
|
public Task HandleAsync(string handle, string key, string value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class PlanStoreInfo
|
public sealed class PlanInfo
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
|
|
||||||
@@ -39,6 +39,22 @@
|
|||||||
public PlanMethod Method { get; set; }
|
public PlanMethod Method { get; set; }
|
||||||
public string Rule { get; set; }
|
public string Rule { get; set; }
|
||||||
}
|
}
|
||||||
|
public sealed class PlanGetInfo
|
||||||
|
{
|
||||||
|
public string MachineId { get; set; }
|
||||||
|
public string Category { get; set; }
|
||||||
|
public string Key { get; set; }
|
||||||
|
}
|
||||||
|
public sealed class PlanAddInfo
|
||||||
|
{
|
||||||
|
public string MachineId { get; set; }
|
||||||
|
public PlanInfo Plan { get; set; }
|
||||||
|
}
|
||||||
|
public sealed class PlanRemoveInfo
|
||||||
|
{
|
||||||
|
public string MachineId { get; set; }
|
||||||
|
public int PlanId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 计划任务方法
|
/// 计划任务方法
|
||||||
|
79
src/linker.messenger.plan/PlanApiController.cs
Normal file
79
src/linker.messenger.plan/PlanApiController.cs
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
using linker.libs;
|
||||||
|
using linker.libs.api;
|
||||||
|
using linker.libs.extends;
|
||||||
|
using linker.messenger.signin;
|
||||||
|
|
||||||
|
namespace linker.messenger.plan
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 中继管理接口
|
||||||
|
/// </summary>
|
||||||
|
public sealed class PlanApiController : IApiController
|
||||||
|
{
|
||||||
|
private readonly SignInClientState signInClientState;
|
||||||
|
private readonly IMessengerSender messengerSender;
|
||||||
|
private readonly ISerializer serializer;
|
||||||
|
private readonly ISignInClientStore signInClientStore;
|
||||||
|
private readonly PlanTransfer planTransfer;
|
||||||
|
|
||||||
|
public PlanApiController( SignInClientState signInClientState, IMessengerSender messengerSender, ISerializer serializer, ISignInClientStore signInClientStore, PlanTransfer planTransfer)
|
||||||
|
{
|
||||||
|
this.signInClientState = signInClientState;
|
||||||
|
this.messengerSender = messengerSender;
|
||||||
|
this.serializer = serializer;
|
||||||
|
this.signInClientStore = signInClientStore;
|
||||||
|
this.planTransfer = planTransfer;
|
||||||
|
}
|
||||||
|
public async Task<List<PlanInfo>> Get(ApiControllerParamsInfo param)
|
||||||
|
{
|
||||||
|
PlanGetInfo info = param.Content.DeJson<PlanGetInfo>();
|
||||||
|
if (info.MachineId == signInClientStore.Id)
|
||||||
|
{
|
||||||
|
return planTransfer.Get(info.Category).ToList();
|
||||||
|
}
|
||||||
|
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||||
|
{
|
||||||
|
Connection = signInClientState.Connection,
|
||||||
|
MessengerId = (ushort)PlanMessengerIds.GetForward,
|
||||||
|
Payload = serializer.Serialize(info)
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if(resp.Code == MessageResponeCodes.OK)
|
||||||
|
{
|
||||||
|
return serializer.Deserialize<List<PlanInfo>>(resp.Data.Span);
|
||||||
|
}
|
||||||
|
return new List<PlanInfo>();
|
||||||
|
}
|
||||||
|
public async Task<bool> Add(ApiControllerParamsInfo param)
|
||||||
|
{
|
||||||
|
PlanAddInfo info = param.Content.DeJson<PlanAddInfo>();
|
||||||
|
if (info.MachineId == signInClientStore.Id)
|
||||||
|
{
|
||||||
|
return planTransfer.Add(info.Plan);
|
||||||
|
}
|
||||||
|
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||||
|
{
|
||||||
|
Connection = signInClientState.Connection,
|
||||||
|
MessengerId = (ushort)PlanMessengerIds.AddForward,
|
||||||
|
Payload = serializer.Serialize(info)
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
return resp.Code == MessageResponeCodes.OK && resp.Data.Span.SequenceEqual(Helper.TrueArray);
|
||||||
|
}
|
||||||
|
public async Task<bool> Remove(ApiControllerParamsInfo param)
|
||||||
|
{
|
||||||
|
PlanRemoveInfo info = param.Content.DeJson<PlanRemoveInfo>();
|
||||||
|
if (info.MachineId == signInClientStore.Id)
|
||||||
|
{
|
||||||
|
return planTransfer.Remove(info.PlanId);
|
||||||
|
}
|
||||||
|
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||||
|
{
|
||||||
|
Connection = signInClientState.Connection,
|
||||||
|
MessengerId = (ushort)PlanMessengerIds.RemoveForward,
|
||||||
|
Payload = serializer.Serialize(info)
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
return resp.Code == MessageResponeCodes.OK && resp.Data.Span.SequenceEqual(Helper.TrueArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
151
src/linker.messenger.plan/PlanMessenger.cs
Normal file
151
src/linker.messenger.plan/PlanMessenger.cs
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
using linker.libs;
|
||||||
|
using linker.messenger.signin;
|
||||||
|
|
||||||
|
namespace linker.messenger.plan
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 计划任务客户端
|
||||||
|
/// </summary>
|
||||||
|
public class PlanClientMessenger : IMessenger
|
||||||
|
{
|
||||||
|
private readonly PlanTransfer planTransfer;
|
||||||
|
private readonly ISerializer serializer;
|
||||||
|
public PlanClientMessenger(PlanTransfer planTransfer, ISerializer serializer)
|
||||||
|
{
|
||||||
|
this.planTransfer = planTransfer;
|
||||||
|
this.serializer = serializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="connection"></param>
|
||||||
|
[MessengerId((ushort)PlanMessengerIds.Get)]
|
||||||
|
public void Get(IConnection connection)
|
||||||
|
{
|
||||||
|
PlanGetInfo info = serializer.Deserialize<PlanGetInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
|
List<PlanInfo> result = planTransfer.Get(info.Category).ToList();
|
||||||
|
connection.Write(serializer.Serialize(result));
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 添加
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="connection"></param>
|
||||||
|
[MessengerId((ushort)PlanMessengerIds.Add)]
|
||||||
|
public void AddClient(IConnection connection)
|
||||||
|
{
|
||||||
|
PlanAddInfo info = serializer.Deserialize<PlanAddInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
|
planTransfer.Add(info.Plan);
|
||||||
|
connection.Write(Helper.TrueArray);
|
||||||
|
}
|
||||||
|
// <summary>
|
||||||
|
/// 删除
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="connection"></param>
|
||||||
|
[MessengerId((ushort)PlanMessengerIds.Remove)]
|
||||||
|
public void RemoveClient(IConnection connection)
|
||||||
|
{
|
||||||
|
PlanRemoveInfo info = serializer.Deserialize<PlanRemoveInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
|
planTransfer.Remove(info.PlanId);
|
||||||
|
connection.Write(Helper.TrueArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 计划任务服务端
|
||||||
|
/// </summary>
|
||||||
|
public class PlanServerMessenger : IMessenger
|
||||||
|
{
|
||||||
|
private readonly IMessengerSender messengerSender;
|
||||||
|
private readonly SignInServerCaching signCaching;
|
||||||
|
private readonly ISerializer serializer;
|
||||||
|
|
||||||
|
public PlanServerMessenger(IMessengerSender messengerSender, SignInServerCaching signCaching, ISerializer serializer)
|
||||||
|
{
|
||||||
|
this.messengerSender = messengerSender;
|
||||||
|
this.signCaching = signCaching;
|
||||||
|
this.serializer = serializer;
|
||||||
|
}
|
||||||
|
[MessengerId((ushort)PlanMessengerIds.GetForward)]
|
||||||
|
public async Task GetForward(IConnection connection)
|
||||||
|
{
|
||||||
|
PlanGetInfo info = serializer.Deserialize<PlanGetInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
|
if (signCaching.TryGet(info.MachineId, out SignCacheInfo cacheTo) && signCaching.TryGet(connection.Id, out SignCacheInfo cacheFrom) && cacheFrom.GroupId == cacheTo.GroupId)
|
||||||
|
{
|
||||||
|
uint requestid = connection.ReceiveRequestWrap.RequestId;
|
||||||
|
await messengerSender.SendReply(new MessageRequestWrap
|
||||||
|
{
|
||||||
|
Connection = cacheTo.Connection,
|
||||||
|
MessengerId = (ushort)PlanMessengerIds.Get,
|
||||||
|
Payload = connection.ReceiveRequestWrap.Payload
|
||||||
|
}).ContinueWith(async (result) =>
|
||||||
|
{
|
||||||
|
if (result.Result.Code == MessageResponeCodes.OK)
|
||||||
|
{
|
||||||
|
await messengerSender.ReplyOnly(new MessageResponseWrap
|
||||||
|
{
|
||||||
|
Connection = connection,
|
||||||
|
Code = MessageResponeCodes.OK,
|
||||||
|
Payload = result.Result.Data,
|
||||||
|
RequestId = requestid
|
||||||
|
}, (ushort)PlanMessengerIds.GetForward).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[MessengerId((ushort)PlanMessengerIds.AddForward)]
|
||||||
|
public async Task AddForward(IConnection connection)
|
||||||
|
{
|
||||||
|
PlanAddInfo info = serializer.Deserialize<PlanAddInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
|
if (signCaching.TryGet(info.MachineId, out SignCacheInfo cacheTo) && signCaching.TryGet(connection.Id, out SignCacheInfo cacheFrom) && cacheFrom.GroupId == cacheTo.GroupId)
|
||||||
|
{
|
||||||
|
uint requestid = connection.ReceiveRequestWrap.RequestId;
|
||||||
|
await messengerSender.SendReply(new MessageRequestWrap
|
||||||
|
{
|
||||||
|
Connection = cacheTo.Connection,
|
||||||
|
MessengerId = (ushort)PlanMessengerIds.Add,
|
||||||
|
Payload = connection.ReceiveRequestWrap.Payload
|
||||||
|
}).ContinueWith(async (result) =>
|
||||||
|
{
|
||||||
|
if (result.Result.Code == MessageResponeCodes.OK)
|
||||||
|
{
|
||||||
|
await messengerSender.ReplyOnly(new MessageResponseWrap
|
||||||
|
{
|
||||||
|
Connection = connection,
|
||||||
|
Code = MessageResponeCodes.OK,
|
||||||
|
Payload = result.Result.Data,
|
||||||
|
RequestId = requestid
|
||||||
|
}, (ushort)PlanMessengerIds.AddForward).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[MessengerId((ushort)PlanMessengerIds.RemoveForward)]
|
||||||
|
public async Task RemoveForward(IConnection connection)
|
||||||
|
{
|
||||||
|
PlanRemoveInfo info = serializer.Deserialize<PlanRemoveInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
|
if (signCaching.TryGet(info.MachineId, out SignCacheInfo cacheTo) && signCaching.TryGet(connection.Id, out SignCacheInfo cacheFrom) && cacheFrom.GroupId == cacheTo.GroupId)
|
||||||
|
{
|
||||||
|
uint requestid = connection.ReceiveRequestWrap.RequestId;
|
||||||
|
await messengerSender.SendReply(new MessageRequestWrap
|
||||||
|
{
|
||||||
|
Connection = cacheTo.Connection,
|
||||||
|
MessengerId = (ushort)PlanMessengerIds.Remove,
|
||||||
|
Payload = connection.ReceiveRequestWrap.Payload
|
||||||
|
}).ContinueWith(async (result) =>
|
||||||
|
{
|
||||||
|
if (result.Result.Code == MessageResponeCodes.OK)
|
||||||
|
{
|
||||||
|
await messengerSender.ReplyOnly(new MessageResponseWrap
|
||||||
|
{
|
||||||
|
Connection = connection,
|
||||||
|
Code = MessageResponeCodes.OK,
|
||||||
|
Payload = result.Result.Data,
|
||||||
|
RequestId = requestid
|
||||||
|
}, (ushort)PlanMessengerIds.RemoveForward).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
src/linker.messenger.plan/PlanMessengerIds.cs
Normal file
18
src/linker.messenger.plan/PlanMessengerIds.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
namespace linker.messenger.plan
|
||||||
|
{
|
||||||
|
public enum PlanMessengerIds : ushort
|
||||||
|
{
|
||||||
|
Min = 3000,
|
||||||
|
|
||||||
|
Add = 3001,
|
||||||
|
AddForward = 3002,
|
||||||
|
|
||||||
|
Remove = 3003,
|
||||||
|
RemoveForward = 3004,
|
||||||
|
|
||||||
|
Get = 3005,
|
||||||
|
GetForward = 3006,
|
||||||
|
|
||||||
|
Max = 3099
|
||||||
|
}
|
||||||
|
}
|
@@ -27,16 +27,16 @@ namespace linker.messenger.plan
|
|||||||
handles.AddOrUpdate(handle.CategoryName, handle, (a, b) => handle);
|
handles.AddOrUpdate(handle.CategoryName, handle, (a, b) => handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<PlanStoreInfo> Get(string category)
|
public IEnumerable<PlanInfo> Get(string category)
|
||||||
{
|
{
|
||||||
return planStore.Get(category);
|
return planStore.Get(category);
|
||||||
}
|
}
|
||||||
public bool Add(PlanStoreInfo info)
|
public bool Add(PlanInfo info)
|
||||||
{
|
{
|
||||||
bool result = planStore.Add(info);
|
bool result = planStore.Add(info);
|
||||||
|
|
||||||
caches.TryRemove(info.Id, out _);
|
caches.TryRemove(info.Id, out _);
|
||||||
PlanExecCacheInfo cache = new PlanExecCacheInfo { Store = info };
|
PlanExecCacheInfo cache = new PlanExecCacheInfo { Plan = info };
|
||||||
cache.Active = UpdateNextTime(cache) && string.IsNullOrWhiteSpace(info.TriggerHandle);
|
cache.Active = UpdateNextTime(cache) && string.IsNullOrWhiteSpace(info.TriggerHandle);
|
||||||
caches.TryAdd(info.Id, cache);
|
caches.TryAdd(info.Id, cache);
|
||||||
return result;
|
return result;
|
||||||
@@ -56,12 +56,12 @@ namespace linker.messenger.plan
|
|||||||
}
|
}
|
||||||
private void Load()
|
private void Load()
|
||||||
{
|
{
|
||||||
foreach (PlanStoreInfo info in planStore.Get())
|
foreach (PlanInfo info in planStore.Get())
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
PlanExecCacheInfo cache = new PlanExecCacheInfo { Store = info };
|
PlanExecCacheInfo cache = new PlanExecCacheInfo { Plan = info };
|
||||||
cache.Active = (cache.Store.Method < PlanMethod.At) || (UpdateNextTime(cache) && cache.Store.Method != PlanMethod.Trigger);
|
cache.Active = (cache.Plan.Method < PlanMethod.At) || (UpdateNextTime(cache) && cache.Plan.Method != PlanMethod.Trigger);
|
||||||
caches.TryAdd(info.Id, cache);
|
caches.TryAdd(info.Id, cache);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
@@ -71,33 +71,33 @@ namespace linker.messenger.plan
|
|||||||
}
|
}
|
||||||
private void RunSetup()
|
private void RunSetup()
|
||||||
{
|
{
|
||||||
foreach (PlanExecCacheInfo item in caches.Values.Where(c => c.Store.Method == PlanMethod.Setup && c.Store.Disabled == false && c.Running == false))
|
foreach (PlanExecCacheInfo item in caches.Values.Where(c => c.Plan.Method == PlanMethod.Setup && c.Plan.Disabled == false && c.Running == false))
|
||||||
{
|
{
|
||||||
Run(item);
|
Run(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void RunLoop()
|
private void RunLoop()
|
||||||
{
|
{
|
||||||
foreach (PlanExecCacheInfo item in caches.Values.Where(c => c.NextTime <= DateTime.Now && c.Store.Method >= PlanMethod.At))
|
foreach (PlanExecCacheInfo item in caches.Values.Where(c => c.NextTime <= DateTime.Now && c.Plan.Method >= PlanMethod.At))
|
||||||
{
|
{
|
||||||
Run(item);
|
Run(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void Run(PlanExecCacheInfo item)
|
private void Run(PlanExecCacheInfo item)
|
||||||
{
|
{
|
||||||
if(item.Store.Disabled || item.Active == false || item.Running || handles.TryGetValue(item.Store.Category, out IPlanHandle handle) == false)
|
if(item.Plan.Disabled || item.Active == false || item.Running || handles.TryGetValue(item.Plan.Category, out IPlanHandle handle) == false)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
item.Running = true;
|
item.Running = true;
|
||||||
item.Active = (item.Store.Method < PlanMethod.At) || (UpdateNextTime(item) && item.Store.Method != PlanMethod.Trigger);
|
item.Active = (item.Plan.Method < PlanMethod.At) || (UpdateNextTime(item) && item.Plan.Method != PlanMethod.Trigger);
|
||||||
item.LastTime = DateTime.Now;
|
item.LastTime = DateTime.Now;
|
||||||
|
|
||||||
handle.HandleAsync(item.Store.Handle, item.Store.Key, item.Store.Value).ContinueWith((result) =>
|
handle.HandleAsync(item.Plan.Handle, item.Plan.Key, item.Plan.Value).ContinueWith((result) =>
|
||||||
{
|
{
|
||||||
item.Running = false;
|
item.Running = false;
|
||||||
PlanExecCacheInfo trigger = caches.Values.FirstOrDefault(c => c.Store.Category == item.Store.Category && c.Store.Key == item.Store.Key && c.Store.TriggerHandle == item.Store.Handle && c.Store.TriggerHandle != c.Store.Handle && c.Store.Method == PlanMethod.Trigger);
|
PlanExecCacheInfo trigger = caches.Values.FirstOrDefault(c => c.Plan.Category == item.Plan.Category && c.Plan.Key == item.Plan.Key && c.Plan.TriggerHandle == item.Plan.Handle && c.Plan.TriggerHandle != c.Plan.Handle && c.Plan.Method == PlanMethod.Trigger);
|
||||||
if (trigger != null)
|
if (trigger != null)
|
||||||
{
|
{
|
||||||
trigger.Active = UpdateNextTime(trigger);
|
trigger.Active = UpdateNextTime(trigger);
|
||||||
@@ -109,19 +109,19 @@ namespace linker.messenger.plan
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (cache.Store.Method == PlanMethod.At)
|
if (cache.Plan.Method == PlanMethod.At)
|
||||||
{
|
{
|
||||||
return NextTimeAt(cache);
|
return NextTimeAt(cache);
|
||||||
}
|
}
|
||||||
else if (cache.Store.Method == PlanMethod.Timer)
|
else if (cache.Plan.Method == PlanMethod.Timer)
|
||||||
{
|
{
|
||||||
return NextTimeTimer(cache);
|
return NextTimeTimer(cache);
|
||||||
}
|
}
|
||||||
else if (cache.Store.Method == PlanMethod.Cron)
|
else if (cache.Plan.Method == PlanMethod.Cron)
|
||||||
{
|
{
|
||||||
return NextTimeCorn(cache);
|
return NextTimeCorn(cache);
|
||||||
}
|
}
|
||||||
else if (cache.Store.Method == PlanMethod.Trigger)
|
else if (cache.Plan.Method == PlanMethod.Trigger)
|
||||||
{
|
{
|
||||||
return NextTimeAfter(cache);
|
return NextTimeAfter(cache);
|
||||||
}
|
}
|
||||||
@@ -136,7 +136,7 @@ namespace linker.messenger.plan
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
CronExpression cron = CronExpression.Parse(cache.Store.Rule, CronFormat.IncludeSeconds);
|
CronExpression cron = CronExpression.Parse(cache.Plan.Rule, CronFormat.IncludeSeconds);
|
||||||
DateTimeOffset? nextOccurrence = cron.GetNextOccurrence(DateTimeOffset.Now, TimeZoneInfo.Local);
|
DateTimeOffset? nextOccurrence = cron.GetNextOccurrence(DateTimeOffset.Now, TimeZoneInfo.Local);
|
||||||
if (nextOccurrence.HasValue)
|
if (nextOccurrence.HasValue)
|
||||||
{
|
{
|
||||||
@@ -153,15 +153,15 @@ namespace linker.messenger.plan
|
|||||||
}
|
}
|
||||||
private bool NextTimeAt(PlanExecCacheInfo cache)
|
private bool NextTimeAt(PlanExecCacheInfo cache)
|
||||||
{
|
{
|
||||||
if (Regex.IsMatch(cache.Store.Rule, regex) == false)
|
if (Regex.IsMatch(cache.Plan.Rule, regex) == false)
|
||||||
{
|
{
|
||||||
cache.Error = $"{cache.Store.Rule} format error";
|
cache.Error = $"{cache.Plan.Rule} format error";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DateTime from = DateTime.Now;
|
DateTime from = DateTime.Now;
|
||||||
|
|
||||||
GroupCollection groups = Regex.Match(cache.Store.Rule, regex).Groups;
|
GroupCollection groups = Regex.Match(cache.Plan.Rule, regex).Groups;
|
||||||
int year = groups[1].Value == "?" ? from.Year : int.Parse(groups[1].Value);
|
int year = groups[1].Value == "?" ? from.Year : int.Parse(groups[1].Value);
|
||||||
int month = groups[2].Value == "?" ? from.Month : int.Parse(groups[2].Value);
|
int month = groups[2].Value == "?" ? from.Month : int.Parse(groups[2].Value);
|
||||||
int day = groups[3].Value == "?" ? from.Day : int.Parse(groups[3].Value);
|
int day = groups[3].Value == "?" ? from.Day : int.Parse(groups[3].Value);
|
||||||
@@ -183,13 +183,13 @@ namespace linker.messenger.plan
|
|||||||
}
|
}
|
||||||
private bool NextTimeTimer(PlanExecCacheInfo cache)
|
private bool NextTimeTimer(PlanExecCacheInfo cache)
|
||||||
{
|
{
|
||||||
if (Regex.IsMatch(cache.Store.Rule, regex) == false)
|
if (Regex.IsMatch(cache.Plan.Rule, regex) == false)
|
||||||
{
|
{
|
||||||
cache.Error = $"{cache.Store.Rule} format error";
|
cache.Error = $"{cache.Plan.Rule} format error";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupCollection groups = Regex.Match(cache.Store.Rule, regex).Groups;
|
GroupCollection groups = Regex.Match(cache.Plan.Rule, regex).Groups;
|
||||||
int year = groups[1].Value == "?" ? 0 : int.Parse(groups[1].Value);
|
int year = groups[1].Value == "?" ? 0 : int.Parse(groups[1].Value);
|
||||||
int month = groups[2].Value == "?" ? 0 : int.Parse(groups[2].Value);
|
int month = groups[2].Value == "?" ? 0 : int.Parse(groups[2].Value);
|
||||||
int day = groups[3].Value == "?" ? 0 : int.Parse(groups[3].Value);
|
int day = groups[3].Value == "?" ? 0 : int.Parse(groups[3].Value);
|
||||||
@@ -202,13 +202,13 @@ namespace linker.messenger.plan
|
|||||||
}
|
}
|
||||||
private bool NextTimeAfter(PlanExecCacheInfo cache)
|
private bool NextTimeAfter(PlanExecCacheInfo cache)
|
||||||
{
|
{
|
||||||
if (Regex.IsMatch(cache.Store.Rule, regex) == false)
|
if (Regex.IsMatch(cache.Plan.Rule, regex) == false)
|
||||||
{
|
{
|
||||||
cache.Error = $"{cache.Store.Rule} format error";
|
cache.Error = $"{cache.Plan.Rule} format error";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupCollection groups = Regex.Match(cache.Store.Rule, regex).Groups;
|
GroupCollection groups = Regex.Match(cache.Plan.Rule, regex).Groups;
|
||||||
int year = groups[1].Value == "?" ? 0 : int.Parse(groups[1].Value);
|
int year = groups[1].Value == "?" ? 0 : int.Parse(groups[1].Value);
|
||||||
int month = groups[2].Value == "?" ? 0 : int.Parse(groups[2].Value);
|
int month = groups[2].Value == "?" ? 0 : int.Parse(groups[2].Value);
|
||||||
int day = groups[3].Value == "?" ? 0 : int.Parse(groups[3].Value);
|
int day = groups[3].Value == "?" ? 0 : int.Parse(groups[3].Value);
|
||||||
@@ -224,7 +224,7 @@ namespace linker.messenger.plan
|
|||||||
|
|
||||||
public sealed class PlanExecCacheInfo
|
public sealed class PlanExecCacheInfo
|
||||||
{
|
{
|
||||||
public PlanStoreInfo Store { get; set; }
|
public PlanInfo Plan { get; set; }
|
||||||
public DateTime LastTime { get; set; }
|
public DateTime LastTime { get; set; }
|
||||||
public DateTime NextTime { get; set; }
|
public DateTime NextTime { get; set; }
|
||||||
|
|
||||||
|
@@ -127,6 +127,12 @@ namespace linker.messenger.serializer.memorypack
|
|||||||
MemoryPackFormatterProvider.Register(new TuntapLanInfoFormatter());
|
MemoryPackFormatterProvider.Register(new TuntapLanInfoFormatter());
|
||||||
MemoryPackFormatterProvider.Register(new LeaseInfoFormatter());
|
MemoryPackFormatterProvider.Register(new LeaseInfoFormatter());
|
||||||
|
|
||||||
|
|
||||||
|
MemoryPackFormatterProvider.Register(new PlanInfoFormatter());
|
||||||
|
MemoryPackFormatterProvider.Register(new PlanGetInfoFormatter());
|
||||||
|
MemoryPackFormatterProvider.Register(new PlanAddInfoFormatter());
|
||||||
|
MemoryPackFormatterProvider.Register(new PlanRemoveInfoFormatter());
|
||||||
|
|
||||||
return serviceCollection;
|
return serviceCollection;
|
||||||
}
|
}
|
||||||
public static ServiceProvider UseSerializerMemoryPack(this ServiceProvider serviceProvider)
|
public static ServiceProvider UseSerializerMemoryPack(this ServiceProvider serviceProvider)
|
||||||
|
251
src/linker.messenger.serializer.memorypack/PlanSerializer.cs
Normal file
251
src/linker.messenger.serializer.memorypack/PlanSerializer.cs
Normal file
@@ -0,0 +1,251 @@
|
|||||||
|
using linker.messenger.plan;
|
||||||
|
using MemoryPack;
|
||||||
|
|
||||||
|
namespace linker.messenger.serializer.memorypack
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
[MemoryPackable]
|
||||||
|
public readonly partial struct SerializablePlanInfo
|
||||||
|
{
|
||||||
|
[MemoryPackIgnore]
|
||||||
|
public readonly PlanInfo info;
|
||||||
|
|
||||||
|
[MemoryPackInclude]
|
||||||
|
int Id => info.Id;
|
||||||
|
|
||||||
|
[MemoryPackInclude]
|
||||||
|
string Category => info.Category;
|
||||||
|
[MemoryPackInclude]
|
||||||
|
string Key => info.Key;
|
||||||
|
[MemoryPackInclude]
|
||||||
|
string Handle => info.Handle;
|
||||||
|
[MemoryPackInclude]
|
||||||
|
string Value => info.Value;
|
||||||
|
[MemoryPackInclude]
|
||||||
|
bool Disabled => info.Disabled;
|
||||||
|
[MemoryPackInclude]
|
||||||
|
string TriggerHandle => info.TriggerHandle;
|
||||||
|
[MemoryPackInclude]
|
||||||
|
PlanMethod Method => info.Method;
|
||||||
|
[MemoryPackInclude]
|
||||||
|
string Rule => info.Rule;
|
||||||
|
|
||||||
|
[MemoryPackConstructor]
|
||||||
|
SerializablePlanInfo(int id, string category, string key, string handle, string value, bool disabled, string triggerHandle, PlanMethod method, string rule)
|
||||||
|
{
|
||||||
|
var info = new PlanInfo
|
||||||
|
{
|
||||||
|
Id = id,
|
||||||
|
Category = category,
|
||||||
|
Key = key,
|
||||||
|
Handle = handle,
|
||||||
|
Value = value,
|
||||||
|
Disabled = disabled,
|
||||||
|
TriggerHandle = triggerHandle,
|
||||||
|
Method = method,
|
||||||
|
Rule = rule
|
||||||
|
};
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SerializablePlanInfo(PlanInfo info)
|
||||||
|
{
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class PlanInfoFormatter : MemoryPackFormatter<PlanInfo>
|
||||||
|
{
|
||||||
|
public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref PlanInfo value)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
writer.WriteNullObjectHeader();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WritePackable(new SerializablePlanInfo(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Deserialize(ref MemoryPackReader reader, scoped ref PlanInfo value)
|
||||||
|
{
|
||||||
|
if (reader.PeekIsNull())
|
||||||
|
{
|
||||||
|
reader.Advance(1); // skip null block
|
||||||
|
value = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var wrapped = reader.ReadPackable<SerializablePlanInfo>();
|
||||||
|
value = wrapped.info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[MemoryPackable]
|
||||||
|
public readonly partial struct SerializablePlanGetInfo
|
||||||
|
{
|
||||||
|
[MemoryPackIgnore]
|
||||||
|
public readonly PlanGetInfo info;
|
||||||
|
|
||||||
|
[MemoryPackInclude]
|
||||||
|
string MachineId => info.MachineId;
|
||||||
|
[MemoryPackInclude]
|
||||||
|
string Category => info.Category;
|
||||||
|
[MemoryPackInclude]
|
||||||
|
string Key => info.Key;
|
||||||
|
|
||||||
|
[MemoryPackConstructor]
|
||||||
|
SerializablePlanGetInfo(string machineId, string category, string key)
|
||||||
|
{
|
||||||
|
var info = new PlanGetInfo
|
||||||
|
{
|
||||||
|
MachineId = machineId,
|
||||||
|
Category = category,
|
||||||
|
Key = key
|
||||||
|
};
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SerializablePlanGetInfo(PlanGetInfo info)
|
||||||
|
{
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class PlanGetInfoFormatter : MemoryPackFormatter<PlanGetInfo>
|
||||||
|
{
|
||||||
|
public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref PlanGetInfo value)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
writer.WriteNullObjectHeader();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WritePackable(new SerializablePlanGetInfo(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Deserialize(ref MemoryPackReader reader, scoped ref PlanGetInfo value)
|
||||||
|
{
|
||||||
|
if (reader.PeekIsNull())
|
||||||
|
{
|
||||||
|
reader.Advance(1); // skip null block
|
||||||
|
value = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var wrapped = reader.ReadPackable<SerializablePlanGetInfo>();
|
||||||
|
value = wrapped.info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[MemoryPackable]
|
||||||
|
public readonly partial struct SerializablePlanAddInfo
|
||||||
|
{
|
||||||
|
[MemoryPackIgnore]
|
||||||
|
public readonly PlanAddInfo info;
|
||||||
|
|
||||||
|
[MemoryPackInclude]
|
||||||
|
string MachineId => info.MachineId;
|
||||||
|
[MemoryPackInclude, MemoryPackAllowSerialize]
|
||||||
|
PlanInfo Plan => info.Plan;
|
||||||
|
|
||||||
|
[MemoryPackConstructor]
|
||||||
|
SerializablePlanAddInfo(string machineId, PlanInfo plan)
|
||||||
|
{
|
||||||
|
var info = new PlanAddInfo
|
||||||
|
{
|
||||||
|
MachineId = machineId,
|
||||||
|
Plan = plan
|
||||||
|
};
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SerializablePlanAddInfo(PlanAddInfo info)
|
||||||
|
{
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class PlanAddInfoFormatter : MemoryPackFormatter<PlanAddInfo>
|
||||||
|
{
|
||||||
|
public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref PlanAddInfo value)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
writer.WriteNullObjectHeader();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WritePackable(new SerializablePlanAddInfo(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Deserialize(ref MemoryPackReader reader, scoped ref PlanAddInfo value)
|
||||||
|
{
|
||||||
|
if (reader.PeekIsNull())
|
||||||
|
{
|
||||||
|
reader.Advance(1); // skip null block
|
||||||
|
value = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var wrapped = reader.ReadPackable<SerializablePlanAddInfo>();
|
||||||
|
value = wrapped.info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[MemoryPackable]
|
||||||
|
public readonly partial struct SerializablePlanRemoveInfo
|
||||||
|
{
|
||||||
|
[MemoryPackIgnore]
|
||||||
|
public readonly PlanRemoveInfo info;
|
||||||
|
|
||||||
|
[MemoryPackInclude]
|
||||||
|
string MachineId => info.MachineId;
|
||||||
|
[MemoryPackInclude, MemoryPackAllowSerialize]
|
||||||
|
int PlanId => info.PlanId;
|
||||||
|
|
||||||
|
[MemoryPackConstructor]
|
||||||
|
SerializablePlanRemoveInfo(string machineId, int planid)
|
||||||
|
{
|
||||||
|
var info = new PlanRemoveInfo
|
||||||
|
{
|
||||||
|
MachineId = machineId,
|
||||||
|
PlanId = planid
|
||||||
|
};
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SerializablePlanRemoveInfo(PlanRemoveInfo info)
|
||||||
|
{
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class PlanRemoveInfoFormatter : MemoryPackFormatter<PlanRemoveInfo>
|
||||||
|
{
|
||||||
|
public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref PlanRemoveInfo value)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
writer.WriteNullObjectHeader();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WritePackable(new SerializablePlanRemoveInfo(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Deserialize(ref MemoryPackReader reader, scoped ref PlanRemoveInfo value)
|
||||||
|
{
|
||||||
|
if (reader.PeekIsNull())
|
||||||
|
{
|
||||||
|
reader.Advance(1); // skip null block
|
||||||
|
value = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var wrapped = reader.ReadPackable<SerializablePlanRemoveInfo>();
|
||||||
|
value = wrapped.info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -115,12 +115,13 @@ namespace linker.messenger.sforward.client
|
|||||||
return forwardTransfer.Add(info.Data);
|
return forwardTransfer.Add(info.Data);
|
||||||
}
|
}
|
||||||
if (accessStore.HasAccess(AccessValue.ForwardOther) == false) return false;
|
if (accessStore.HasAccess(AccessValue.ForwardOther) == false) return false;
|
||||||
return await messengerSender.SendOnly(new MessageRequestWrap
|
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||||
{
|
{
|
||||||
Connection = signInClientState.Connection,
|
Connection = signInClientState.Connection,
|
||||||
MessengerId = (ushort)SForwardMessengerIds.AddClientForward,
|
MessengerId = (ushort)SForwardMessengerIds.AddClientForward,
|
||||||
Payload = serializer.Serialize(info)
|
Payload = serializer.Serialize(info)
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
|
return resp.Code == MessageResponeCodes.OK && resp.Data.Span.SequenceEqual(Helper.TrueArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -137,12 +138,13 @@ namespace linker.messenger.sforward.client
|
|||||||
return forwardTransfer.Remove(info.Id);
|
return forwardTransfer.Remove(info.Id);
|
||||||
}
|
}
|
||||||
if (accessStore.HasAccess(AccessValue.ForwardOther) == false) return false;
|
if (accessStore.HasAccess(AccessValue.ForwardOther) == false) return false;
|
||||||
return await messengerSender.SendOnly(new MessageRequestWrap
|
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||||
{
|
{
|
||||||
Connection = signInClientState.Connection,
|
Connection = signInClientState.Connection,
|
||||||
MessengerId = (ushort)SForwardMessengerIds.RemoveClientForward,
|
MessengerId = (ushort)SForwardMessengerIds.RemoveClientForward,
|
||||||
Payload = serializer.Serialize(info)
|
Payload = serializer.Serialize(info)
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
|
return resp.Code == MessageResponeCodes.OK && resp.Data.Span.SequenceEqual(Helper.TrueArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@@ -30,6 +30,22 @@ namespace linker.messenger.sforward.client
|
|||||||
this.serializer = serializer;
|
this.serializer = serializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Start(int id)
|
||||||
|
{
|
||||||
|
SForwardInfo forwardInfo = sForwardClientStore.Get(id);
|
||||||
|
if(forwardInfo != null)
|
||||||
|
{
|
||||||
|
Start(forwardInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void Stop(int id)
|
||||||
|
{
|
||||||
|
SForwardInfo forwardInfo = sForwardClientStore.Get(id);
|
||||||
|
if (forwardInfo != null)
|
||||||
|
{
|
||||||
|
Stop(forwardInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
private void Start()
|
private void Start()
|
||||||
{
|
{
|
||||||
foreach (var item in sForwardClientStore.Get())
|
foreach (var item in sForwardClientStore.Get())
|
||||||
@@ -70,7 +86,7 @@ namespace linker.messenger.sforward.client
|
|||||||
forwardInfo.BufferSize = sForwardAddResultInfo.BufferSize;
|
forwardInfo.BufferSize = sForwardAddResultInfo.BufferSize;
|
||||||
if (sForwardAddResultInfo.Success)
|
if (sForwardAddResultInfo.Success)
|
||||||
{
|
{
|
||||||
sForwardClientStore.Update(forwardInfo.Id, forwardInfo.Started,true, string.Empty);
|
sForwardClientStore.Update(forwardInfo.Id, forwardInfo.Started, true, string.Empty);
|
||||||
LoggerHelper.Instance.Debug(sForwardAddResultInfo.Message);
|
LoggerHelper.Instance.Debug(sForwardAddResultInfo.Message);
|
||||||
OnOpen(forwardInfo.Id);
|
OnOpen(forwardInfo.Id);
|
||||||
}
|
}
|
||||||
@@ -117,7 +133,7 @@ namespace linker.messenger.sforward.client
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sForwardClientStore.Update(forwardInfo.Id, true, forwardInfo.Proxy, string.Empty);
|
sForwardClientStore.Update(forwardInfo.Id, forwardInfo.Started, forwardInfo.Proxy, string.Empty);
|
||||||
LoggerHelper.Instance.Error(sForwardAddResultInfo.Message);
|
LoggerHelper.Instance.Error(sForwardAddResultInfo.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -7,12 +7,27 @@ namespace linker.messenger.sforward.client
|
|||||||
public string CategoryName => "sforward";
|
public string CategoryName => "sforward";
|
||||||
|
|
||||||
|
|
||||||
public SForwardPlanHandle()
|
private readonly SForwardClientTransfer sForwardClientTransfer;
|
||||||
|
public SForwardPlanHandle(SForwardClientTransfer sForwardClientTransfer)
|
||||||
{
|
{
|
||||||
|
this.sForwardClientTransfer = sForwardClientTransfer;
|
||||||
}
|
}
|
||||||
public async Task HandleAsync(string handle, string key, string value)
|
public async Task HandleAsync(string handle, string key, string value)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"[{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}] exec plan {CategoryName} {handle} {key}->{value}");
|
if (int.TryParse(key, out int id) == false) return;
|
||||||
|
|
||||||
|
switch (handle)
|
||||||
|
{
|
||||||
|
case "start":
|
||||||
|
sForwardClientTransfer.Start(id);
|
||||||
|
break;
|
||||||
|
case "stop":
|
||||||
|
sForwardClientTransfer.Stop(id);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
await Task.CompletedTask;
|
await Task.CompletedTask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -237,7 +237,7 @@ namespace linker.plugins.sforward.messenger
|
|||||||
RequestId = requestid
|
RequestId = requestid
|
||||||
}, (ushort)SForwardMessengerIds.GetForward).ConfigureAwait(false);
|
}, (ushort)SForwardMessengerIds.GetForward).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
});
|
}).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -251,11 +251,23 @@ namespace linker.plugins.sforward.messenger
|
|||||||
if (signCaching.TryGet(info.MachineId, out SignCacheInfo cacheTo) && signCaching.TryGet(connection.Id, out SignCacheInfo cacheFrom) && cacheFrom.GroupId == cacheTo.GroupId)
|
if (signCaching.TryGet(info.MachineId, out SignCacheInfo cacheTo) && signCaching.TryGet(connection.Id, out SignCacheInfo cacheFrom) && cacheFrom.GroupId == cacheTo.GroupId)
|
||||||
{
|
{
|
||||||
uint requestid = connection.ReceiveRequestWrap.RequestId;
|
uint requestid = connection.ReceiveRequestWrap.RequestId;
|
||||||
await sender.SendOnly(new MessageRequestWrap
|
await sender.SendReply(new MessageRequestWrap
|
||||||
{
|
{
|
||||||
Connection = cacheTo.Connection,
|
Connection = cacheTo.Connection,
|
||||||
MessengerId = (ushort)SForwardMessengerIds.AddClient,
|
MessengerId = (ushort)SForwardMessengerIds.AddClient,
|
||||||
Payload = serializer.Serialize(info.Data)
|
Payload = serializer.Serialize(info.Data)
|
||||||
|
}).ContinueWith(async (result) =>
|
||||||
|
{
|
||||||
|
if (result.Result.Code == MessageResponeCodes.OK)
|
||||||
|
{
|
||||||
|
await sender.ReplyOnly(new MessageResponseWrap
|
||||||
|
{
|
||||||
|
Connection = connection,
|
||||||
|
Code = MessageResponeCodes.OK,
|
||||||
|
Payload = result.Result.Data,
|
||||||
|
RequestId = requestid
|
||||||
|
}, (ushort)SForwardMessengerIds.AddClientForward).ConfigureAwait(false);
|
||||||
|
}
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -270,11 +282,23 @@ namespace linker.plugins.sforward.messenger
|
|||||||
if (signCaching.TryGet(info.MachineId, out SignCacheInfo cacheTo) && signCaching.TryGet(connection.Id, out SignCacheInfo cacheFrom) && cacheFrom.GroupId == cacheTo.GroupId)
|
if (signCaching.TryGet(info.MachineId, out SignCacheInfo cacheTo) && signCaching.TryGet(connection.Id, out SignCacheInfo cacheFrom) && cacheFrom.GroupId == cacheTo.GroupId)
|
||||||
{
|
{
|
||||||
uint requestid = connection.ReceiveRequestWrap.RequestId;
|
uint requestid = connection.ReceiveRequestWrap.RequestId;
|
||||||
await sender.SendOnly(new MessageRequestWrap
|
await sender.SendReply(new MessageRequestWrap
|
||||||
{
|
{
|
||||||
Connection = cacheTo.Connection,
|
Connection = cacheTo.Connection,
|
||||||
MessengerId = (ushort)SForwardMessengerIds.RemoveClient,
|
MessengerId = (ushort)SForwardMessengerIds.RemoveClient,
|
||||||
Payload = serializer.Serialize(info.Id)
|
Payload = serializer.Serialize(info.Id)
|
||||||
|
}).ContinueWith(async (result) =>
|
||||||
|
{
|
||||||
|
if (result.Result.Code == MessageResponeCodes.OK)
|
||||||
|
{
|
||||||
|
await sender.ReplyOnly(new MessageResponseWrap
|
||||||
|
{
|
||||||
|
Connection = connection,
|
||||||
|
Code = MessageResponeCodes.OK,
|
||||||
|
Payload = result.Result.Data,
|
||||||
|
RequestId = requestid
|
||||||
|
}, (ushort)SForwardMessengerIds.RemoveClientForward).ConfigureAwait(false);
|
||||||
|
}
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -404,6 +428,7 @@ namespace linker.plugins.sforward.messenger
|
|||||||
{
|
{
|
||||||
SForwardInfo sForwardInfo = serializer.Deserialize<SForwardInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
SForwardInfo sForwardInfo = serializer.Deserialize<SForwardInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
sForwardTransfer.Add(sForwardInfo);
|
sForwardTransfer.Add(sForwardInfo);
|
||||||
|
connection.Write(Helper.TrueArray);
|
||||||
}
|
}
|
||||||
// <summary>
|
// <summary>
|
||||||
/// 删除
|
/// 删除
|
||||||
@@ -414,6 +439,7 @@ namespace linker.plugins.sforward.messenger
|
|||||||
{
|
{
|
||||||
int id = serializer.Deserialize<int>(connection.ReceiveRequestWrap.Payload.Span);
|
int id = serializer.Deserialize<int>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
sForwardTransfer.Remove(id);
|
sForwardTransfer.Remove(id);
|
||||||
|
connection.Write(Helper.TrueArray);
|
||||||
}
|
}
|
||||||
// <summary>
|
// <summary>
|
||||||
/// 测试
|
/// 测试
|
||||||
|
@@ -6,13 +6,13 @@ namespace linker.messenger.store.file.plan
|
|||||||
public sealed class PlanStore : IPlanStore
|
public sealed class PlanStore : IPlanStore
|
||||||
{
|
{
|
||||||
private readonly Storefactory dBfactory;
|
private readonly Storefactory dBfactory;
|
||||||
private readonly ILiteCollection<PlanStoreInfo> liteCollection;
|
private readonly ILiteCollection<PlanInfo> liteCollection;
|
||||||
public PlanStore(Storefactory dBfactory)
|
public PlanStore(Storefactory dBfactory)
|
||||||
{
|
{
|
||||||
this.dBfactory = dBfactory;
|
this.dBfactory = dBfactory;
|
||||||
liteCollection = dBfactory.GetCollection<PlanStoreInfo>("plan");
|
liteCollection = dBfactory.GetCollection<PlanInfo>("plan");
|
||||||
}
|
}
|
||||||
public bool Add(PlanStoreInfo info)
|
public bool Add(PlanInfo info)
|
||||||
{
|
{
|
||||||
if (info.Id == 0)
|
if (info.Id == 0)
|
||||||
{
|
{
|
||||||
@@ -27,16 +27,16 @@ namespace linker.messenger.store.file.plan
|
|||||||
return liteCollection.Update(info);
|
return liteCollection.Update(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<PlanStoreInfo> Get()
|
public IEnumerable<PlanInfo> Get()
|
||||||
{
|
{
|
||||||
return liteCollection.FindAll();
|
return liteCollection.FindAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<PlanStoreInfo> Get(string category)
|
public IEnumerable<PlanInfo> Get(string category)
|
||||||
{
|
{
|
||||||
return liteCollection.Find(c => c.Category == category);
|
return liteCollection.Find(c => c.Category == category);
|
||||||
}
|
}
|
||||||
public PlanStoreInfo Get(string category, string key)
|
public PlanInfo Get(string category, string key)
|
||||||
{
|
{
|
||||||
return liteCollection.FindOne(c => c.Category == category && c.Key == key);
|
return liteCollection.FindOne(c => c.Category == category && c.Key == key);
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
<el-dialog v-model="state.show" @open="handleOnShowList" append-to=".app-wrap" :title="`【${machineName}】的内网穿透`" top="1vh" width="700">
|
<el-dialog v-model="state.show" @open="handleOnShowList" append-to=".app-wrap" :title="`【${machineName}】的内网穿透`" top="1vh" width="700">
|
||||||
<div>
|
<div>
|
||||||
<div class="t-c head">
|
<div class="t-c head">
|
||||||
<el-button type="success" size="small" @click="handleAdd">添加</el-button>
|
<el-button type="success" size="small" @click="handleAdd" :loading="state.loading">添加</el-button>
|
||||||
<el-button size="small" @click="handleRefresh">刷新</el-button>
|
<el-button size="small" @click="handleRefresh">刷新</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-table :data="state.data" size="small" border height="500" @cell-dblclick="handleCellClick">
|
<el-table :data="state.data" size="small" border height="500" @cell-dblclick="handleCellClick">
|
||||||
@@ -100,6 +100,7 @@ export default {
|
|||||||
timer:0,
|
timer:0,
|
||||||
timer1:0,
|
timer1:0,
|
||||||
editing:false,
|
editing:false,
|
||||||
|
loading:false,
|
||||||
});
|
});
|
||||||
watch(() => state.show, (val) => {
|
watch(() => state.show, (val) => {
|
||||||
if (!val) {
|
if (!val) {
|
||||||
@@ -147,12 +148,15 @@ export default {
|
|||||||
ElMessage.success('已刷新')
|
ElMessage.success('已刷新')
|
||||||
}
|
}
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
|
state.loading = true;
|
||||||
const row = { Id: 0, Name: '', RemotePort: 0, LocalEP: '127.0.0.1:80',Domain:'',Temp:'' };
|
const row = { Id: 0, Name: '', RemotePort: 0, LocalEP: '127.0.0.1:80',Domain:'',Temp:'' };
|
||||||
addSForwardInfo({machineid:sforward.value.machineid,data:row}).then(() => {
|
addSForwardInfo({machineid:sforward.value.machineid,data:row}).then(() => {
|
||||||
|
state.loading = false;
|
||||||
setTimeout(()=>{
|
setTimeout(()=>{
|
||||||
_getSForwardInfo();
|
_getSForwardInfo();
|
||||||
},100)
|
},100)
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
|
state.loading = false;
|
||||||
ElMessage.error(err);
|
ElMessage.error(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -181,9 +185,15 @@ export default {
|
|||||||
saveRow(row);
|
saveRow(row);
|
||||||
}
|
}
|
||||||
const handleDel = (id) => {
|
const handleDel = (id) => {
|
||||||
removeSForwardInfo({machineid:sforward.value.machineid,id:id}).then(() => {
|
state.loading = true;
|
||||||
|
removeSForwardInfo({machineid:sforward.value.machineid,id:id})
|
||||||
|
.then(() => {
|
||||||
|
state.loading = false;
|
||||||
_getSForwardInfo();
|
_getSForwardInfo();
|
||||||
})
|
}).catch((err) => {
|
||||||
|
state.loading = false;
|
||||||
|
ElMessage.error(err);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
const handleStartChange = (row) => {
|
const handleStartChange = (row) => {
|
||||||
saveRow(row);
|
saveRow(row);
|
||||||
@@ -195,13 +205,15 @@ export default {
|
|||||||
}else{
|
}else{
|
||||||
row.Domain = row.Temp;
|
row.Domain = row.Temp;
|
||||||
}
|
}
|
||||||
|
state.loading = true;
|
||||||
addSForwardInfo({machineid:sforward.value.machineid,data:row}).then((res) => {
|
addSForwardInfo({machineid:sforward.value.machineid,data:row}).then((res) => {
|
||||||
|
state.loading = false;
|
||||||
if(res == false){
|
if(res == false){
|
||||||
ElMessage.error('操作失败,可能存在相同值');
|
ElMessage.error('操作失败,可能存在相同值');
|
||||||
}
|
}
|
||||||
_getSForwardInfo();
|
_getSForwardInfo();
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
|
state.loading = false;
|
||||||
ElMessage.error(err);
|
ElMessage.error(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
v1.7.1
|
v1.7.1
|
||||||
2025-03-26 23:10:35
|
2025-03-27 17:21:16
|
||||||
1. 优化数据同步
|
1. 优化数据同步
|
||||||
2. 优化linux的tun网卡网卡,读写分离,提高性能
|
2. 优化linux的tun网卡网卡,读写分离,提高性能
|
||||||
3. 优化windows网卡的禁用自动启用
|
3. 优化windows网卡的禁用自动启用
|
||||||
|
Reference in New Issue
Block a user