XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

LumaTunnel

【WinUI】LumaTunnel 是一个面向个人多设备的 Windows 代理系统。客户端在本机提供 HTTP/HTTPS CONNECT 与 SOCKS5 TCP 代理,并通过一个受信任 TLS 证书保护的 WSS 会话,将多个 TCP 流复用到自建 Windows Server 节点。

公开
关注 0 Fork 0 Star 0
UTF-8
using LumaTunnel.Server.Core.Configuration;
using LumaTunnel.Server.Core.Persistence;
using LumaTunnel.Server.Core.Security;

namespace LumaTunnel.Server.Core.Runtime;

public sealed class ServerRuntime
{
    private static ServerRuntime? s_current;

    private readonly AtomicJsonStore<TrafficDatabase> _trafficStore;

    private ServerRuntime(ServerPaths paths, ServerSettings settings, DeviceRegistry devices, PairingCodeService pairingCodes, AtomicJsonStore<TrafficDatabase> trafficStore, TrafficCounters traffic)
    {
        Paths = paths;
        Settings = settings;
        Devices = devices;
        PairingCodes = pairingCodes;
        _trafficStore = trafficStore;
        Traffic = traffic;
        TargetPolicy = new TargetPolicy(settings);
    }

    public static ServerRuntime Current => s_current ?? throw new InvalidOperationException("Server runtime has not been initialized.");
    public ServerPaths Paths { get; }
    public ServerSettings Settings { get; }
    public DeviceRegistry Devices { get; }
    public PairingCodeService PairingCodes { get; }
    public TargetPolicy TargetPolicy { get; }
    public TrafficCounters Traffic { get; }
    public TunnelConnectionManager? TunnelConnections { get; set; }

    public static async Task<ServerRuntime> InitializeAsync(ServerPaths? paths = null, CancellationToken cancellationToken = default)
    {
        paths ??= ServerPaths.CreateDefault();
        paths.EnsureDirectories();
        var settingsStore = new AtomicJsonStore<ServerSettings>(paths.SettingsFile);
        var settings = await settingsStore.LoadOrCreateAsync(static () => new ServerSettings(), cancellationToken).ConfigureAwait(false);
        settings.Validate();
        var devices = new DeviceRegistry(new AtomicJsonStore<DeviceDatabase>(paths.DevicesFile));
        var pairingCodes = new PairingCodeService(new AtomicJsonStore<PairingCodeDatabase>(paths.PairingCodesFile));
        var trafficStore = new AtomicJsonStore<TrafficDatabase>(paths.TrafficFile);
        await devices.InitializeAsync(cancellationToken).ConfigureAwait(false);
        await pairingCodes.InitializeAsync(cancellationToken).ConfigureAwait(false);
        var traffic = await trafficStore.LoadOrCreateAsync(static () => new TrafficDatabase(), cancellationToken).ConfigureAwait(false);
        s_current = new ServerRuntime(paths, settings, devices, pairingCodes, trafficStore, new TrafficCounters(traffic.Devices));
        return s_current;
    }

    public async Task FlushAsync(CancellationToken cancellationToken = default)
    {
        await Devices.SaveAsync(cancellationToken).ConfigureAwait(false);
        await _trafficStore.SaveAsync(Traffic.Snapshot(), cancellationToken).ConfigureAwait(false);
    }
}