diff --git a/v2rayN/v2rayN/Forms/MainForm.cs b/v2rayN/v2rayN/Forms/MainForm.cs
index 6e88ea80..cb839d46 100644
--- a/v2rayN/v2rayN/Forms/MainForm.cs
+++ b/v2rayN/v2rayN/Forms/MainForm.cs
@@ -129,7 +129,7 @@ namespace v2rayN.Forms
{
e.Cancel = true;
- statistics?.saveToFile();
+ statistics?.SaveToFile();
HideForm();
return;
@@ -137,7 +137,7 @@ namespace v2rayN.Forms
if (e.CloseReason == CloseReason.ApplicationExitCall)
{
ConfigHandler.SaveConfig(ref config);
- statistics?.saveToFile();
+ statistics?.SaveToFile();
statistics?.Close();
}
}
@@ -168,7 +168,7 @@ namespace v2rayN.Forms
Utils.SaveLog("Windows shutdown UnsetProxy");
//CloseV2ray();
ConfigHandler.ToJsonFile(config);
- statistics?.saveToFile();
+ statistics?.SaveToFile();
ProxySetting.UnsetProxy();
m.Result = (IntPtr)1;
break;
diff --git a/v2rayN/v2rayN/Global.cs b/v2rayN/v2rayN/Global.cs
index 8bbab44b..eb54a2be 100644
--- a/v2rayN/v2rayN/Global.cs
+++ b/v2rayN/v2rayN/Global.cs
@@ -146,7 +146,7 @@ namespace v2rayN
public const string InboundProxyTagName = "proxy";
public const string Loopback = "127.0.0.1";
public const string InboundAPIProtocal = "dokodemo-door";
- public const uint InboundAPIPort = 10805;
+
public enum StatisticsFreshRate
{
quick = 1000,
@@ -185,6 +185,11 @@ namespace v2rayN
///
public static int pacPort { get; set; }
+ ///
+ ///
+ ///
+ public static int statePort { get; set; }
+
#endregion
diff --git a/v2rayN/v2rayN/Handler/StatisticsHandler.cs b/v2rayN/v2rayN/Handler/StatisticsHandler.cs
index ba2e948d..d25c23b0 100644
--- a/v2rayN/v2rayN/Handler/StatisticsHandler.cs
+++ b/v2rayN/v2rayN/Handler/StatisticsHandler.cs
@@ -1,16 +1,13 @@
-using System;
+using Grpc.Core;
+using System;
using System.Collections.Generic;
-using System.Diagnostics;
using System.IO;
-using System.Text;
-using System.Text.RegularExpressions;
+using System.Net;
+using System.Net.Sockets;
using System.Threading;
-
using v2rayN.Mode;
using v2rayN.Protos.Statistics;
-using Grpc.Core;
-
namespace v2rayN.Handler
{
class StatisticsHandler
@@ -63,19 +60,24 @@ namespace v2rayN.Handler
Statistic.Add(statistic);
}
- loadFromFile();
+ LoadFromFile();
- grpcInit();
+ GrpcInit();
- workThread_ = new Thread(new ThreadStart(run));
+ workThread_ = new Thread(new ThreadStart(Run));
workThread_.Start();
}
- private void grpcInit()
+ private void GrpcInit()
{
- channel_ = new Channel($"127.0.0.1:{Global.InboundAPIPort}", ChannelCredentials.Insecure);
- channel_.ConnectAsync();
- client_ = new StatsService.StatsServiceClient(channel_);
+ if (channel_ == null)
+ {
+ Global.statePort = GetFreePort();
+
+ channel_ = new Channel($"127.0.0.1:{Global.statePort}", ChannelCredentials.Insecure);
+ channel_.ConnectAsync();
+ client_ = new StatsService.StatsServiceClient(channel_);
+ }
}
public void Close()
@@ -92,7 +94,7 @@ namespace v2rayN.Handler
}
}
- public void run()
+ public void Run()
{
while (!exitFlag_)
{
@@ -120,7 +122,7 @@ namespace v2rayN.Handler
down = 0;
//TODO: parse output
- parseOutput(res.Stat, out up, out down);
+ ParseOutput(res.Stat, out up, out down);
Up = up;
Down = down;
@@ -139,10 +141,9 @@ namespace v2rayN.Handler
if (UpdateUI)
updateFunc_(TotalUp, TotalDown, Up, Down, Statistic);
}
-
- Thread.Sleep(config_.statisticsFreshRate);
- channel_.ConnectAsync();
}
+ Thread.Sleep(config_.statisticsFreshRate);
+ channel_.ConnectAsync();
}
catch (Exception ex)
{
@@ -151,7 +152,7 @@ namespace v2rayN.Handler
}
}
- public void parseOutput(Google.Protobuf.Collections.RepeatedField source, out ulong up, out ulong down)
+ public void ParseOutput(Google.Protobuf.Collections.RepeatedField source, out ulong up, out ulong down)
{
up = 0; down = 0;
@@ -189,7 +190,7 @@ namespace v2rayN.Handler
}
}
- public void saveToFile()
+ public void SaveToFile()
{
if (!Directory.Exists(logPath_))
{
@@ -249,7 +250,7 @@ namespace v2rayN.Handler
}
}
- public void loadFromFile()
+ public void LoadFromFile()
{
if (!Directory.Exists(logPath_)) return;
@@ -397,5 +398,25 @@ namespace v2rayN.Handler
Utils.SaveLog(ex.Message, ex);
}
}
+
+ private int GetFreePort()
+ {
+ int defaultPort = 28123;
+ try
+ {
+ // TCP stack please do me a favor
+ TcpListener l = new TcpListener(IPAddress.Loopback, 0);
+ l.Start();
+ var port = ((IPEndPoint)l.LocalEndpoint).Port;
+ l.Stop();
+ return port;
+ }
+ catch (Exception ex)
+ {
+ // in case access denied
+ Utils.SaveLog(ex.Message, ex);
+ return defaultPort;
+ }
+ }
}
}
diff --git a/v2rayN/v2rayN/Handler/V2rayConfigHandler.cs b/v2rayN/v2rayN/Handler/V2rayConfigHandler.cs
index bf417ab0..7f8cc0c8 100644
--- a/v2rayN/v2rayN/Handler/V2rayConfigHandler.cs
+++ b/v2rayN/v2rayN/Handler/V2rayConfigHandler.cs
@@ -631,26 +631,28 @@ namespace v2rayN.Handler
v2rayConfig.stats = new Stats();
apiObj.tag = tag;
- apiObj.services = services.ToList();
+ apiObj.services = services.ToList();
v2rayConfig.api = apiObj;
policySystemSetting.statsInboundDownlink = true;
policySystemSetting.statsInboundUplink = true;
policyObj.system = policySystemSetting;
v2rayConfig.policy = policyObj;
- if(!v2rayConfig.inbounds.Exists(item => { return item.tag == tag; }))
+
+ if (!v2rayConfig.inbounds.Exists(item => { return item.tag == tag; }))
{
var apiInbound = new Mode.Inbounds();
var apiInboundSettings = new Mode.Inboundsettings();
apiInbound.tag = tag;
apiInbound.listen = Global.Loopback;
- apiInbound.port = config.port();
+ apiInbound.port = Global.statePort;
apiInbound.protocol = Global.InboundAPIProtocal;
apiInboundSettings.address = Global.Loopback;
apiInbound.settings = apiInboundSettings;
v2rayConfig.inbounds.Add(apiInbound);
}
- if(!v2rayConfig.routing.rules.Exists(item => { return item.outboundTag == tag; }))
+
+ if (!v2rayConfig.routing.rules.Exists(item => { return item.outboundTag == tag; }))
{
var apiRoutingRule = new Mode.RulesItem();
apiRoutingRule.inboundTag = tag;
@@ -1153,14 +1155,14 @@ namespace v2rayN.Handler
vmessItem.network = Global.DefaultNetwork;
vmessItem.headerType = Global.None;
-
+
vmessItem.configVersion = Utils.ToInt(vmessQRCode.v);
vmessItem.remarks = Utils.ToString(vmessQRCode.ps);
vmessItem.address = Utils.ToString(vmessQRCode.add);
vmessItem.port = Utils.ToInt(vmessQRCode.port);
vmessItem.id = Utils.ToString(vmessQRCode.id);
vmessItem.alterId = Utils.ToInt(vmessQRCode.aid);
-
+
if (!Utils.IsNullOrEmpty(vmessQRCode.net))
{
vmessItem.network = vmessQRCode.net;
@@ -1169,7 +1171,7 @@ namespace v2rayN.Handler
{
vmessItem.headerType = vmessQRCode.type;
}
-
+
vmessItem.requestHost = Utils.ToString(vmessQRCode.host);
vmessItem.path = Utils.ToString(vmessQRCode.path);
vmessItem.streamSecurity = Utils.ToString(vmessQRCode.tls);
diff --git a/v2rayN/v2rayN/Mode/V2rayConfig.cs b/v2rayN/v2rayN/Mode/V2rayConfig.cs
index d969b539..3a25ac0d 100644
--- a/v2rayN/v2rayN/Mode/V2rayConfig.cs
+++ b/v2rayN/v2rayN/Mode/V2rayConfig.cs
@@ -21,40 +21,14 @@ namespace v2rayN.Mode
///
public List outbounds { get; set; }
- /// 网速统计
- /// 使用v2ray api功能
- ///
- /// routing->rules 需要加上这一条
- /// {
- /// "inboundTag": [
- /// "api"
- /// ],
- /// "outboundTag": "api",
- /// "type": "field"
- /// }
-
///
/// 统计需要, 空对象
///
public Stats stats { get; set; }
-
- ///
- /// 需要tag和services
- /// "api": {
- /// "tag": "api",
- /// "services": [
- /// "StatsService"
- /// ]
- /// }
+
///
public API api { get; set; }
- ///
- /// policy 都设置为true;
- /// "system": {
- /// "statsInboundUplink": true,
- /// "statsInboundDownlink": true
- /// }
///
public Policy policy;
diff --git a/v2rayN/v2rayN/Properties/AssemblyInfo.cs b/v2rayN/v2rayN/Properties/AssemblyInfo.cs
index 12067001..e7cbee3a 100644
--- a/v2rayN/v2rayN/Properties/AssemblyInfo.cs
+++ b/v2rayN/v2rayN/Properties/AssemblyInfo.cs
@@ -33,4 +33,4 @@ using System.Runtime.InteropServices;
// 方法是按如下所示使用“*”:
//[assembly: AssemblyVersion("1.0.*")]
//[assembly: AssemblyVersion("1.0.0")]
-[assembly: AssemblyFileVersion("2.37")]
+[assembly: AssemblyFileVersion("2.38")]
diff --git a/v2rayN/v2rayN/Sample/SampleClientConfig.txt b/v2rayN/v2rayN/Sample/SampleClientConfig.txt
index 2b134ca3..11572d8a 100644
--- a/v2rayN/v2rayN/Sample/SampleClientConfig.txt
+++ b/v2rayN/v2rayN/Sample/SampleClientConfig.txt
@@ -1,17 +1,4 @@
-{
- "stats": {},
- "api": {
- "tag": "api",
- "services": [
- "StatsService"
- ]
- },
- "policy": {
- "system": {
- "statsInboundUplink": true,
- "statsInboundDownlink": true
- }
- },
+{
"log": {
"access": "",
"error": "",
@@ -39,16 +26,7 @@
"tls"
]
}
- },
- {
- "listen": "127.0.0.1",
- "port": 10805,
- "protocol": "dokodemo-door",
- "settings": {
- "address": "127.0.0.1"
- },
- "tag": "api"
- }
+ }
],
"outbounds": [{
"tag": "proxy",