This commit is contained in:
snltty
2025-03-12 20:37:02 +08:00
parent 734b2644c9
commit 0275735b09
53 changed files with 652 additions and 314 deletions

View File

@@ -63,6 +63,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "linker.app", "src\linker.ap
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "linker.ics", "src\linker.ics\linker.ics.csproj", "{BBE91688-7734-4BEF-B957-54F8C17F47CE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "linker.messenger.plan", "src\linker.messenger.plan\linker.messenger.plan.csproj", "{5649D02E-200B-45E0-A82F-8EBE76CF96C6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -439,6 +441,18 @@ Global
{BBE91688-7734-4BEF-B957-54F8C17F47CE}.Release|x64.Build.0 = Release|Any CPU
{BBE91688-7734-4BEF-B957-54F8C17F47CE}.Release|x86.ActiveCfg = Release|Any CPU
{BBE91688-7734-4BEF-B957-54F8C17F47CE}.Release|x86.Build.0 = Release|Any CPU
{5649D02E-200B-45E0-A82F-8EBE76CF96C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5649D02E-200B-45E0-A82F-8EBE76CF96C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5649D02E-200B-45E0-A82F-8EBE76CF96C6}.Debug|x64.ActiveCfg = Debug|Any CPU
{5649D02E-200B-45E0-A82F-8EBE76CF96C6}.Debug|x64.Build.0 = Debug|Any CPU
{5649D02E-200B-45E0-A82F-8EBE76CF96C6}.Debug|x86.ActiveCfg = Debug|Any CPU
{5649D02E-200B-45E0-A82F-8EBE76CF96C6}.Debug|x86.Build.0 = Debug|Any CPU
{5649D02E-200B-45E0-A82F-8EBE76CF96C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5649D02E-200B-45E0-A82F-8EBE76CF96C6}.Release|Any CPU.Build.0 = Release|Any CPU
{5649D02E-200B-45E0-A82F-8EBE76CF96C6}.Release|x64.ActiveCfg = Release|Any CPU
{5649D02E-200B-45E0-A82F-8EBE76CF96C6}.Release|x64.Build.0 = Release|Any CPU
{5649D02E-200B-45E0-A82F-8EBE76CF96C6}.Release|x86.ActiveCfg = Release|Any CPU
{5649D02E-200B-45E0-A82F-8EBE76CF96C6}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -7,7 +7,7 @@ namespace linker.messenger.forward
public sealed partial class ForwardInfo
{
public ForwardInfo() { }
public long Id { get; set; }
public int Id { get; set; }
/// <summary>
/// 名称
/// </summary>
@@ -60,7 +60,7 @@ namespace linker.messenger.forward
public sealed partial class ForwardRemoveForwardInfo
{
public string MachineId { get; set; }
public long Id { get; set; }
public int Id { get; set; }
}
public sealed partial class ForwardCountInfo
{

View File

@@ -86,7 +86,7 @@ namespace linker.messenger.forward
if (param.Content == signInClientStore.Id)
{
if (accessStore.HasAccess(AccessValue.ForwardShowSelf) == false) return new List<ForwardInfo>();
return forwardTransfer.Get();
return forwardTransfer.Get().ToList();
}
if (accessStore.HasAccess(AccessValue.ForwardShowOther) == false) return new List<ForwardInfo>();

View File

@@ -183,7 +183,7 @@ namespace linker.messenger.forward
[MessengerId((ushort)ForwardMessengerIds.Remove)]
public void Remove(IConnection connection)
{
uint id = serializer.Deserialize<uint>(connection.ReceiveRequestWrap.Payload.Span);
int id = serializer.Deserialize<int>(connection.ReceiveRequestWrap.Payload.Span);
forwardTransfer.Remove(id);
}

View File

@@ -61,9 +61,7 @@ namespace linker.messenger.forward
{
Stop(item);
}
forwardClientStore.Update(item);
}
forwardClientStore.Confirm();
OnChanged();
}
}
@@ -74,22 +72,22 @@ namespace linker.messenger.forward
try
{
forwardProxy.Start(new System.Net.IPEndPoint(forwardInfo.BindIPAddress, forwardInfo.Port), forwardInfo.TargetEP, forwardInfo.MachineId, forwardInfo.BufferSize);
forwardInfo.Port = forwardProxy.LocalEndpoint.Port;
forwardClientStore.Update(forwardInfo.Id, forwardInfo.Port);
if (forwardInfo.Port > 0)
{
forwardInfo.Started = true;
forwardInfo.Proxy = true;
forwardInfo.Msg = string.Empty;
forwardClientStore.Update(forwardInfo.Id, true, true, string.Empty);
LoggerHelper.Instance.Debug($"start forward {forwardInfo.Port}->{forwardInfo.MachineId}->{forwardInfo.TargetEP}");
}
else
{
if (errorStop)
{
forwardInfo.Started = false;
forwardClientStore.Update(forwardInfo.Id, false);
}
forwardInfo.Msg = $"start forward {forwardInfo.Port}->{forwardInfo.MachineId}->{forwardInfo.TargetEP} fail";
forwardClientStore.Update(forwardInfo.Id, $"start forward {forwardInfo.Port}->{forwardInfo.MachineId}->{forwardInfo.TargetEP} fail");
LoggerHelper.Instance.Error(forwardInfo.Msg);
}
}
@@ -97,9 +95,9 @@ namespace linker.messenger.forward
{
if (errorStop)
{
forwardInfo.Started = false;
forwardClientStore.Update(forwardInfo.Id, false);
}
forwardInfo.Msg = $"{ex.Message},start forward {forwardInfo.Port}->{forwardInfo.MachineId}->{forwardInfo.TargetEP} fail";
forwardClientStore.Update(forwardInfo.Id, $"{ex.Message},start forward {forwardInfo.Port}->{forwardInfo.MachineId}->{forwardInfo.TargetEP} fail");
LoggerHelper.Instance.Error(ex);
}
}
@@ -127,6 +125,7 @@ namespace linker.messenger.forward
LoggerHelper.Instance.Debug($"stop forward {forwardInfo.ToJson()}");
forwardProxy.StopPort(forwardInfo.Port);
forwardInfo.Proxy = false;
forwardClientStore.Update(forwardInfo.Id, forwardInfo.Started, false, forwardInfo.Msg);
}
}
catch (Exception ex)
@@ -136,65 +135,23 @@ namespace linker.messenger.forward
OnChanged();
}
public List<ForwardInfo> Get()
public IEnumerable<ForwardInfo> Get()
{
return forwardClientStore.Get(signInClientStore.Group.Id);
}
public bool Add(ForwardInfo forwardInfo)
{
//同名或者同端口但是ID不一样
ForwardInfo old = forwardClientStore.Get().FirstOrDefault(c => (c.Port == forwardInfo.Port && c.Port != 0) && c.GroupId == signInClientStore.Group.Id && c.MachineId == forwardInfo.MachineId);
if (old != null && old.Id != forwardInfo.Id) return false;
if (forwardInfo.Id != 0)
{
old = forwardClientStore.Get(forwardInfo.Id);
if (old == null) return false;
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Debug($"update forward {old.ToJson()}->{forwardInfo.ToJson()}");
old.BindIPAddress = forwardInfo.BindIPAddress;
old.Port = forwardInfo.Port;
old.Name = forwardInfo.Name;
old.TargetEP = forwardInfo.TargetEP;
old.MachineId = forwardInfo.MachineId;
old.MachineName = forwardInfo.MachineName;
old.Started = forwardInfo.Started;
old.BufferSize = forwardInfo.BufferSize;
old.GroupId = signInClientStore.Group.Id;
forwardClientStore.Update(forwardInfo);
}
else
{
forwardInfo.GroupId = signInClientStore.Group.Id;
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Debug($"add forward {forwardInfo.ToJson()}");
forwardClientStore.Add(forwardInfo);
}
forwardClientStore.Confirm();
Start();
return true;
}
public bool Remove(long id)
public bool Remove(int id)
{
//同名或者同端口但是ID不一样
ForwardInfo old = forwardClientStore.Get(id);
if (old == null) return false;
old.Started = false;
forwardClientStore.Remove(old.Id);
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Debug($"remove forward {old.ToJson()}");
forwardClientStore.Update(id, false);
Start();
forwardClientStore.Confirm();
forwardClientStore.Remove(id);
return true;
}
@@ -237,7 +194,7 @@ namespace linker.messenger.forward
return;
}
var forwards = Get().GroupBy(c => c.MachineId).ToDictionary(c => c.Key, d => d.Select(d => new ForwardTestInfo { Target = d.TargetEP }).ToList());
var forwards = Get().Where(c => string.IsNullOrWhiteSpace(c.MachineId) == false).GroupBy(c => c.MachineId).ToDictionary(c => c.Key, d => d.Select(d => new ForwardTestInfo { Target = d.TargetEP }).ToList());
messengerSender.SendReply(new MessageRequestWrap
{
@@ -252,16 +209,11 @@ namespace linker.messenger.forward
{
Dictionary<string, List<ForwardTestInfo>> tests = serializer.Deserialize<Dictionary<string, List<ForwardTestInfo>>>(result.Result.Data.Span);
var list = Get();
foreach (var item in tests)
{
foreach (var value in item.Value)
{
var forward = list.FirstOrDefault(c => c.MachineId == item.Key && c.TargetEP.Equals(value.Target));
if (forward != null)
{
forward.TargetMsg = value.Msg;
}
forwardClientStore.Update(item.Key, value.Target, value.Msg);
}
}

View File

@@ -1,4 +1,6 @@
namespace linker.messenger.forward
using System.Net;
namespace linker.messenger.forward
{
public interface IForwardClientStore
{
@@ -12,19 +14,19 @@
/// 获取端口转发列表
/// </summary>
/// <returns></returns>
public List<ForwardInfo> Get();
public IEnumerable<ForwardInfo> Get();
/// <summary>
/// 根据id获取
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public ForwardInfo Get(long id);
public ForwardInfo Get(int id);
/// <summary>
/// 根据分组获取
/// </summary>
/// <param name="groupId"></param>
/// <returns></returns>
public List<ForwardInfo> Get(string groupId);
public IEnumerable<ForwardInfo> Get(string groupId);
/// <summary>
/// 添加转发
/// </summary>
@@ -32,22 +34,41 @@
/// <returns></returns>
public bool Add(ForwardInfo info);
/// <summary>
/// 更新转发
/// 更新
/// </summary>
/// <param name="info"></param>
/// <param name="id"></param>
/// <param name="started"></param>
/// <param name="proxy"></param>
/// <param name="msg"></param>
/// <returns></returns>
public bool Update(ForwardInfo info);
public bool Update(int id,bool started,bool proxy,string msg);
/// <summary>
/// 更新
/// </summary>
/// <param name="id"></param>
/// <param name="started"></param>
/// <returns></returns>
public bool Update(int id,bool started);
/// <summary>
/// 更新
/// </summary>
/// <param name="id"></param>
/// <param name="msg"></param>
/// <returns></returns>
public bool Update(int id, string msg);
/// <summary>
/// 更新
/// </summary>
/// <param name="id"></param>
/// <param name="port"></param>
/// <returns></returns>
public bool Update(int id, int port);
public bool Update(string machineId, IPEndPoint target, string targetMsg);
/// <summary>
/// 删除转发
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public bool Remove(long id);
/// <summary>
/// 提交更新
/// </summary>
/// <returns></returns>
public bool Confirm();
public bool Remove(int id);
}
}

View File

@@ -0,0 +1,21 @@

using Microsoft.Extensions.DependencyInjection;
namespace linker.messenger.plan
{
public static class Entry
{
public static ServiceCollection AddPlan(this ServiceCollection serviceCollection)
{
serviceCollection.AddSingleton<PlanTransfer>();
return serviceCollection;
}
public static ServiceProvider UsePlan(this ServiceProvider serviceProvider)
{
PlanTransfer planTransfer = serviceProvider.GetService<PlanTransfer>();
return serviceProvider;
}
}
}

View File

@@ -0,0 +1,77 @@
namespace linker.messenger.plan
{
public interface IPlanStore
{
public bool Add(PlanStoreInfo info);
public IEnumerable<PlanStoreInfo> Get();
public IEnumerable<PlanStoreInfo> Get(string category);
public bool Remove(int id);
}
public interface IPlanHandle
{
/// <summary>
/// 操作分类
/// </summary>
public string CategoryName { get; }
/// <summary>
/// 操作
/// </summary>
/// <param name="handle">操作名</param>
/// <param name="value">值</param>
public void Handle(string handle,string value);
}
public sealed class PlanStoreInfo
{
public int Id { get; set; }
public string Value { get; set; }
public string Category { get; set; }
public string Handle { get; set; }
public PlanMethod Method { get; set; }
public PlanPeriod Period { get; set; }
public string Corn { get; set; }
public int Month { get; set; }
public int Day { get; set; }
public int Hour { get; set; }
public int Min { get; set; }
public int Sec { get; set; }
}
/// <summary>
/// 计划任务方法
/// </summary>
public enum PlanMethod : byte
{
/// <summary>
/// 手动
/// </summary>
Hand = 0,
/// <summary>
/// 定时
/// </summary>
Timer = 1,
/// <summary>
/// 表达式
/// </summary>
Corn = 2,
/// <summary>
/// 启动后
/// </summary>
Setup = 4,
}
/// <summary>
/// 计划任务周期
/// </summary>
public enum PlanPeriod : byte
{
Year = 0,
Month = 1,
Day = 2,
Hour = 4,
Min = 8
}
}

View File

@@ -0,0 +1,129 @@
using Cronos;
using System.Collections.Concurrent;
namespace linker.messenger.plan
{
public sealed class PlanTransfer
{
private readonly ConcurrentDictionary<string, IPlanHandle> handles = new ConcurrentDictionary<string, IPlanHandle>();
private readonly ConcurrentDictionary<int, PlanExecCacheInfo> caches = new ConcurrentDictionary<int, PlanExecCacheInfo>();
private readonly IPlanStore planStore;
public PlanTransfer(IPlanStore planStore)
{
this.planStore = planStore;
PlanTask();
}
public void AddHandle(IPlanHandle handle)
{
handles.AddOrUpdate(handle.CategoryName, handle, (a, b) => handle);
}
public IEnumerable<PlanStoreInfo> Get(string category)
{
return planStore.Get(category);
}
public bool Add(PlanStoreInfo info)
{
bool result = planStore.Add(info);
caches.TryRemove(info.Id, out _);
PlanExecCacheInfo cache = new PlanExecCacheInfo { Store = info };
UpdateNextTime(cache);
caches.TryAdd(info.Id, cache);
return result;
}
public bool Remove(int id)
{
bool result = planStore.Remove(id);
caches.TryRemove(id, out _);
return result;
}
private void PlanTask()
{
foreach (PlanStoreInfo info in planStore.Get())
{
PlanExecCacheInfo cache = new PlanExecCacheInfo { Store = info };
UpdateNextTime(cache);
caches.TryAdd(info.Id, cache);
}
}
private void UpdateNextTime(PlanExecCacheInfo cache)
{
cache.LastTime = DateTime.Now;
if (cache.Store.Method == PlanMethod.Timer)
{
NextTimeTimer(cache);
}
else if (cache.Store.Method == PlanMethod.Corn)
{
NextTimeCorn(cache);
}
}
private void NextTimeCorn(PlanExecCacheInfo cache)
{
CronExpression cron = CronExpression.Parse(cache.Store.Corn);
DateTimeOffset? nextOccurrence = cron.GetNextOccurrence(DateTimeOffset.Now, TimeZoneInfo.Local);
if (nextOccurrence.HasValue)
{
cache.NextTime = nextOccurrence.Value.LocalDateTime;
}
}
private void NextTimeTimer(PlanExecCacheInfo cache)
{
DateTime from = DateTime.Now;
int month = cache.Store.Month;
int day = cache.Store.Day;
int hour = cache.Store.Hour;
int minute = cache.Store.Min;
int second = cache.Store.Sec;
DateTime next = cache.Store.Period switch
{
PlanPeriod.Year => new DateTime(from.Year, month, day, hour, minute, second),
PlanPeriod.Month => new DateTime(from.Year, from.Month, day, hour, minute, second),
PlanPeriod.Day => new DateTime(from.Year, from.Month, from.Day, hour, minute, second),
PlanPeriod.Hour => new DateTime(from.Year, from.Month, from.Day, from.Hour, minute, second),
PlanPeriod.Min => new DateTime(from.Year, from.Month, from.Day, from.Hour, from.Minute, second),
_ => new DateTime(from.Year, from.Month, from.Day, from.Hour, from.Minute, from.Second),
};
if (next <= from)
{
switch (cache.Store.Period)
{
case PlanPeriod.Year:
next = next.AddYears(1);
break;
case PlanPeriod.Month:
next = next.AddMonths(1);
break;
case PlanPeriod.Day:
next = next.AddDays(1);
break;
case PlanPeriod.Hour:
next = next.AddHours(1);
break;
case PlanPeriod.Min:
next = next.AddSeconds(1);
break;
default:
break;
}
}
cache.NextTime = next;
}
}
public sealed class PlanExecCacheInfo
{
public PlanStoreInfo Store { get; set; }
public DateTime LastTime { get; set; }
public DateTime NextTime { get; set; }
public bool Running { get; set; }
}
}

View File

@@ -0,0 +1,47 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>disable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PublishAot>false</PublishAot>
<JsonSerializerIsReflectionEnabledByDefault>true</JsonSerializerIsReflectionEnabledByDefault>
<EnablePreviewFeatures>True</EnablePreviewFeatures>
<Title>linker messenger plan</Title>
<Authors>snltty</Authors>
<Company>snltty</Company>
<Description>linker messenger plan</Description>
<Copyright>snltty</Copyright>
<PackageProjectUrl>https://github.com/snltty/linker</PackageProjectUrl>
<RepositoryUrl>https://github.com/snltty/linker</RepositoryUrl>
<PackageReleaseNotes>linker messenger plan</PackageReleaseNotes>
<Version>1.7.0</Version>
<AssemblyVersion>1.7.0</AssemblyVersion>
<FileVersion>1.7.0</FileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>full</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DebugType>full</DebugType>
<DebugSymbols>true</DebugSymbols>
<Optimize>True</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net8.0|AnyCPU'">
<DebugType>embedded</DebugType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net8.0|AnyCPU'">
<DebugType>embedded</DebugType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Cronos" Version="0.9.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\linker.libs\linker.libs.csproj" />
<ProjectReference Include="..\linker.messenger\linker.messenger.csproj" />
</ItemGroup>
</Project>

View File

@@ -96,7 +96,7 @@ namespace linker.messenger.relay
MessengerId = (ushort)RelayMessengerIds.DelCdkey,
Payload = serializer.Serialize(new RelayServerCdkeyDelInfo
{
CdkeyId = long.Parse(param.Content),
Id = int.Parse(param.Content),
UserId = signInClientStore.Server.UserId,
SecretKey = relayClientStore.Server.SecretKey
})

View File

@@ -91,6 +91,7 @@ namespace linker.messenger.relay.client
SSL = relayClientStore.Server.SSL,
NodeId = nodeId,
UserId = signInClientStore.Server.UserId,
UseCdkey = relayClientStore.Server.UseCdkey,
};
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)

View File

@@ -74,6 +74,7 @@ namespace linker.messenger.relay.client.transport
/// UserId
/// </summary>
public string UserId { get; set; }
public bool UseCdkey { get; set; }
}
/// <summary>
/// 中继交换数据
@@ -149,5 +150,7 @@ namespace linker.messenger.relay.client.transport
public bool SSL { get; set; } = true;
public RelayClientType RelayType { get; set; } = RelayClientType.Linker;
public bool UseCdkey { get; set; } = true;
}
}

View File

@@ -159,7 +159,9 @@ namespace linker.messenger.relay.messenger
if (result.Nodes.Count > 0)
{
List<RelayServerCdkeyInfo> cdkeys = (await relayServerCdkeyStore.GetAvailable(info.UserId)).Select(c => new RelayServerCdkeyInfo { Bandwidth = c.Bandwidth, CdkeyId = c.CdkeyId, LastBytes = c.LastBytes }).ToList();
List<RelayServerCdkeyInfo> cdkeys = info.UseCdkey
? (await relayServerCdkeyStore.GetAvailable(info.UserId)).Select(c => new RelayServerCdkeyInfo { Bandwidth = c.Bandwidth, Id = c.Id, LastBytes = c.LastBytes }).ToList()
: new List<RelayServerCdkeyInfo>();
result.FlowingId = relayServerTransfer.AddRelay(cacheFrom.MachineId, cacheFrom.MachineName, cacheTo.MachineId, cacheTo.MachineName, cacheFrom.GroupId, validated, cdkeys);
}
@@ -321,7 +323,7 @@ namespace linker.messenger.relay.messenger
[MessengerId((ushort)RelayMessengerIds.SendLastBytes)]
public void SendLastBytes(IConnection connection)
{
Dictionary<long, long> info = serializer.Deserialize<Dictionary<long,long>>(connection.ReceiveRequestWrap.Payload.Span);
Dictionary<int, long> info = serializer.Deserialize<Dictionary<int, long>>(connection.ReceiveRequestWrap.Payload.Span);
relayServerNodeTransfer.UpdateLastBytes(info);
}
@@ -377,11 +379,11 @@ namespace linker.messenger.relay.messenger
}
if (relayServerStore.SecretKey == info.SecretKey)
{
await relayServerCdkeyStore.Del(info.CdkeyId);
await relayServerCdkeyStore.Del(info.Id);
}
else
{
await relayServerCdkeyStore.Del(info.CdkeyId, info.UserId);
await relayServerCdkeyStore.Del(info.Id, info.UserId);
}
connection.Write(Helper.TrueArray);
}

View File

@@ -16,14 +16,14 @@ namespace linker.messenger.relay.server
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public Task<bool> Del(long id);
public Task<bool> Del(int id);
/// <summary>
/// 删除
/// </summary>
/// <param name="id"></param>
/// <param name="userid"></param>
/// <returns></returns>
public Task<bool> Del(long id, string userid);
public Task<bool> Del(int id, string userid);
/// <summary>
/// 测试卡密是否可用
@@ -49,19 +49,19 @@ namespace linker.messenger.relay.server
/// </summary>
/// <param name="ids"></param>
/// <returns></returns>
public Task<List<RelayServerCdkeyStoreInfo>> Get(List<long> ids);
public Task<List<RelayServerCdkeyStoreInfo>> Get(List<int> ids);
/// <summary>
/// 消耗流量
/// </summary>
/// <param name="dic"></param>
/// <returns></returns>
public Task<bool> Traffic(Dictionary<long, long> dic);
public Task<bool> Traffic(Dictionary<int, long> dic);
/// <summary>
/// 获取剩余流量
/// </summary>
/// <param name="ids"></param>
/// <returns></returns>
public Task<Dictionary<long, long>> GetLastBytes(List<long> ids);
public Task<Dictionary<int, long>> GetLastBytes(List<int> ids);
/// <summary>
/// 分页
/// </summary>
@@ -125,7 +125,7 @@ namespace linker.messenger.relay.server
{
public string SecretKey { get; set; }
public string UserId { get; set; }
public long CdkeyId { get; set; }
public int Id { get; set; }
}
/// <summary>
@@ -133,8 +133,6 @@ namespace linker.messenger.relay.server
/// </summary>
public sealed partial class RelayServerCdkeyStoreInfo : RelayServerCdkeyInfo
{
public string Id { get; set; }
/// <summary>
/// 用户标识
/// </summary>

View File

@@ -15,8 +15,8 @@ namespace linker.messenger.relay.server
private ulong relayFlowingId = 0;
private readonly ConcurrentDictionary<string, RelayServerNodeReportInfo170> reports = new ConcurrentDictionary<string, RelayServerNodeReportInfo170>();
private readonly ConcurrentQueue<Dictionary<long, long>> trafficQueue = new ConcurrentQueue<Dictionary<long, long>>();
private readonly ConcurrentQueue<List<long>> trafficIdsQueue = new ConcurrentQueue<List<long>>();
private readonly ConcurrentQueue<Dictionary<int, long>> trafficQueue = new ConcurrentQueue<Dictionary<int, long>>();
private readonly ConcurrentQueue<List<int>> trafficIdsQueue = new ConcurrentQueue<List<int>>();
private readonly IRelayServerCaching relayCaching;
private readonly ISerializer serializer;
@@ -148,7 +148,7 @@ namespace linker.messenger.relay.server
/// </summary>
/// <param name="relayTrafficUpdateInfo"></param>
/// <returns></returns>
public void AddTraffic(Dictionary<long, long> dic)
public void AddTraffic(Dictionary<int, long> dic)
{
if (dic.Count > 0)
trafficQueue.Enqueue(dic);
@@ -157,7 +157,7 @@ namespace linker.messenger.relay.server
{
TimerHelper.SetIntervalLong(async () =>
{
while (trafficQueue.TryDequeue(out Dictionary<long, long> dic))
while (trafficQueue.TryDequeue(out Dictionary<int, long> dic))
{
try
{
@@ -180,11 +180,11 @@ namespace linker.messenger.relay.server
}, 500);
TimerHelper.SetIntervalLong(async () =>
{
while (trafficIdsQueue.TryDequeue(out List<long> ids))
while (trafficIdsQueue.TryDequeue(out List<int> ids))
{
try
{
Dictionary<long, long> id2last = await relayServerCdkeyStore.GetLastBytes(ids).ConfigureAwait(false);
Dictionary<int, long> id2last = await relayServerCdkeyStore.GetLastBytes(ids).ConfigureAwait(false);
if (id2last.Count == 0) continue;
byte[] bytes = serializer.Serialize(id2last);

View File

@@ -238,13 +238,13 @@ namespace linker.messenger.relay.server
/// 更新剩余流量
/// </summary>
/// <param name="dic"></param>
public void UpdateLastBytes(Dictionary<long, long> dic)
public void UpdateLastBytes(Dictionary<int, long> dic)
{
if (dic.Count == 0) return;
Dictionary<long, RelayServerCdkeyInfo> cdkeys = trafficDict.Values.SelectMany(c => c.Cache.Cdkey).ToDictionary(c => c.CdkeyId, c => c);
Dictionary<int, RelayServerCdkeyInfo> cdkeys = trafficDict.Values.SelectMany(c => c.Cache.Cdkey).ToDictionary(c => c.Id, c => c);
//更新剩余流量
foreach (KeyValuePair<long, long> item in dic)
foreach (KeyValuePair<int, long> item in dic)
{
if (cdkeys.TryGetValue(item.Key, out RelayServerCdkeyInfo info))
{
@@ -274,7 +274,7 @@ namespace linker.messenger.relay.server
private async Task UploadBytes()
{
var cdkeys = trafficDict.Values.Where(c => c.CurrentCdkey != null && c.Sendt > 0).ToList();
Dictionary<long, long> id2sent = cdkeys.GroupBy(c => c.CurrentCdkey.CdkeyId).ToDictionary(c => c.Key, d => d.Sum(d => { d.SendtCache = d.Sendt; return d.SendtCache; }));
Dictionary<int, long> id2sent = cdkeys.GroupBy(c => c.CurrentCdkey.Id).ToDictionary(c => c.Key, d => d.Sum(d => { d.SendtCache = d.Sendt; return d.SendtCache; }));
if (id2sent.Count == 0) return;
bool result = await messengerSender.SendOnly(new MessageRequestWrap
@@ -417,7 +417,7 @@ namespace linker.messenger.relay.server
/// <summary>
/// cdkey id 和 流量
/// </summary>
public Dictionary<long, long> Dic { get; set; }
public Dictionary<int, long> Dic { get; set; }
public string SecretKey { get; set; }
}

View File

@@ -268,7 +268,7 @@ namespace linker.messenger.relay.server
}
public partial class RelayServerCdkeyInfo
{
public long CdkeyId { get; set; }
public int Id { get; set; }
/// <summary>
/// 带宽Mbps
/// </summary>

View File

@@ -11,7 +11,7 @@ namespace linker.messenger.serializer.memorypack
public readonly ForwardInfo info;
[MemoryPackInclude]
long Id => info.Id;
int Id => info.Id;
[MemoryPackInclude]
string Name => info.Name;
@@ -47,7 +47,7 @@ namespace linker.messenger.serializer.memorypack
string TargetMsg => info.TargetMsg;
[MemoryPackConstructor]
SerializableForwardInfo(long id, string name, string machineId, string groupId, string machineName, IPAddress bindIPAddress, int port, IPEndPoint targetEP, bool started, byte bufferSize, string msg, string targetMsg)
SerializableForwardInfo(int id, string name, string machineId, string groupId, string machineName, IPAddress bindIPAddress, int port, IPEndPoint targetEP, bool started, byte bufferSize, string msg, string targetMsg)
{
this.info = new ForwardInfo
{
@@ -167,10 +167,10 @@ namespace linker.messenger.serializer.memorypack
string MachineId => info.MachineId;
[MemoryPackInclude, MemoryPackAllowSerialize]
long Id => info.Id;
int Id => info.Id;
[MemoryPackConstructor]
SerializableForwardRemoveForwardInfo(string machineId, long id)
SerializableForwardRemoveForwardInfo(string machineId, int id)
{
this.info = new ForwardRemoveForwardInfo
{

View File

@@ -235,11 +235,15 @@ namespace linker.messenger.serializer.memorypack
[MemoryPackInclude]
string UserId => info.UserId;
[MemoryPackInclude]
bool UseCdkey => info.UseCdkey;
[MemoryPackConstructor]
SerializableRelayInfo170(string fromMachineId, string fromMachineName,
string remoteMachineId, string remoteMachineName,
string transactionId, string secretKey, string transportName, ulong flowingId,
string nodeId, IPEndPoint server, bool ssl, string userid)
string nodeId, IPEndPoint server, bool ssl, string userid, bool useCdkey)
{
var info = new RelayInfo170
{
@@ -254,7 +258,8 @@ namespace linker.messenger.serializer.memorypack
TransportName = transportName,
SecretKey = secretKey,
Server = server,
UserId = userid
UserId = userid,
UseCdkey = useCdkey
};
this.info = info;
}
@@ -868,7 +873,7 @@ namespace linker.messenger.serializer.memorypack
public readonly RelayServerCdkeyInfo info;
[MemoryPackInclude]
long CdkeyId => info.CdkeyId;
int Id => info.Id;
[MemoryPackInclude]
double Bandwidth => info.Bandwidth;
@@ -876,11 +881,11 @@ namespace linker.messenger.serializer.memorypack
long LastBytes => info.LastBytes;
[MemoryPackConstructor]
SerializableRelayServerCdkeyInfo(long cdkeyid, double bandwidth, long lastBytes)
SerializableRelayServerCdkeyInfo(int id, double bandwidth, long lastBytes)
{
var info = new RelayServerCdkeyInfo
{
CdkeyId = cdkeyid,
Id = id,
Bandwidth = bandwidth,
LastBytes = lastBytes
};
@@ -926,15 +931,13 @@ namespace linker.messenger.serializer.memorypack
[MemoryPackIgnore]
public readonly RelayServerCdkeyStoreInfo info;
[MemoryPackInclude]
long CdkeyId => info.CdkeyId;
[MemoryPackInclude]
double Bandwidth => info.Bandwidth;
[MemoryPackInclude]
long LastBytes => info.LastBytes;
[MemoryPackInclude]
string Id => info.Id;
int Id => info.Id;
[MemoryPackInclude]
string UserId => info.UserId;
@@ -968,11 +971,10 @@ namespace linker.messenger.serializer.memorypack
bool Deleted => info.Deleted;
[MemoryPackConstructor]
SerializableRelayServerCdkeyStoreInfo(long cdkeyid, double bandwidth, long lastBytes, string id, string userid, DateTime addTime, DateTime startTime, DateTime endTime, DateTime useTime, long maxBytes, double costPrice, double price, double userPrice, double payPrice, string remark, string orderId, string contact, bool deleted)
SerializableRelayServerCdkeyStoreInfo(double bandwidth, long lastBytes, int id, string userid, DateTime addTime, DateTime startTime, DateTime endTime, DateTime useTime, long maxBytes, double costPrice, double price, double userPrice, double payPrice, string remark, string orderId, string contact, bool deleted)
{
var info = new RelayServerCdkeyStoreInfo
{
CdkeyId = cdkeyid,
Bandwidth = bandwidth,
LastBytes = lastBytes,
Id = id,
@@ -1094,16 +1096,16 @@ namespace linker.messenger.serializer.memorypack
[MemoryPackInclude]
string UserId => info.UserId;
[MemoryPackInclude]
long CdkeyId => info.CdkeyId;
int Id => info.Id;
[MemoryPackConstructor]
SerializableRelayServerCdkeyDelInfo(string secretKey, string userid, long cdkeyid)
SerializableRelayServerCdkeyDelInfo(string secretKey, string userid, int id)
{
var info = new RelayServerCdkeyDelInfo
{
SecretKey = secretKey,
UserId = userid,
CdkeyId = cdkeyid
Id = id
};
this.info = info;
}
@@ -1291,12 +1293,12 @@ namespace linker.messenger.serializer.memorypack
public readonly RelayTrafficUpdateInfo info;
[MemoryPackInclude]
Dictionary<long, long> Dic => info.Dic;
Dictionary<int, long> Dic => info.Dic;
[MemoryPackInclude]
string SecretKey => info.SecretKey;
[MemoryPackConstructor]
SerializableRelayTrafficUpdateInfo(Dictionary<long, long> dic, string secretKey)
SerializableRelayTrafficUpdateInfo(Dictionary<int, long> dic, string secretKey)
{
var info = new RelayTrafficUpdateInfo
{

View File

@@ -11,7 +11,7 @@ namespace linker.messenger.serializer.memorypack
public readonly SForwardInfo info;
[MemoryPackInclude]
long Id => info.Id;
int Id => info.Id;
[MemoryPackInclude]
string Name => info.Name;
@@ -44,7 +44,7 @@ namespace linker.messenger.serializer.memorypack
int RemotePortMax => info.RemotePortMax;
[MemoryPackConstructor]
SerializableSForwardInfo(long id, string name, string domain, int remotePort, byte bufferSize, IPEndPoint localEP, bool started, string msg, string localMsg, int remotePortMin, int remotePortMax)
SerializableSForwardInfo(int id, string name, string domain, int remotePort, byte bufferSize, IPEndPoint localEP, bool started, string msg, string localMsg, int remotePortMin, int remotePortMax)
{
this.info = new SForwardInfo
{
@@ -277,10 +277,10 @@ namespace linker.messenger.serializer.memorypack
string MachineId => info.MachineId;
[MemoryPackInclude, MemoryPackAllowSerialize]
long Id => info.Id;
int Id => info.Id;
[MemoryPackConstructor]
SerializableSForwardRemoveForwardInfo(string machineId, long id)
SerializableSForwardRemoveForwardInfo(string machineId, int id)
{
this.info = new SForwardRemoveForwardInfo
{

View File

@@ -10,7 +10,7 @@ namespace linker.messenger.sforward
/// <summary>
/// 穿透id
/// </summary>
public long Id { get; set; }
public int Id { get; set; }
/// <summary>
/// 名称
/// </summary>
@@ -125,7 +125,7 @@ namespace linker.messenger.sforward
public sealed partial class SForwardRemoveForwardInfo
{
public string MachineId { get; set; }
public long Id { get; set; }
public int Id { get; set; }
}
/// <summary>

View File

@@ -24,13 +24,13 @@
/// 获取穿透列表
/// </summary>
/// <returns></returns>
public List<SForwardInfo> Get();
public IEnumerable<SForwardInfo> Get();
/// <summary>
/// 获取穿透
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public SForwardInfo Get(long id);
public SForwardInfo Get(int id);
/// <summary>
/// 获取穿透
/// </summary>
@@ -42,7 +42,7 @@
/// </summary>
/// <param name="port"></param>
/// <returns></returns>
public SForwardInfo Get(int port);
public SForwardInfo GetPort(int port);
/// <summary>
/// 添加穿透
/// </summary>
@@ -52,19 +52,39 @@
/// <summary>
/// 更新穿透
/// </summary>
/// <param name="info"></param>
/// <param name="id"></param>
/// <param name="started"></param>
/// <param name="msg"></param>
/// <returns></returns>
public bool Update(SForwardInfo info);
public bool Update(int id,bool started,string msg);
/// <summary>
/// 更新
/// </summary>
/// <param name="id"></param>
/// <param name="started"></param>
/// <param name="proxy"></param>
/// <param name="msg"></param>
/// <returns></returns>
public bool Update(int id,bool started,bool proxy,string msg);
/// <summary>
/// 更新
/// </summary>
/// <param name="id"></param>
/// <param name="started"></param>
/// <returns></returns>
public bool Update(int id,bool started);
/// <summary>
/// 更新
/// </summary>
/// <param name="id"></param>
/// <param name="localMsg"></param>
/// <returns></returns>
public bool Update(int id,string localMsg);
/// <summary>
/// 删除穿透
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public bool Remove(long id);
/// <summary>
/// 提交保存
/// </summary>
/// <returns></returns>
public bool Confirm();
public bool Remove(int id);
}
}

View File

@@ -84,7 +84,7 @@ namespace linker.messenger.sforward.client
if (param.Content == signInClientStore.Id)
{
if (accessStore.HasAccess(AccessValue.ForwardShowSelf) == false) return new List<SForwardInfo>();
return sForwardClientStore.Get();
return sForwardClientStore.Get().ToList();
}
if (accessStore.HasAccess(AccessValue.ForwardShowOther) == false) return new List<SForwardInfo>();

View File

@@ -9,6 +9,8 @@ namespace linker.messenger.sforward.client
public sealed class SForwardClientTransfer
{
public Action OnChanged { get; set; } = () => { };
public Action<int> OnOpen = (id) => { };
public Action<int> OnClose = (id) => { };
private readonly SignInClientState signInClientState;
private readonly IMessengerSender messengerSender;
@@ -23,15 +25,14 @@ namespace linker.messenger.sforward.client
this.signInClientStore = signInClientStore;
this.sForwardClientStore = sForwardClientStore;
//也有可能是服务端重启导致重新上线,所以不能在首次登录启动,要每次登录都尝试添加一下
signInClientState.OnSignInSuccess += (i) => Start();
this.serializer = serializer;
}
private void Start()
{
var list = sForwardClientStore.Get();
foreach (var item in list)
foreach (var item in sForwardClientStore.Get())
{
if (item.Started)
{
@@ -41,18 +42,14 @@ namespace linker.messenger.sforward.client
{
Stop(item);
}
sForwardClientStore.Update(item);
sForwardClientStore.Confirm();
}
OnChanged();
}
private void Start(SForwardInfo forwardInfo)
{
if (forwardInfo.Proxy) return;
if (forwardInfo.RemotePort == 0 && string.IsNullOrWhiteSpace(forwardInfo.Domain))
{
forwardInfo.Msg = $"Please use port or domain";
forwardInfo.Started = false;
sForwardClientStore.Update(forwardInfo.Id, false, forwardInfo.Proxy, $"Please use port or domain");
return;
}
@@ -73,26 +70,27 @@ namespace linker.messenger.sforward.client
forwardInfo.BufferSize = sForwardAddResultInfo.BufferSize;
if (sForwardAddResultInfo.Success)
{
forwardInfo.Proxy = true;
forwardInfo.Msg = string.Empty;
sForwardClientStore.Update(forwardInfo.Id, forwardInfo.Started,true, string.Empty);
LoggerHelper.Instance.Debug(sForwardAddResultInfo.Message);
OnOpen(forwardInfo.Id);
}
else
{
forwardInfo.Started = false;
forwardInfo.Msg = sForwardAddResultInfo.Message;
sForwardClientStore.Update(forwardInfo.Id, false, forwardInfo.Proxy, sForwardAddResultInfo.Message);
LoggerHelper.Instance.Error(sForwardAddResultInfo.Message);
}
}
OnChanged();
});
}
catch (Exception ex)
{
forwardInfo.Started = false;
sForwardClientStore.Update(forwardInfo.Id, false, ex.Message);
LoggerHelper.Instance.Error(ex);
}
OnChanged();
}
}
private void Stop(SForwardInfo forwardInfo)
{
try
@@ -113,16 +111,18 @@ namespace linker.messenger.sforward.client
SForwardAddResultInfo sForwardAddResultInfo = serializer.Deserialize<SForwardAddResultInfo>(result.Result.Data.Span);
if (sForwardAddResultInfo.Success)
{
forwardInfo.Proxy = false;
sForwardClientStore.Update(forwardInfo.Id, forwardInfo.Started, false, string.Empty);
LoggerHelper.Instance.Debug(sForwardAddResultInfo.Message);
OnClose(forwardInfo.Id);
}
else
{
forwardInfo.Started = true;
sForwardClientStore.Update(forwardInfo.Id, true, forwardInfo.Proxy, string.Empty);
LoggerHelper.Instance.Error(sForwardAddResultInfo.Message);
}
}
OnChanged();
});
}
}
@@ -130,81 +130,23 @@ namespace linker.messenger.sforward.client
{
LoggerHelper.Instance.Error(ex);
}
OnChanged();
}
public bool Add(SForwardInfo forwardInfo)
{
//同名或者同端口但是ID不一样
SForwardInfo old = sForwardClientStore.Get().FirstOrDefault(c => forwardInfo.RemotePort > 0 && c.RemotePort == forwardInfo.RemotePort || string.IsNullOrWhiteSpace(forwardInfo.Domain) == false && c.Domain == forwardInfo.Domain);
if (old != null && old.Id != forwardInfo.Id) return false;
if (forwardInfo.Id != 0)
{
old = sForwardClientStore.Get(forwardInfo.Id);
if (old == null) return false;
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Info($"update sforward {old.ToJson()}->{forwardInfo.ToJson()}");
old.RemotePort = forwardInfo.RemotePort;
old.Name = forwardInfo.Name;
old.LocalEP = forwardInfo.LocalEP;
old.Domain = forwardInfo.Domain;
old.Started = forwardInfo.Started;
if (PortRange(forwardInfo.Domain, out int min, out int max))
{
old.RemotePortMin = min;
old.RemotePortMax = max;
}
sForwardClientStore.Update(old);
}
else
{
if (PortRange(forwardInfo.Domain, out int min, out int max))
{
forwardInfo.RemotePortMin = min;
forwardInfo.RemotePortMax = max;
}
sForwardClientStore.Add(forwardInfo);
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Info($"add sforward {forwardInfo.ToJson()}");
}
sForwardClientStore.Confirm();
Start();
return true;
}
public bool Remove(long id)
public bool Remove(int id)
{
//同名或者同端口但是ID不一样
SForwardInfo old = sForwardClientStore.Get(id);
if (old == null)
{
return false;
}
old.Started = false;
sForwardClientStore.Update(id, false);
Start();
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Info($"remove sforward {old.ToJson()}");
sForwardClientStore.Remove(id);
sForwardClientStore.Confirm();
return true;
}
private bool PortRange(string str, out int min, out int max)
{
min = 0; max = 0;
if (string.IsNullOrWhiteSpace(str)) return false;
string[] arr = str.Split('/');
return arr.Length == 2 && int.TryParse(arr[0], out min) && int.TryParse(arr[1], out max);
}
private readonly OperatingManager testing = new OperatingManager();
public void SubscribeTest()
@@ -227,12 +169,12 @@ namespace linker.messenger.sforward.client
try
{
await socket.ConnectAsync(info.LocalEP).WaitAsync(TimeSpan.FromMilliseconds(500));
info.LocalMsg = string.Empty;
sForwardClientStore.Update(info.Id, string.Empty);
return true;
}
catch (Exception ex)
{
info.LocalMsg = ex.Message;
sForwardClientStore.Update(info.Id, ex.Message);
}
finally
{

View File

@@ -43,4 +43,7 @@
<ProjectReference Include="..\linker.messenger.sync\linker.messenger.sync.csproj" />
<ProjectReference Include="..\linker.messenger\linker.messenger.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="client\plan\" />
</ItemGroup>
</Project>

View File

@@ -392,7 +392,7 @@ namespace linker.plugins.sforward.messenger
[MessengerId((ushort)SForwardMessengerIds.Get)]
public void Get(IConnection connection)
{
List<SForwardInfo> result = sForwardClientStore.Get();
List<SForwardInfo> result = sForwardClientStore.Get().ToList();
connection.Write(serializer.Serialize(result));
}
/// <summary>
@@ -412,7 +412,7 @@ namespace linker.plugins.sforward.messenger
[MessengerId((ushort)SForwardMessengerIds.RemoveClient)]
public void RemoveClient(IConnection connection)
{
uint id = serializer.Deserialize<uint>(connection.ReceiveRequestWrap.Payload.Span);
int id = serializer.Deserialize<int>(connection.ReceiveRequestWrap.Payload.Span);
sForwardTransfer.Remove(id);
}
// <summary>

View File

@@ -49,6 +49,7 @@ namespace linker.messenger.signin
public sealed class SignInConfigServerInfo
{
public string SecretKey { get; set; } = string.Empty;
public int CleanDays { get; set; } = 7;
}
public sealed partial class SignInConfigSetNameInfo

View File

@@ -11,10 +11,13 @@ namespace linker.messenger.signin
/// 信标密钥
/// </summary>
public string SecretKey { get; }
public int CleanDays { get; }
/// <summary>
/// 设置信标密钥
/// </summary>
/// <param name="secretKey"></param>
public void SetSecretKey(string secretKey);
public void SetCleanDays(int days);
}
}

View File

@@ -125,7 +125,7 @@ namespace linker.messenger.signin
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Debug($"start cleaning up clients that have exceeded the 7-day timeout period");
LoggerHelper.Instance.Debug($"start cleaning up clients that have exceeded the {signInStore.CleanDays}-day timeout period");
}
try
@@ -133,7 +133,7 @@ namespace linker.messenger.signin
DateTime now = DateTime.Now;
var groups = Clients.Values.GroupBy(c => c.GroupId)
.Where(group => group.All(info => info.Connected == false && (now - info.LastSignIn).TotalDays > 7))
.Where(group => group.All(info => info.Connected == false && (now - info.LastSignIn).TotalDays > signInStore.CleanDays))
.Select(group => group.Key).ToList();
if (groups.Count > 0)
@@ -163,7 +163,6 @@ namespace linker.messenger.signin
/// </summary>
public sealed class SignCacheInfo
{
public string Id { get; set; }
/// <summary>
/// 客户端id

View File

@@ -32,8 +32,6 @@ using linker.messenger.tuntap.lease;
using linker.messenger.updater;
using linker.plugins.tunnel;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Yitter.IdGenerator;
namespace linker.messenger.store.file
{
public static class Entry
@@ -42,8 +40,6 @@ namespace linker.messenger.store.file
{
LoggerHelper.Instance.Info("add store file");
YitIdHelper.SetIdGenerator(new IdGeneratorOptions(1));
serviceCollection.AddSingleton<Storefactory>();
serviceCollection.AddSingleton<FileConfig>();
serviceCollection.AddSingleton<RunningConfig>();

View File

@@ -102,8 +102,6 @@ namespace linker.messenger.store.file
[JsonIgnore, BsonIgnore]
public uint Updated { get; set; } = 1;
public bool IsSyncConfig { get; set; }
public void Update()
{
Updated++;

View File

@@ -1,63 +1,106 @@
using linker.messenger.forward;
using Yitter.IdGenerator;
using linker.messenger.sforward;
using linker.messenger.store.file.signIn;
using linker.tunnel.transport;
using LiteDB;
using System.Net;
namespace linker.messenger.store.file.forward
{
public sealed class ForwardClientStore : IForwardClientStore
{
private readonly RunningConfig runningConfig;
public ForwardClientStore(RunningConfig runningConfig)
private readonly Storefactory dBfactory;
private readonly ILiteCollection<ForwardInfo> liteCollection;
public ForwardClientStore(RunningConfig runningConfig, Storefactory dBfactory)
{
this.dBfactory = dBfactory;
liteCollection = dBfactory.GetCollection<ForwardInfo>("forward");
this.runningConfig = runningConfig;
foreach (var item in runningConfig.Data.Forwards)
{
item.Proxy = false;
item.Id = 0;
liteCollection.Insert(item);
}
runningConfig.Data.Forwards = new List<ForwardInfo>();
runningConfig.Data.Update();
liteCollection.UpdateMany(c => new ForwardInfo { Proxy = false },c=>c.Proxy==true);
}
public int Count()
{
return runningConfig.Data.Forwards.Count();
return liteCollection.Count();
}
public List<ForwardInfo> Get()
public IEnumerable<ForwardInfo> Get()
{
return runningConfig.Data.Forwards;
return liteCollection.FindAll();
}
public ForwardInfo Get(long id)
public ForwardInfo Get(int id)
{
return runningConfig.Data.Forwards.FirstOrDefault(x => x.Id == id);
return liteCollection.FindOne(x => x.Id == id);
}
public List<ForwardInfo> Get(string groupid)
public IEnumerable<ForwardInfo> Get(string groupid)
{
return runningConfig.Data.Forwards.Where(x => x.GroupId == groupid).ToList();
return liteCollection.Find(x => x.GroupId == groupid);
}
public bool Add(ForwardInfo info)
{
if(info.Id == 0)
//同名或者同端口但是ID不一样
ForwardInfo old = liteCollection.FindOne(c => (c.Port == info.Port && c.Port != 0) && c.GroupId == info.GroupId && c.MachineId == info.MachineId);
if (old != null && old.Id != info.Id) return false;
if (info.Id != 0)
{
info.Id = YitIdHelper.NextId();
liteCollection.UpdateMany(c => new ForwardInfo
{
BindIPAddress = info.BindIPAddress,
Port = info.Port,
Name = info.Name,
TargetEP = info.TargetEP,
MachineId = info.MachineId,
MachineName = info.MachineName,
Started = info.Started,
BufferSize = info.BufferSize,
GroupId = info.GroupId,
}, c => c.Id == info.Id);
}
else
{
liteCollection.Insert(info);
}
runningConfig.Data.Forwards.Add(info);
return true;
}
public bool Update(ForwardInfo info)
public bool Update(int id, bool started, bool proxy, string msg)
{
return true;
return liteCollection.UpdateMany(c => new ForwardInfo { Started = started, Proxy = proxy, Msg = msg }, c => c.Id == id) > 0;
}
public bool Remove(long id)
public bool Update(int id, bool started)
{
runningConfig.Data.Forwards.Remove(Get(id));
return true;
return liteCollection.UpdateMany(c => new ForwardInfo { Started = started }, c => c.Id == id) > 0;
}
public bool Confirm()
public bool Update(int id, string msg)
{
runningConfig.Data.Update();
return true;
return liteCollection.UpdateMany(c => new ForwardInfo { Msg = msg }, c => c.Id == id) > 0;
}
public bool Update(string machineId, IPEndPoint target, string targetMsg)
{
return liteCollection.UpdateMany(c => new ForwardInfo { TargetMsg = targetMsg }, c => c.MachineId == machineId && c.TargetEP == target) > 0;
}
public bool Update(int id, int port)
{
return liteCollection.UpdateMany(c => new ForwardInfo { Port = port }, c => c.Id == id) > 0;
}
public bool Remove(int id)
{
return liteCollection.Delete(id);
}

View File

@@ -38,7 +38,6 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="LiteDB" Version="5.0.17" />
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\linker.libs\linker.libs.csproj" />

View File

@@ -4,13 +4,13 @@ using linker.messenger.relay.server;
using LiteDB;
using System.Text;
using System.Text.RegularExpressions;
using Yitter.IdGenerator;
namespace linker.messenger.store.file.relay
{
public sealed class RelayServerCdkeyStore : IRelayServerCdkeyStore
{
private string regex = @"([0-9]+)-([0-9]+)-([0-9]+)\s+([0-9]+):([0-9]+):([0-9]+)";
private int index = 0;
private readonly Storefactory dBfactory;
private readonly ILiteCollection<RelayServerCdkeyStoreInfo> liteCollection;
@@ -24,15 +24,16 @@ namespace linker.messenger.store.file.relay
public async Task<bool> Add(RelayServerCdkeyStoreInfo info)
{
if (string.IsNullOrWhiteSpace(info.Id))
if (info.Id == 0)
{
info.Id = ObjectId.NewObjectId().ToString();
Interlocked.Increment(ref index);
Interlocked.CompareExchange(ref index, 0, 65535);
info.AddTime = DateTime.Now;
info.UseTime = DateTime.Now;
info.StartTime = DateTime.Now;
info.LastBytes = info.MaxBytes;
info.CdkeyId = YitIdHelper.NextId();
info.OrderId = $"Linker{YitIdHelper.NextId()}";
info.OrderId = $"Linker{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}{index}";
liteCollection.Insert(info);
}
else
@@ -41,13 +42,13 @@ namespace linker.messenger.store.file.relay
}
return await Task.FromResult(true);
}
public async Task<bool> Del(long id)
public async Task<bool> Del(int id)
{
return await Task.FromResult(liteCollection.UpdateMany(c => new RelayServerCdkeyStoreInfo { Deleted = true }, c => c.CdkeyId == id) > 0);
return await Task.FromResult(liteCollection.UpdateMany(c => new RelayServerCdkeyStoreInfo { Deleted = true }, c => c.Id == id) > 0);
}
public async Task<bool> Del(long id, string userid)
public async Task<bool> Del(int id, string userid)
{
return await Task.FromResult(liteCollection.UpdateMany(c => new RelayServerCdkeyStoreInfo { Deleted = true }, c => c.CdkeyId == id && c.UserId == userid) > 0);
return await Task.FromResult(liteCollection.UpdateMany(c => new RelayServerCdkeyStoreInfo { Deleted = true }, c => c.Id == id && c.UserId == userid) > 0);
}
public async Task<RelayServerCdkeyTestResultInfo> Test(RelayServerCdkeyImportInfo info)
@@ -144,42 +145,40 @@ namespace linker.messenger.store.file.relay
Remark = "order",
StartTime = DateTime.Now,
UserId = order.WidgetUserId,
CdkeyId = YitIdHelper.NextId(),
Contact = order.Contact,
OrderId = order.OrderId,
PayPrice = order.PayPrice,
UserPrice = order.UserPrice,
Id = ObjectId.NewObjectId().ToString()
UserPrice = order.UserPrice
};
liteCollection.Insert(store);
return await Task.FromResult(string.Empty);
}
public async Task<bool> Traffic(Dictionary<long, long> dic)
public async Task<bool> Traffic(Dictionary<int, long> dic)
{
foreach (var item in dic)
{
var info = liteCollection.FindOne(x => x.CdkeyId == item.Key);
var info = liteCollection.FindOne(x => x.Id == item.Key);
if (info != null)
{
long bytes = info.LastBytes >= item.Value ? info.LastBytes - item.Value : 0;
liteCollection.UpdateMany(x => new RelayServerCdkeyStoreInfo { LastBytes = bytes, UseTime = DateTime.Now }, c => c.CdkeyId == item.Key);
liteCollection.UpdateMany(x => new RelayServerCdkeyStoreInfo { LastBytes = bytes, UseTime = DateTime.Now }, c => c.Id == item.Key);
}
}
return await Task.FromResult(true);
}
public async Task<Dictionary<long,long>> GetLastBytes(List<long> ids)
public async Task<Dictionary<int, long>> GetLastBytes(List<int> ids)
{
return await Task.FromResult(liteCollection.Find(c => ids.Contains(c.CdkeyId)).ToDictionary(c => c.CdkeyId, c => c.LastBytes));
return await Task.FromResult(liteCollection.Find(c => ids.Contains(c.Id)).ToDictionary(c => c.Id, c => c.LastBytes));
}
public async Task<List<RelayServerCdkeyStoreInfo>> GetAvailable(string userid)
{
return await Task.FromResult(liteCollection.Find(x => x.UserId == userid && x.LastBytes > 0 && x.StartTime <= DateTime.Now && x.EndTime >= DateTime.Now && x.Deleted == false).ToList());
}
public async Task<List<RelayServerCdkeyStoreInfo>> Get(List<long> ids)
public async Task<List<RelayServerCdkeyStoreInfo>> Get(List<int> ids)
{
return await Task.FromResult(liteCollection.Find(x => ids.Contains(x.CdkeyId)).ToList());
return await Task.FromResult(liteCollection.Find(x => ids.Contains(x.Id)).ToList());
}
public async Task<RelayServerCdkeyPageResultInfo> Page(RelayServerCdkeyPageRequestInfo info)
@@ -233,7 +232,7 @@ namespace linker.messenger.store.file.relay
}
else
{
query = query.OrderBy(c => c.CdkeyId, Query.Descending);
query = query.OrderBy(c => c.Id, Query.Descending);
}
return await Task.FromResult(new RelayServerCdkeyPageResultInfo

View File

@@ -1,6 +1,9 @@
using linker.messenger.sforward;
using linker.libs.extends;
using linker.libs;
using linker.messenger.sforward;
using linker.messenger.sforward.client;
using Yitter.IdGenerator;
using LiteDB;
using linker.messenger.forward;
namespace linker.messenger.store.file.sforward
{
@@ -10,14 +13,26 @@ namespace linker.messenger.store.file.sforward
private readonly FileConfig fileConfig;
private readonly RunningConfig runningConfig;
public SForwardClientStore(FileConfig fileConfig, RunningConfig runningConfig)
private readonly Storefactory dBfactory;
private readonly ILiteCollection<SForwardInfo> liteCollection;
public SForwardClientStore(FileConfig fileConfig, RunningConfig runningConfig, Storefactory dBfactory)
{
this.dBfactory = dBfactory;
liteCollection = dBfactory.GetCollection<SForwardInfo>("sforward");
this.fileConfig = fileConfig;
this.runningConfig = runningConfig;
foreach (var item in runningConfig.Data.SForwards)
{
item.Proxy = false;
item.Id = 0;
liteCollection.Insert(item);
}
runningConfig.Data.SForwards = new List<SForwardInfo>();
runningConfig.Data.Update();
liteCollection.UpdateMany(c => new SForwardInfo { Proxy = false }, c => c.Proxy == true);
}
public bool SetSecretKey(string key)
{
@@ -26,57 +41,96 @@ namespace linker.messenger.store.file.sforward
return true;
}
public int Count()
{
return runningConfig.Data.SForwards.Count();
return liteCollection.Count();
}
public List<SForwardInfo> Get()
public IEnumerable<SForwardInfo> Get()
{
return runningConfig.Data.SForwards;
return liteCollection.FindAll();
}
public SForwardInfo Get(long id)
public SForwardInfo Get(int id)
{
return runningConfig.Data.SForwards.FirstOrDefault(x => x.Id == id);
return liteCollection.FindOne(x => x.Id == id);
}
public SForwardInfo Get(string domain)
{
return runningConfig.Data.SForwards.FirstOrDefault(x => x.Domain == domain);
return liteCollection.FindOne(x => x.Domain == domain);
}
public SForwardInfo Get(int port)
public SForwardInfo GetPort(int port)
{
return runningConfig.Data.SForwards.FirstOrDefault(c => c.RemotePort == port);
return liteCollection.FindOne(c => c.RemotePort == port);
}
public bool Add(SForwardInfo info)
{
if (info.Id == 0)
SForwardInfo old = liteCollection.FindOne(c => info.RemotePort > 0 && c.RemotePort == info.RemotePort || string.IsNullOrWhiteSpace(info.Domain) == false && c.Domain == info.Domain);
if (old != null && old.Id != info.Id)
{
info.Id = YitIdHelper.NextId();
}
runningConfig.Data.SForwards.Add(info);
return true;
}
public bool Update(SForwardInfo info)
{
return true;
}
public bool Remove(long id)
{
runningConfig.Data.SForwards.Remove(Get(id));
return true;
return false;
}
public bool Confirm()
if (PortRange(info.Domain, out int min, out int max))
{
runningConfig.Data.Update();
info.RemotePortMin = min;
info.RemotePortMax = max;
}
if (info.Id != 0)
{
liteCollection.UpdateMany(c => new SForwardInfo
{
RemotePort = info.RemotePort,
Name = info.Name,
LocalEP = info.LocalEP,
Domain = info.Domain,
Started = info.Started,
RemotePortMin = info.RemotePortMin,
RemotePortMax = info.RemotePortMax
}, c => c.Id == info.Id);
}
else
{
liteCollection.Insert(info);
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Info($"add sforward {info.ToJson()}");
}
return true;
}
public bool Update(int id, bool started, string msg)
{
return liteCollection.UpdateMany(c => new SForwardInfo { Started = started, Msg = msg }, c => c.Id == id) > 0;
}
public bool Update(int id, bool started, bool proxy, string msg)
{
return liteCollection.UpdateMany(c => new SForwardInfo { Started = started, Proxy = proxy, Msg = msg }, c => c.Id == id) > 0;
}
public bool Update(int id, bool started)
{
return liteCollection.UpdateMany(c => new SForwardInfo { Started = started }, c => c.Id == id) > 0;
}
public bool Update(int id, string localMsg)
{
return liteCollection.UpdateMany(c => new SForwardInfo { LocalMsg = localMsg }, c => c.Id == id) > 0;
}
public bool Remove(int id)
{
return liteCollection.Delete(id);
}
private bool PortRange(string str, out int min, out int max)
{
min = 0; max = 0;
if (string.IsNullOrWhiteSpace(str)) return false;
string[] arr = str.Split('/');
return arr.Length == 2 && int.TryParse(arr[0], out min) && int.TryParse(arr[1], out max);
}
}
}

View File

@@ -6,6 +6,7 @@ namespace linker.messenger.store.file.signIn
public sealed class SignInServerStore : ISignInServerStore
{
public string SecretKey => fileConfig.Data.Server.SignIn.SecretKey;
public int CleanDays => fileConfig.Data.Server.SignIn.CleanDays;
private readonly Storefactory dBfactory;
private readonly ILiteCollection<SignCacheInfo> liteCollection;
@@ -19,6 +20,12 @@ namespace linker.messenger.store.file.signIn
public void SetSecretKey(string secretKey)
{
fileConfig.Data.Server.SignIn.SecretKey = secretKey;
fileConfig.Data.Update();
}
public void SetCleanDays(int days)
{
fileConfig.Data.Server.SignIn.CleanDays = days;
fileConfig.Data.Update();
}
public void Confirm()

View File

@@ -1,5 +1,5 @@
<?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.214" ProductVersion="0.0.0.214" 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.216" ProductVersion="0.0.0.216" publishDir="/dist/" dstrip="false" local="false" ignored="false">
<file name="main.aardio" path="main.aardio" comment="main.aardio"/>
<folder name="资源文件" path="res" embed="true" local="false" ignored="false">
<file name="favicon.ico" path="res\favicon.ico" comment="res\favicon.ico"/>

Binary file not shown.

View File

@@ -1 +1 @@
.table-sort th[data-v-754b053a]{border-bottom:0}.dropdown[data-v-6e34f330]{border:1px solid #ddd;padding:.4rem;font-size:1.3rem;border-radius:.4rem;position:relative}.dropdown .el-icon[data-v-6e34f330]{vertical-align:middle}.dropdown .badge[data-v-6e34f330]{position:absolute;right:-1rem;top:-50%;border-radius:10px;background-color:#f1ae05;color:#fff;padding:.2rem .6rem;font-size:1.2rem}a[data-v-90c5041c]{color:#666;text-decoration:underline}a.green[data-v-90c5041c]{color:green;font-weight:700}a.download[data-v-90c5041c]{margin-left:.6rem}a.download .el-icon[data-v-90c5041c]{vertical-align:middle;font-weight:700;margin-left:.3rem}a.download .el-icon.loading[data-v-90c5041c]{animation:loading-90c5041c 1s linear infinite}a.download+a.download[data-v-90c5041c]{margin-left:.2rem}@keyframes loading-90c5041c{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}img.system[data-v-9f58a72e]{height:1.6rem;vertical-align:middle;margin-right:.4rem}.self[data-v-9f58a72e]{color:#d400ff}.self .el-icon[data-v-9f58a72e]{vertical-align:text-bottom}.ipaddress span[data-v-5db71b03]{vertical-align:middle}.el-input[data-v-5db71b03]{width:12rem;margin-right:.6rem}.el-col[data-v-7a697708]{text-align:left}div.point[data-v-41d1beca]{margin:-.2rem .3rem 0 -1.3rem;position:absolute}span.point[data-v-41d1beca]{width:.8rem;height:.8rem;border-radius:50%;display:inline-block;vertical-align:middle;background-color:#eee;border:1px solid #ddd;cursor:pointer;transition:.3s}span.point[data-v-41d1beca]:hover{transform:scale(2)}span.point.p2p[data-v-41d1beca]{background-color:#01c901;border:1px solid #049538}span.point.relay[data-v-41d1beca]{background-color:#e3e811;border:1px solid #b3c410}span.point.node[data-v-41d1beca]{background-color:#09dda9;border:1px solid #0cac90}.el-icon.loading[data-v-6710e79d],a.loading[data-v-6710e79d]{vertical-align:middle;font-weight:700;animation:loading-6710e79d 1s linear infinite}.el-switch.is-disabled[data-v-6710e79d]{opacity:1}.el-input[data-v-6710e79d]{width:8rem}.delay[data-v-6710e79d]{position:absolute;right:0;bottom:0;line-height:normal}.switch-btn[data-v-6710e79d]{font-size:1.5rem}.any[data-v-6710e79d]{position:absolute;left:-7px;top:-2px;line-height:normal}.any.green[data-v-6710e79d]{background:linear-gradient(270deg,#caff00,green,#0d6d23,#e38a00,green);background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:hsla(0,0%,100%,0)}@keyframes loading-6710e79d{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.wrap[data-v-786fe646]{padding-right:1rem}.remark[data-v-786fe646]{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.wrap[data-v-286c7cac]{padding-right:1rem}.el-switch.is-disabled[data-v-0b701835]{opacity:1}.upgrade-wrap[data-v-0b701835]{border:1px solid #ddd;margin-bottom:2rem;padding:0 0 1rem 0}.el-switch.is-disabled[data-v-67ed3552]{opacity:1}.calc span[data-v-67ed3552]{display:inline-block}.calc span.label[data-v-67ed3552]{width:6rem}.el-icon.loading[data-v-b38b7526],a.loading[data-v-b38b7526]{vertical-align:middle;font-weight:700;animation:loading-b38b7526 1s linear infinite}.el-switch.is-disabled[data-v-b38b7526]{opacity:1}.el-input[data-v-b38b7526]{width:8rem}.switch-btn[data-v-b38b7526]{font-size:1.5rem}@keyframes loading-b38b7526{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.el-switch.is-disabled[data-v-022e3781]{opacity:1}.upgrade-wrap[data-v-022e3781]{border:1px solid #ddd;margin-bottom:2rem;padding:1rem 0 1rem 0}.lan-item[data-v-022e3781]{margin-bottom:0}.el-switch.is-disabled[data-v-723b8bdd]{opacity:1}.green[data-v-723b8bdd]{font-weight:700}img.system[data-v-723b8bdd]{height:1.4rem;margin-right:.4rem;border:1px solid #eee}.el-switch.is-disabled[data-v-4d08fa0e]{opacity:1}ul li[data-v-4d08fa0e]{padding-left:2rem}a[data-v-2ee190a4]{text-decoration:underline}a+a[data-v-2ee190a4]{margin-left:1rem}a.green[data-v-2ee190a4]{font-weight:700}.head[data-v-6897ed85]{padding-bottom:1rem}.green[data-v-6897ed85]{color:green;font-weight:700}.error[data-v-6897ed85]{font-weight:700}.error .el-icon[data-v-6897ed85]{vertical-align:text-bottom}.head[data-v-9f4ae946]{padding-bottom:1rem}.error[data-v-9f4ae946]{font-weight:700}.error .el-icon[data-v-9f4ae946]{vertical-align:text-bottom}.head[data-v-497cd22a]{padding-bottom:1rem}.blue[data-v-497cd22a]{color:#409eff}.table-sort.el-table th.el-table__cell.is-leaf{border-bottom:0}.table-sort.el-table .el-table__inner-wrapper:before{height:0}.home-list-wrap[data-v-524833e4]{padding:1rem}.home-list-wrap .page[data-v-524833e4]{padding-top:1rem}.home-list-wrap .page-wrap[data-v-524833e4]{display:inline-block}
.table-sort th[data-v-754b053a]{border-bottom:0}.dropdown[data-v-6e34f330]{border:1px solid #ddd;padding:.4rem;font-size:1.3rem;border-radius:.4rem;position:relative}.dropdown .el-icon[data-v-6e34f330]{vertical-align:middle}.dropdown .badge[data-v-6e34f330]{position:absolute;right:-1rem;top:-50%;border-radius:10px;background-color:#f1ae05;color:#fff;padding:.2rem .6rem;font-size:1.2rem}a[data-v-90c5041c]{color:#666;text-decoration:underline}a.green[data-v-90c5041c]{color:green;font-weight:700}a.download[data-v-90c5041c]{margin-left:.6rem}a.download .el-icon[data-v-90c5041c]{vertical-align:middle;font-weight:700;margin-left:.3rem}a.download .el-icon.loading[data-v-90c5041c]{animation:loading-90c5041c 1s linear infinite}a.download+a.download[data-v-90c5041c]{margin-left:.2rem}@keyframes loading-90c5041c{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}img.system[data-v-9f58a72e]{height:1.6rem;vertical-align:middle;margin-right:.4rem}.self[data-v-9f58a72e]{color:#d400ff}.self .el-icon[data-v-9f58a72e]{vertical-align:text-bottom}.ipaddress span[data-v-5db71b03]{vertical-align:middle}.el-input[data-v-5db71b03]{width:12rem;margin-right:.6rem}.el-col[data-v-7a697708]{text-align:left}div.point[data-v-41d1beca]{margin:-.2rem .3rem 0 -1.3rem;position:absolute}span.point[data-v-41d1beca]{width:.8rem;height:.8rem;border-radius:50%;display:inline-block;vertical-align:middle;background-color:#eee;border:1px solid #ddd;cursor:pointer;transition:.3s}span.point[data-v-41d1beca]:hover{transform:scale(2)}span.point.p2p[data-v-41d1beca]{background-color:#01c901;border:1px solid #049538}span.point.relay[data-v-41d1beca]{background-color:#e3e811;border:1px solid #b3c410}span.point.node[data-v-41d1beca]{background-color:#09dda9;border:1px solid #0cac90}.el-icon.loading[data-v-6710e79d],a.loading[data-v-6710e79d]{vertical-align:middle;font-weight:700;animation:loading-6710e79d 1s linear infinite}.el-switch.is-disabled[data-v-6710e79d]{opacity:1}.el-input[data-v-6710e79d]{width:8rem}.delay[data-v-6710e79d]{position:absolute;right:0;bottom:0;line-height:normal}.switch-btn[data-v-6710e79d]{font-size:1.5rem}.any[data-v-6710e79d]{position:absolute;left:-7px;top:-2px;line-height:normal}.any.green[data-v-6710e79d]{background:linear-gradient(270deg,#caff00,green,#0d6d23,#e38a00,green);background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:hsla(0,0%,100%,0)}@keyframes loading-6710e79d{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.wrap[data-v-786fe646]{padding-right:1rem}.remark[data-v-786fe646]{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.wrap[data-v-286c7cac]{padding-right:1rem}.el-switch.is-disabled[data-v-0b701835]{opacity:1}.upgrade-wrap[data-v-0b701835]{border:1px solid #ddd;margin-bottom:2rem;padding:0 0 1rem 0}.el-switch.is-disabled[data-v-67ed3552]{opacity:1}.calc span[data-v-67ed3552]{display:inline-block}.calc span.label[data-v-67ed3552]{width:6rem}.el-icon.loading[data-v-b38b7526],a.loading[data-v-b38b7526]{vertical-align:middle;font-weight:700;animation:loading-b38b7526 1s linear infinite}.el-switch.is-disabled[data-v-b38b7526]{opacity:1}.el-input[data-v-b38b7526]{width:8rem}.switch-btn[data-v-b38b7526]{font-size:1.5rem}@keyframes loading-b38b7526{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.el-switch.is-disabled[data-v-022e3781]{opacity:1}.upgrade-wrap[data-v-022e3781]{border:1px solid #ddd;margin-bottom:2rem;padding:1rem 0 1rem 0}.lan-item[data-v-022e3781]{margin-bottom:0}.el-switch.is-disabled[data-v-723b8bdd]{opacity:1}.green[data-v-723b8bdd]{font-weight:700}img.system[data-v-723b8bdd]{height:1.4rem;margin-right:.4rem;border:1px solid #eee}.el-switch.is-disabled[data-v-4d08fa0e]{opacity:1}ul li[data-v-4d08fa0e]{padding-left:2rem}a[data-v-2ee190a4]{text-decoration:underline}a+a[data-v-2ee190a4]{margin-left:1rem}a.green[data-v-2ee190a4]{font-weight:700}.head[data-v-6897ed85]{padding-bottom:1rem}.green[data-v-6897ed85]{color:green;font-weight:700}.error[data-v-6897ed85]{font-weight:700}.error .el-icon[data-v-6897ed85]{vertical-align:text-bottom}.head[data-v-7d65167d]{padding-bottom:1rem}.error[data-v-7d65167d]{font-weight:700}.error .el-icon[data-v-7d65167d]{vertical-align:text-bottom}.head[data-v-497cd22a]{padding-bottom:1rem}.blue[data-v-497cd22a]{color:#409eff}.table-sort.el-table th.el-table__cell.is-leaf{border-bottom:0}.table-sort.el-table .el-table__inner-wrapper:before{height:0}.home-list-wrap[data-v-524833e4]{padding:1rem}.home-list-wrap .page[data-v-524833e4]{padding-top:1rem}.home-list-wrap .page-wrap[data-v-524833e4]{display:inline-block}

View File

@@ -1 +1 @@
.el-radio-group[data-v-7061404c]{margin-right:.6rem}.wrap[data-v-7061404c]{padding-bottom:1rem}.el-form-item[data-v-2bef0d8e]{margin-bottom:1rem}.el-input-number--small[data-v-2bef0d8e]{width:10rem!important}.el-form-item[data-v-3d96703d]{margin-bottom:1rem}.el-input-number--small[data-v-3d96703d]{width:10rem!important}.head .search>div[data-v-96177fdc]{margin-right:1rem}.page[data-v-96177fdc]{padding:2rem 0;display:inline-block}.el-form-item[data-v-96177fdc]{margin-bottom:1rem}.el-input-number--small[data-v-96177fdc]{width:10rem!important}.head .search>div[data-v-48a99ebb]{margin-right:1rem}.page[data-v-48a99ebb]{padding:2rem 0;display:inline-block}.el-form-item[data-v-48a99ebb]{margin-bottom:1rem}.el-input-number--small[data-v-48a99ebb]{width:10rem!important}.el-form-item[data-v-5bae8d04]{margin-bottom:1rem}.el-input-number--small[data-v-5bae8d04]{width:10rem!important}.blue[data-v-4893eaea]{color:#409eff}.servers-wrap[data-v-597f32d0]{padding:1rem;font-size:1.3rem;color:#555}.servers-wrap a[data-v-597f32d0]{color:#333}
.el-radio-group[data-v-7061404c]{margin-right:.6rem}.wrap[data-v-7061404c]{padding-bottom:1rem}.el-form-item[data-v-2bef0d8e]{margin-bottom:1rem}.el-input-number--small[data-v-2bef0d8e]{width:10rem!important}.el-form-item[data-v-3d96703d]{margin-bottom:1rem}.el-input-number--small[data-v-3d96703d]{width:10rem!important}.head .search>div[data-v-5d11d068]{margin-right:1rem}.page[data-v-5d11d068]{padding:2rem 0;display:inline-block}.el-form-item[data-v-5d11d068]{margin-bottom:1rem}.el-input-number--small[data-v-5d11d068]{width:10rem!important}.head .search>div[data-v-22d5523e]{margin-right:1rem}.page[data-v-22d5523e]{padding:2rem 0;display:inline-block}.el-form-item[data-v-22d5523e]{margin-bottom:1rem}.el-input-number--small[data-v-22d5523e]{width:10rem!important}.el-form-item[data-v-5bae8d04]{margin-bottom:1rem}.el-input-number--small[data-v-5bae8d04]{width:10rem!important}.blue[data-v-2f3d60d9]{color:#409eff}.servers-wrap[data-v-597f32d0]{padding:1rem;font-size:1.3rem;color:#555}.servers-wrap a[data-v-597f32d0]{color:#333}

View File

@@ -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.f322f42d.js"></script><script defer="defer" src="js/app.f10de741.js"></script><link href="css/chunk-vendors.d8267b33.css" rel="stylesheet"><link href="css/app.c44d60aa.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.f322f42d.js"></script><script defer="defer" src="js/app.fdbcdbd9.js"></script><link href="css/chunk-vendors.d8267b33.css" rel="stylesheet"><link href="css/app.c44d60aa.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

File diff suppressed because one or more lines are too long

View File

@@ -120,6 +120,7 @@ export default {
'server.relaySecretKey': 'Relay SecretKey',
'server.relaySSL': 'Use SSL',
'server.relayDisable': 'Disable',
'server.relayUseCdkey': 'Use CDKEY',
'server.relayNodes': 'Nodes',
'server.relayTitle': 'Relay Nodes',
'server.relayName': 'Name',

View File

@@ -122,6 +122,7 @@ export default {
'server.relaySecretKey': '中继密钥',
'server.relaySSL': '使用ssl',
'server.relayDisable': '禁用',
'server.relayUseCdkey': '消耗CDKEY',
'server.relayNodes': '节点',
'server.relayTitle': '中继节点',
'server.relayName': '名称',

View File

@@ -17,9 +17,9 @@
</template>
</template>
</el-table-column>
<el-table-column prop="BufferSize" label="缓冲区" width="100">
<el-table-column prop="Plan" label="计划" width="100">
<template #default="scope">
<span>{{ 1<<scope.row.BufferSize }}KB</span>
<span>{{ scope.row.Plan }}</span>
</template>
</el-table-column>
<el-table-column property="Temp" label="远程端口/域名" width="160">

View File

@@ -9,10 +9,15 @@
<div class="mgr-1">
<el-checkbox class="mgr-1" v-model="state.list.SSL" :label="$t('server.relaySSL')" @change="handleSave" />
<el-checkbox v-model="state.list.Disabled" :label="$t('server.relayDisable')" @change="handleSave" />
</div>
<a href="javascript:;" @click="state.show=true" class="mgl-1 delay a-line" :class="{red:state.nodes.length==0,green:state.nodes.length>0}">
{{$t('server.relayNodes')}} : {{state.nodes.length}}
</a>
<div class="mgl-1">
<el-checkbox v-model="state.list.UseCdkey" :label="$t('server.relayUseCdkey')" @change="handleSave" />
</div>
<RelayCdkey></RelayCdkey>
</div>
</div>

View File

@@ -157,7 +157,7 @@ export default {
}
const handleDel = (row)=>{
relayCdkeyDel(row.CdkeyId).then((res)=>{
relayCdkeyDel(row.Id).then((res)=>{
handleSearch();
}).catch(()=>{})
}

View File

@@ -146,7 +146,7 @@ export default {
handleSearch();
}
const handleDel = (row)=>{
relayCdkeyDel(row.CdkeyId).then((res)=>{
relayCdkeyDel(row.Id).then((res)=>{
handleSearch();
}).catch(()=>{})
}

View File

@@ -1,5 +1,5 @@
v1.7.0
2025-03-11 23:50:55
2025-03-12 20:37:01
1. 优化linux下路由跟踪问题提高启动速度
2. 优化linux下获取本机IP问题提升虚拟网卡稳定性
3. 增加ICS让win7+、win server2008+支持NAT