diff --git a/v2rayN/ServiceLib/Handler/StatisticsHandler.cs b/v2rayN/ServiceLib/Handler/StatisticsHandler.cs index 97d4f7b3..377638cb 100644 --- a/v2rayN/ServiceLib/Handler/StatisticsHandler.cs +++ b/v2rayN/ServiceLib/Handler/StatisticsHandler.cs @@ -9,7 +9,8 @@ private ServerStatItem? _serverStatItem; private List _lstServerStat; private Action? _updateFunc; - private StatisticsV2rayService? _statisticsV2Ray; + //private StatisticsV2rayService? _statisticsV2Ray; + private StatisticsXrayService? _statisticsXray; private StatisticsSingboxService? _statisticsSingbox; public List ServerStat => _lstServerStat; @@ -25,7 +26,8 @@ await InitData(); - _statisticsV2Ray = new StatisticsV2rayService(config, UpdateServerStatHandler); + //_statisticsV2Ray = new StatisticsV2rayService(config, UpdateServerStatHandler); + _statisticsXray = new StatisticsXrayService(config, UpdateServerStatHandler); _statisticsSingbox = new StatisticsSingboxService(config, UpdateServerStatHandler); } @@ -33,7 +35,8 @@ { try { - _statisticsV2Ray?.Close(); + //_statisticsV2Ray?.Close(); + _statisticsXray?.Close(); _statisticsSingbox?.Close(); } catch (Exception ex) diff --git a/v2rayN/ServiceLib/Models/V2rayConfig.cs b/v2rayN/ServiceLib/Models/V2rayConfig.cs index 593e3710..b5623398 100644 --- a/v2rayN/ServiceLib/Models/V2rayConfig.cs +++ b/v2rayN/ServiceLib/Models/V2rayConfig.cs @@ -2,60 +2,33 @@ using System.Text.Json.Serialization; namespace ServiceLib.Models { - /// - /// v2ray配置文件实体类 例子SampleConfig.txt - /// public class V2rayConfig { - /// - /// Properties that do not belong to Ray - /// public string? remarks { get; set; } - /// - /// 日志配置 - /// public Log4Ray log { get; set; } - /// - /// 传入连接配置 - /// public List inbounds { get; set; } - /// - /// 传出连接配置 - /// public List outbounds { get; set; } - /// - /// 统计需要, 空对象 - /// - public Stats4Ray stats { get; set; } + public Stats4Ray? stats { get; set; } - /// - public API4Ray api { get; set; } + public Metrics4Ray? metrics { get; set; } - /// - public Policy4Ray policy { get; set; } + public Policy4Ray? policy { get; set; } - /// - /// DNS 配置 - /// public object dns { get; set; } - /// - /// 路由配置 - /// public Routing4Ray routing { get; set; } } public class Stats4Ray { } - public class API4Ray + public class Metrics4Ray { public string tag { get; set; } - public List services { get; set; } } public class Policy4Ray @@ -71,124 +44,59 @@ namespace ServiceLib.Models public class Log4Ray { - /// - /// - /// - public string access { get; set; } + public string? access { get; set; } - /// - /// - /// - public string error { get; set; } + public string? error { get; set; } - /// - /// - /// - public string loglevel { get; set; } + public string? loglevel { get; set; } } public class Inbounds4Ray { public string tag { get; set; } - /// - /// - /// public int port { get; set; } - /// - /// - /// public string listen { get; set; } - /// - /// - /// public string protocol { get; set; } - /// - /// - /// public Sniffing4Ray sniffing { get; set; } - /// - /// - /// public Inboundsettings4Ray settings { get; set; } - - /// - /// - /// - public StreamSettings4Ray streamSettings { get; set; } } public class Inboundsettings4Ray { - /// - /// - /// - public string auth { get; set; } + public string? auth { get; set; } - /// - /// - /// - public bool udp { get; set; } + public bool? udp { get; set; } - /// - /// - /// - public string ip { get; set; } + public string? ip { get; set; } - /// - /// api 使用 - /// - public string address { get; set; } + public string? address { get; set; } - /// - /// - /// - public List clients { get; set; } + public List? clients { get; set; } - /// - /// VLESS - /// - public string decryption { get; set; } + public string? decryption { get; set; } - public bool allowTransparent { get; set; } + public bool? allowTransparent { get; set; } - public List accounts { get; set; } + public List? accounts { get; set; } } public class UsersItem4Ray { - /// - /// - /// - public string id { get; set; } + public string? id { get; set; } - /// - /// - /// - public int alterId { get; set; } + public int? alterId { get; set; } - /// - /// - /// - public string email { get; set; } + public string? email { get; set; } - /// - /// - /// - public string security { get; set; } + public string? security { get; set; } - /// - /// VLESS - /// - public string encryption { get; set; } + public string? encryption { get; set; } - /// - /// VLESS - /// public string? flow { get; set; } } @@ -201,57 +109,27 @@ namespace ServiceLib.Models public class Outbounds4Ray { - /// - /// 默认值agentout - /// public string tag { get; set; } - /// - /// - /// public string protocol { get; set; } - /// - /// - /// public Outboundsettings4Ray settings { get; set; } - /// - /// - /// public StreamSettings4Ray streamSettings { get; set; } - /// - /// - /// public Mux4Ray mux { get; set; } } public class Outboundsettings4Ray { - /// - /// - /// public List? vnext { get; set; } - /// - /// - /// - public List servers { get; set; } + public List? servers { get; set; } - /// - /// - /// - public Response4Ray response { get; set; } + public Response4Ray? response { get; set; } - /// - /// - /// public string domainStrategy { get; set; } - /// - /// - /// public int? userLevel { get; set; } public FragmentItem4Ray? fragment { get; set; } @@ -259,85 +137,40 @@ namespace ServiceLib.Models public class VnextItem4Ray { - /// - /// - /// public string address { get; set; } - /// - /// - /// public int port { get; set; } - /// - /// - /// public List users { get; set; } } public class ServersItem4Ray { - /// - /// - /// public string email { get; set; } - /// - /// - /// public string address { get; set; } - /// - /// - /// public string? method { get; set; } - /// - /// - /// public bool? ota { get; set; } - /// - /// - /// public string? password { get; set; } - /// - /// - /// public int port { get; set; } - /// - /// - /// public int? level { get; set; } - /// - /// trojan - /// public string flow { get; set; } - /// - /// - /// public List users { get; set; } } public class SocksUsersItem4Ray { - /// - /// - /// public string user { get; set; } - /// - /// - /// public string pass { get; set; } - /// - /// - /// public int? level { get; set; } } @@ -351,17 +184,11 @@ namespace ServiceLib.Models public class Response4Ray { - /// - /// - /// public string type { get; set; } } public class Dns4Ray { - /// - /// - /// public List servers { get; set; } } @@ -373,19 +200,10 @@ namespace ServiceLib.Models public class Routing4Ray { - /// - /// - /// public string domainStrategy { get; set; } - /// - /// - /// public string? domainMatcher { get; set; } - /// - /// - /// public List rules { get; set; } public List? balancers { get; set; } @@ -426,87 +244,39 @@ namespace ServiceLib.Models public class StreamSettings4Ray { - /// - /// - /// public string network { get; set; } - /// - /// - /// public string security { get; set; } - /// - /// - /// public TlsSettings4Ray? tlsSettings { get; set; } - /// - /// Tcp传输额外设置 - /// public TcpSettings4Ray? tcpSettings { get; set; } - /// - /// Kcp传输额外设置 - /// public KcpSettings4Ray? kcpSettings { get; set; } - /// - /// ws传输额外设置 - /// public WsSettings4Ray? wsSettings { get; set; } - /// - /// - /// public HttpupgradeSettings4Ray? httpupgradeSettings { get; set; } - /// - /// - /// public SplithttpSettings4Ray? splithttpSettings { get; set; } - /// - /// h2传输额外设置 - /// public HttpSettings4Ray? httpSettings { get; set; } - /// - /// QUIC - /// public QuicSettings4Ray? quicSettings { get; set; } - /// - /// VLESS only - /// public TlsSettings4Ray? realitySettings { get; set; } - /// - /// grpc - /// public GrpcSettings4Ray? grpcSettings { get; set; } - /// - /// sockopt - /// public Sockopt4Ray? sockopt { get; set; } } public class TlsSettings4Ray { - /// - /// 是否允许不安全连接(用于客户端) - /// public bool? allowInsecure { get; set; } - /// - /// - /// public string? serverName { get; set; } - /// - /// - /// public List? alpn { get; set; } public string? fingerprint { get; set; } @@ -519,115 +289,58 @@ namespace ServiceLib.Models public class TcpSettings4Ray { - /// - /// 数据包头部伪装设置 - /// public Header4Ray header { get; set; } } public class Header4Ray { - /// - /// 伪装 - /// public string type { get; set; } - /// - /// 结构复杂,直接存起来 - /// public object request { get; set; } - /// - /// 结构复杂,直接存起来 - /// public object response { get; set; } } public class KcpSettings4Ray { - /// - /// - /// public int mtu { get; set; } - /// - /// - /// public int tti { get; set; } - /// - /// - /// public int uplinkCapacity { get; set; } - /// - /// - /// public int downlinkCapacity { get; set; } - /// - /// - /// public bool congestion { get; set; } - /// - /// - /// public int readBufferSize { get; set; } - /// - /// - /// public int writeBufferSize { get; set; } - /// - /// - /// public Header4Ray header { get; set; } - /// - /// - /// public string seed { get; set; } } public class WsSettings4Ray { - /// - /// - /// public string path { get; set; } - /// - /// - /// public Headers4Ray headers { get; set; } } public class Headers4Ray { - /// - /// - /// public string Host { get; set; } - /// - /// 用户代理 - /// [JsonPropertyName("User-Agent")] public string UserAgent { get; set; } } public class HttpupgradeSettings4Ray { - /// - /// - /// public string? path { get; set; } - /// - /// - /// public string? host { get; set; } } @@ -644,32 +357,17 @@ namespace ServiceLib.Models public class HttpSettings4Ray { - /// - /// - /// public string? path { get; set; } - /// - /// - /// public List? host { get; set; } } public class QuicSettings4Ray { - /// - /// - /// public string security { get; set; } - /// - /// - /// public string key { get; set; } - /// - /// - /// public Header4Ray header { get; set; } } @@ -686,14 +384,8 @@ namespace ServiceLib.Models public class AccountsItem4Ray { - /// - /// - /// public string user { get; set; } - /// - /// - /// public string pass { get; set; } } diff --git a/v2rayN/ServiceLib/Models/V2rayMetricsVars.cs b/v2rayN/ServiceLib/Models/V2rayMetricsVars.cs new file mode 100644 index 00000000..acd4ea45 --- /dev/null +++ b/v2rayN/ServiceLib/Models/V2rayMetricsVars.cs @@ -0,0 +1,20 @@ +using System.Collections; + +namespace ServiceLib.Models +{ + internal class V2rayMetricsVars + { + public V2rayMetricsVarsStats? stats { get; set; } + } +} + +public class V2rayMetricsVarsStats +{ + public Hashtable? outbound { get; set; } +} + +public class V2rayMetricsVarsLink +{ + public long downlink { get; set; } + public long uplink { get; set; } +} \ No newline at end of file diff --git a/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigV2rayService.cs b/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigV2rayService.cs index 99acf423..ced600cf 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigV2rayService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigV2rayService.cs @@ -366,8 +366,8 @@ namespace ServiceLib.Services.CoreConfig else { v2rayConfig.log.loglevel = _config.CoreBasicItem.Loglevel; - v2rayConfig.log.access = ""; - v2rayConfig.log.error = ""; + v2rayConfig.log.access = null; + v2rayConfig.log.error = null; } } catch (Exception ex) @@ -1120,17 +1120,14 @@ namespace ServiceLib.Services.CoreConfig if (_config.GuiItem.EnableStatistics) { string tag = EInboundProtocol.api.ToString(); - API4Ray apiObj = new(); + Metrics4Ray apiObj = new(); Policy4Ray policyObj = new(); SystemPolicy4Ray policySystemSetting = new(); - string[] services = { "StatsService" }; - v2rayConfig.stats = new Stats4Ray(); apiObj.tag = tag; - apiObj.services = services.ToList(); - v2rayConfig.api = apiObj; + v2rayConfig.metrics = apiObj; policySystemSetting.statsOutboundDownlink = true; policySystemSetting.statsOutboundUplink = true; diff --git a/v2rayN/ServiceLib/Services/Statistics/StatisticsXrayService.cs b/v2rayN/ServiceLib/Services/Statistics/StatisticsXrayService.cs new file mode 100644 index 00000000..72a51905 --- /dev/null +++ b/v2rayN/ServiceLib/Services/Statistics/StatisticsXrayService.cs @@ -0,0 +1,106 @@ +namespace ServiceLib.Services.Statistics +{ + public class StatisticsXrayService + { + private const long linkBase = 1024; + private string _url; + private ServerSpeedItem _serverSpeedItem = new(); + private Config _config; + private bool _exitFlag; + private Action? _updateFunc; + + public StatisticsXrayService(Config config, Action updateFunc) + { + _config = config; + _updateFunc = updateFunc; + _exitFlag = false; + _url = $"{Global.HttpProtocol}{Global.Loopback}:{AppHandler.Instance.StatePort}/debug/vars"; + + Task.Run(Run); + } + + public void Close() + { + _exitFlag = true; + } + + private async void Run() + { + while (!_exitFlag) + { + await Task.Delay(1000); + try + { + if (!_config.IsRunningCore(ECoreType.Xray)) + { + continue; + } + + var result = await HttpClientHelper.Instance.TryGetAsync(_url); + if (result != null) + { + var server = ParseOutput(result) ?? new ServerSpeedItem(); + _updateFunc?.Invoke(server); + } + } + catch + { + // ignored + } + } + } + + private ServerSpeedItem? ParseOutput(string result) + { + try + { + var source = JsonUtils.Deserialize(result); + if (source?.stats?.outbound == null) + { + return null; + } + + ServerSpeedItem server = new(); + foreach (string key in source.stats.outbound.Keys) + { + var value = source.stats.outbound[key]; + if (value == null) continue; + var state = JsonUtils.Deserialize(value.ToString()); + + if (key.StartsWith(Global.ProxyTag)) + { + server.ProxyUp += state.uplink / linkBase; + server.ProxyDown += state.downlink / linkBase; + } + else if (key == Global.DirectTag) + { + server.DirectUp = state.uplink / linkBase; + server.DirectDown = state.downlink / linkBase; + } + } + + if (server.DirectDown < _serverSpeedItem.DirectDown || server.ProxyDown < _serverSpeedItem.ProxyDown) + { + _serverSpeedItem = new(); + return null; + } + + ServerSpeedItem curItem = new() + { + ProxyUp = server.ProxyUp - _serverSpeedItem.ProxyUp, + ProxyDown = server.ProxyDown - _serverSpeedItem.ProxyDown, + DirectUp = server.DirectUp - _serverSpeedItem.DirectUp, + DirectDown = server.DirectDown - _serverSpeedItem.DirectDown, + }; + _serverSpeedItem = server; + return curItem; + } + catch + { + // ignored + } + + return null; + } + } +} \ No newline at end of file