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 System.Diagnostics;
using System.IO.Pipes;
using LumaTunnel.Shared.Windows;

var options = WatchdogOptions.Parse(args);
if (options is null)
    return 2;

try
{
    using var parent = Process.GetProcessById(options.ParentProcessId);
    using var pipe = new NamedPipeClientStream(".", options.PipeName, PipeDirection.In, PipeOptions.Asynchronous);
    try
    {
        using var connectTimeout = new CancellationTokenSource(TimeSpan.FromSeconds(5));
        await pipe.ConnectAsync(connectTimeout.Token).ConfigureAwait(false);
    }
    catch (OperationCanceledException)
    {
    }

    var parentExit = parent.WaitForExitAsync();
    var buffer = new byte[16];
    var pipeSignal = pipe.IsConnected ? pipe.ReadAsync(buffer).AsTask() : Task.FromResult(0);
    var completed = await Task.WhenAny(parentExit, pipeSignal).ConfigureAwait(false);
    if (completed == pipeSignal && await pipeSignal.ConfigureAwait(false) > 0)
        return 0;

    var snapshot = await SystemProxyRegistry.LoadSnapshotAsync(options.SnapshotPath).ConfigureAwait(false);
    if (snapshot is not null && snapshot.OwnerId == options.OwnerId)
        SystemProxyRegistry.RestoreIfOwned(snapshot, options.HttpPort);
    return 0;
}
catch (ArgumentException)
{
    var snapshot = await SystemProxyRegistry.LoadSnapshotAsync(options.SnapshotPath).ConfigureAwait(false);
    if (snapshot is not null && snapshot.OwnerId == options.OwnerId)
        SystemProxyRegistry.RestoreIfOwned(snapshot, options.HttpPort);
    return 0;
}

internal sealed record WatchdogOptions(int ParentProcessId, string PipeName, string SnapshotPath, string OwnerId, int HttpPort)
{
    public static WatchdogOptions? Parse(string[] args)
    {
        string? Read(string name)
        {
            var index = Array.FindIndex(args, item => item.Equals(name, StringComparison.OrdinalIgnoreCase));
            return index >= 0 && index + 1 < args.Length ? args[index + 1] : null;
        }

        return int.TryParse(Read("--parent"), out var parent)
               && int.TryParse(Read("--port"), out var port)
               && Read("--pipe") is { Length: > 0 } pipe
               && Read("--snapshot") is { Length: > 0 } snapshot
               && Read("--owner") is { Length: > 0 } owner
            ? new WatchdogOptions(parent, pipe, snapshot, owner, port)
            : null;
    }
}