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.Collections.Concurrent;
using LumaTunnel.Server.Core.Persistence;

namespace LumaTunnel.Server.Core.Runtime;

public sealed class TrafficCounters
{
    private readonly ConcurrentDictionary<string, DeviceTrafficCounter> _devices = new(StringComparer.Ordinal);
    private long _activeConnections;

    public TrafficCounters(IEnumerable<TrafficRecord>? initial = null)
    {
        if (initial is null) return;
        foreach (var record in initial)
            _devices[record.DeviceId] = new DeviceTrafficCounter(record.UploadBytes, record.DownloadBytes);
    }

    public int ActiveConnections => checked((int)Interlocked.Read(ref _activeConnections));

    public DeviceTrafficCounter GetDevice(string deviceId) => _devices.GetOrAdd(deviceId, static _ => new DeviceTrafficCounter());

    public void ConnectionOpened(string deviceId)
    {
        Interlocked.Increment(ref _activeConnections);
        GetDevice(deviceId).ConnectionOpened();
    }

    public void ConnectionClosed(string deviceId)
    {
        Interlocked.Decrement(ref _activeConnections);
        GetDevice(deviceId).ConnectionClosed();
    }

    public void AddUpload(string deviceId, int bytes) => GetDevice(deviceId).AddUpload(bytes);

    public void AddDownload(string deviceId, int bytes) => GetDevice(deviceId).AddDownload(bytes);

    public TrafficDatabase Snapshot() => new()
    {
        UpdatedAtUtc = DateTimeOffset.UtcNow,
        Devices = _devices.OrderBy(static pair => pair.Key).Select(static pair => new TrafficRecord
        {
            DeviceId = pair.Key,
            UploadBytes = pair.Value.UploadBytes,
            DownloadBytes = pair.Value.DownloadBytes
        }).ToList()
    };
}

public sealed class DeviceTrafficCounter
{
    private long _activeConnections;
    private long _uploadBytes;
    private long _downloadBytes;

    public DeviceTrafficCounter(long uploadBytes = 0, long downloadBytes = 0)
    {
        _uploadBytes = uploadBytes;
        _downloadBytes = downloadBytes;
    }

    public int ActiveConnections => checked((int)Interlocked.Read(ref _activeConnections));
    public long UploadBytes => Interlocked.Read(ref _uploadBytes);
    public long DownloadBytes => Interlocked.Read(ref _downloadBytes);

    internal void ConnectionOpened() => Interlocked.Increment(ref _activeConnections);
    internal void ConnectionClosed() => Interlocked.Decrement(ref _activeConnections);
    internal void AddUpload(int bytes) => Interlocked.Add(ref _uploadBytes, bytes);
    internal void AddDownload(int bytes) => Interlocked.Add(ref _downloadBytes, bytes);
}