From 815826c85688b0e8fdafc151ff176ba1c0a388f6 Mon Sep 17 00:00:00 2001
From: 2dust <31833384+2dust@users.noreply.github.com>
Date: Mon, 11 Apr 2022 15:26:32 +0800
Subject: [PATCH] Refactor download/update/speedtest
---
v2rayN/v2rayN/Base/HttpClientHelper.cs | 226 ++++++++++++++++
v2rayN/v2rayN/Base/WebClientEx.cs | 37 ---
v2rayN/v2rayN/Forms/MainForm.Designer.cs | 23 +-
v2rayN/v2rayN/Forms/MainForm.cs | 38 +--
v2rayN/v2rayN/Forms/MainForm.resx | 54 ++--
v2rayN/v2rayN/Forms/RoutingRuleSettingForm.cs | 19 +-
v2rayN/v2rayN/Handler/DownloadHandle.cs | 253 +++++++++---------
v2rayN/v2rayN/Handler/LazyConfig.cs | 7 +-
v2rayN/v2rayN/Handler/SpeedtestHandler.cs | 89 +-----
v2rayN/v2rayN/Handler/UpdateHandle.cs | 149 ++++-------
v2rayN/v2rayN/Mode/CoreInfo.cs | 2 +
v2rayN/v2rayN/v2rayN.csproj | 4 +-
12 files changed, 478 insertions(+), 423 deletions(-)
create mode 100644 v2rayN/v2rayN/Base/HttpClientHelper.cs
delete mode 100644 v2rayN/v2rayN/Base/WebClientEx.cs
diff --git a/v2rayN/v2rayN/Base/HttpClientHelper.cs b/v2rayN/v2rayN/Base/HttpClientHelper.cs
new file mode 100644
index 00000000..2fa75a24
--- /dev/null
+++ b/v2rayN/v2rayN/Base/HttpClientHelper.cs
@@ -0,0 +1,226 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace v2rayN.Base
+{
+ ///
+ ///
+ public class HttpClientHelper
+ {
+ private static HttpClientHelper httpClientHelper = null;
+ private HttpClient httpClient;
+ private int progressPercentage = -1;
+
+ ///
+ ///
+ private HttpClientHelper() { }
+
+ ///
+ ///
+ ///
+ public static HttpClientHelper GetInstance()
+ {
+ if (httpClientHelper != null)
+ {
+ return httpClientHelper;
+ }
+ else
+ {
+ HttpClientHelper httpClientHelper = new HttpClientHelper();
+
+ HttpClientHandler handler = new HttpClientHandler() { UseCookies = false };
+ httpClientHelper.httpClient = new HttpClient(handler);
+ return httpClientHelper;
+ }
+ }
+ public async Task GetAsync(string url)
+ {
+ if (string.IsNullOrEmpty(url))
+ {
+ return null;
+ }
+ try
+ {
+ HttpResponseMessage response = await httpClient.GetAsync(url);
+
+ return await response.Content.ReadAsStringAsync();
+ }
+ catch
+ {
+ }
+ return null;
+ }
+ public async Task GetAsync(HttpClient client, string url)
+ {
+ if (string.IsNullOrEmpty(url))
+ {
+ return null;
+ }
+ try
+ {
+ var cts = new CancellationTokenSource();
+ cts.CancelAfter(5000);
+
+ HttpResponseMessage response = await client.GetAsync(url, cts.Token);
+ return await response.Content.ReadAsStringAsync();
+ }
+ catch (Exception ex)
+ {
+ Utils.SaveLog("GetAsync", ex);
+ }
+ return null;
+ }
+
+ public async Task PutAsync(string url, Dictionary headers)
+ {
+ var myContent = Utils.ToJson(headers);
+ var buffer = System.Text.Encoding.UTF8.GetBytes(myContent);
+ var byteContent = new ByteArrayContent(buffer);
+ byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
+
+ var result = await httpClient.PutAsync(url, byteContent);
+ }
+
+ public async Task DownloadFileAsync(HttpClient client, string url, string fileName, IProgress progress, CancellationToken token)
+ {
+ if (string.IsNullOrEmpty(url))
+ {
+ throw new ArgumentNullException("url");
+ }
+ if (string.IsNullOrEmpty(fileName))
+ {
+ throw new ArgumentNullException("fileName");
+ }
+ if (File.Exists(fileName))
+ {
+ File.Delete(fileName);
+ }
+
+ var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token);
+
+ if (!response.IsSuccessStatusCode)
+ {
+ throw new Exception(string.Format("The request returned with HTTP status code {0}", response.StatusCode));
+ }
+
+ var total = response.Content.Headers.ContentLength.HasValue ? response.Content.Headers.ContentLength.Value : -1L;
+ var canReportProgress = total != -1 && progress != null;
+
+ using (var stream = await response.Content.ReadAsStreamAsync())
+ {
+ using (var file = File.Create(fileName))
+ {
+ var totalRead = 0L;
+ var buffer = new byte[1024 * 1024];
+ var isMoreToRead = true;
+ progressPercentage = -1;
+
+ do
+ {
+ token.ThrowIfCancellationRequested();
+
+ var read = await stream.ReadAsync(buffer, 0, buffer.Length, token);
+
+ if (read == 0)
+ {
+ isMoreToRead = false;
+ }
+ else
+ {
+ var data = new byte[read];
+ buffer.ToList().CopyTo(0, data, 0, read);
+
+ // TODO: put here the code to write the file to disk
+ file.Write(data, 0, read);
+
+ totalRead += read;
+
+ if (canReportProgress)
+ {
+ var percent = Convert.ToInt32((totalRead * 1d) / (total * 1d) * 100);
+ if (progressPercentage != percent && percent % 10 == 0)
+ {
+ progressPercentage = percent;
+ progress.Report(percent);
+ }
+ }
+ }
+ } while (isMoreToRead);
+ file.Close();
+ if (canReportProgress)
+ {
+ progress.Report(101);
+
+ }
+ }
+ }
+ }
+
+ public async Task DownloadDataAsync4Speed(HttpClient client, string url, IProgress progress, CancellationToken token)
+ {
+ if (string.IsNullOrEmpty(url))
+ {
+ throw new ArgumentNullException("url");
+ }
+
+ var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token);
+
+ if (!response.IsSuccessStatusCode)
+ {
+ throw new Exception(string.Format("The request returned with HTTP status code {0}", response.StatusCode));
+ }
+
+ var total = response.Content.Headers.ContentLength.HasValue ? response.Content.Headers.ContentLength.Value : -1L;
+ var canReportProgress = total != -1 && progress != null;
+
+ using (var stream = await response.Content.ReadAsStreamAsync())
+ {
+ var totalRead = 0L;
+ var buffer = new byte[1024 * 1024];
+ var isMoreToRead = true;
+ progressPercentage = -1;
+ DateTime totalDatetime = DateTime.Now;
+
+ do
+ {
+ token.ThrowIfCancellationRequested();
+
+ var read = await stream.ReadAsync(buffer, 0, buffer.Length, token);
+
+ if (read == 0)
+ {
+ isMoreToRead = false;
+ }
+ else
+ {
+ var data = new byte[read];
+ buffer.ToList().CopyTo(0, data, 0, read);
+
+ // TODO:
+ totalRead += read;
+
+ if (canReportProgress)
+ {
+ TimeSpan ts = (DateTime.Now - totalDatetime);
+ var speed = totalRead * 1d / ts.TotalMilliseconds / 1000;
+ var percent = Convert.ToInt32((totalRead * 1d) / (total * 1d) * 100);
+ if (progressPercentage != percent && percent % 5 == 0)
+ {
+ progressPercentage = percent;
+ progress.Report(speed);
+ }
+ }
+ }
+ } while (isMoreToRead);
+ }
+ }
+
+ }
+}
diff --git a/v2rayN/v2rayN/Base/WebClientEx.cs b/v2rayN/v2rayN/Base/WebClientEx.cs
deleted file mode 100644
index 096826cc..00000000
--- a/v2rayN/v2rayN/Base/WebClientEx.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-using System;
-using System.Net;
-
-namespace v2rayN.Base
-{
- class WebClientEx : WebClient
- {
- public int Timeout
- {
- get; set;
- }
- public WebClientEx(int timeout = 3000)
- {
- Timeout = timeout;
- }
-
- protected override WebRequest GetWebRequest(Uri address)
- {
- HttpWebRequest request;
- request = (HttpWebRequest)base.GetWebRequest(address);
- request.Timeout = Timeout;
- request.ReadWriteTimeout = Timeout;
- //request.AllowAutoRedirect = false;
- //request.AllowWriteStreamBuffering = true;
-
- request.ServicePoint.BindIPEndPointDelegate = (servicePoint, remoteEndPoint, retryCount) =>
- {
- if (remoteEndPoint.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6)
- return new IPEndPoint(IPAddress.IPv6Any, 0);
- else
- return new IPEndPoint(IPAddress.Any, 0);
- };
-
- return request;
- }
- }
-}
diff --git a/v2rayN/v2rayN/Forms/MainForm.Designer.cs b/v2rayN/v2rayN/Forms/MainForm.Designer.cs
index 39988104..846d1ea9 100644
--- a/v2rayN/v2rayN/Forms/MainForm.Designer.cs
+++ b/v2rayN/v2rayN/Forms/MainForm.Designer.cs
@@ -126,8 +126,7 @@
this.tsbCheckUpdateCore = new System.Windows.Forms.ToolStripMenuItem();
this.tsbCheckUpdateXrayCore = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator15 = new System.Windows.Forms.ToolStripSeparator();
- this.tsbCheckUpdateGeoSite = new System.Windows.Forms.ToolStripMenuItem();
- this.tsbCheckUpdateGeoIP = new System.Windows.Forms.ToolStripMenuItem();
+ this.tsbCheckUpdateGeo = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator10 = new System.Windows.Forms.ToolStripSeparator();
this.tsbHelp = new System.Windows.Forms.ToolStripDropDownButton();
this.tsbAbout = new System.Windows.Forms.ToolStripMenuItem();
@@ -831,8 +830,7 @@
this.tsbCheckUpdateCore,
this.tsbCheckUpdateXrayCore,
this.toolStripSeparator15,
- this.tsbCheckUpdateGeoSite,
- this.tsbCheckUpdateGeoIP});
+ this.tsbCheckUpdateGeo});
this.tsbCheckUpdate.Image = global::v2rayN.Properties.Resources.checkupdate;
resources.ApplyResources(this.tsbCheckUpdate, "tsbCheckUpdate");
this.tsbCheckUpdate.Name = "tsbCheckUpdate";
@@ -860,17 +858,11 @@
this.toolStripSeparator15.Name = "toolStripSeparator15";
resources.ApplyResources(this.toolStripSeparator15, "toolStripSeparator15");
//
- // tsbCheckUpdateGeoSite
+ // tsbCheckUpdateGeo
//
- this.tsbCheckUpdateGeoSite.Name = "tsbCheckUpdateGeoSite";
- resources.ApplyResources(this.tsbCheckUpdateGeoSite, "tsbCheckUpdateGeoSite");
- this.tsbCheckUpdateGeoSite.Click += new System.EventHandler(this.tsbCheckUpdateGeoSite_Click);
- //
- // tsbCheckUpdateGeoIP
- //
- this.tsbCheckUpdateGeoIP.Name = "tsbCheckUpdateGeoIP";
- resources.ApplyResources(this.tsbCheckUpdateGeoIP, "tsbCheckUpdateGeoIP");
- this.tsbCheckUpdateGeoIP.Click += new System.EventHandler(this.tsbCheckUpdateGeoIP_Click);
+ this.tsbCheckUpdateGeo.Name = "tsbCheckUpdateGeo";
+ resources.ApplyResources(this.tsbCheckUpdateGeo, "tsbCheckUpdateGeo");
+ this.tsbCheckUpdateGeo.Click += new System.EventHandler(this.tsbCheckUpdateGeo_Click);
//
// toolStripSeparator10
//
@@ -1071,8 +1063,7 @@
private System.Windows.Forms.ToolStripSeparator toolStripSeparator14;
private System.Windows.Forms.ToolStripMenuItem tsbBackupGuiNConfig;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator15;
- private System.Windows.Forms.ToolStripMenuItem tsbCheckUpdateGeoSite;
- private System.Windows.Forms.ToolStripMenuItem tsbCheckUpdateGeoIP;
+ private System.Windows.Forms.ToolStripMenuItem tsbCheckUpdateGeo;
private System.Windows.Forms.SplitContainer splitContainer1;
private System.Windows.Forms.ToolStripMenuItem menuMsgBoxFilter;
private System.Windows.Forms.ToolStripStatusLabel toolSslInboundInfo;
diff --git a/v2rayN/v2rayN/Forms/MainForm.cs b/v2rayN/v2rayN/Forms/MainForm.cs
index ddb014c7..cee1f2aa 100644
--- a/v2rayN/v2rayN/Forms/MainForm.cs
+++ b/v2rayN/v2rayN/Forms/MainForm.cs
@@ -413,7 +413,7 @@ namespace v2rayN.Forms
}
private void lvServers_SelectedIndexChanged(object sender, EventArgs e)
- {
+ {
}
private void ssMain_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
@@ -781,13 +781,12 @@ namespace v2rayN.Forms
{
if (GetLvSelectedIndex() < 0) return;
ClearTestResult();
- SpeedtestHandler statistics = new SpeedtestHandler(ref config, v2rayHandler, lstSelecteds, actionType, UpdateSpeedtestHandler);
+ SpeedtestHandler statistics = new SpeedtestHandler(config, v2rayHandler, lstSelecteds, actionType, UpdateSpeedtestHandler);
}
private void tsbTestMe_Click(object sender, EventArgs e)
{
- SpeedtestHandler statistics = new SpeedtestHandler(ref config);
- string result = statistics.RunAvailabilityCheck() + "ms";
+ string result = (new DownloadHandle()).RunAvailabilityCheck(null) + "ms";
AppendText(false, string.Format(ResUI.TestMeOutput, result));
}
@@ -1197,6 +1196,10 @@ namespace v2rayN.Forms
lstVmess[k].testResult = txt;
lvServers.Items[k].SubItems["testResult"].Text = txt;
}
+ else
+ {
+ AppendText(false, txt);
+ }
}
private void SetTestResult(int k, string txt)
{
@@ -1248,7 +1251,7 @@ namespace v2rayN.Forms
lvServers.EndUpdate();
});
}
-
+
}
catch (Exception ex)
{
@@ -1418,31 +1421,16 @@ namespace v2rayN.Forms
(new UpdateHandle()).CheckUpdateCore(type, config, _updateUI);
}
- private void tsbCheckUpdateGeoSite_Click(object sender, EventArgs e)
+ private void tsbCheckUpdateGeo_Click(object sender, EventArgs e)
{
- (new UpdateHandle()).UpdateGeoFile("geosite", config, (bool success, string msg) =>
+ Task.Run(() =>
{
- AppendText(false, msg);
- if (success)
- {
- Global.reloadV2ray = true;
- _ = LoadV2ray();
- }
+ var updateHandle = new UpdateHandle();
+ updateHandle.UpdateGeoFile("geosite", config, UpdateTaskHandler);
+ updateHandle.UpdateGeoFile("geoip", config, UpdateTaskHandler);
});
}
- private void tsbCheckUpdateGeoIP_Click(object sender, EventArgs e)
- {
- (new UpdateHandle()).UpdateGeoFile("geoip", config, (bool success, string msg) =>
- {
- AppendText(false, msg);
- if (success)
- {
- Global.reloadV2ray = true;
- _ = LoadV2ray();
- }
- });
- }
#endregion
#region Help
diff --git a/v2rayN/v2rayN/Forms/MainForm.resx b/v2rayN/v2rayN/Forms/MainForm.resx
index c096011a..d952d26b 100644
--- a/v2rayN/v2rayN/Forms/MainForm.resx
+++ b/v2rayN/v2rayN/Forms/MainForm.resx
@@ -321,7 +321,7 @@
ImageAboveText
- 356, 666
+ 356, 644
cmsLv
@@ -750,19 +750,19 @@
Do not change system proxy
- 264, 22
+ 277, 22
System proxy
- 264, 22
+ 277, 22
Routing
- 264, 22
+ 277, 22
Server
@@ -780,43 +780,43 @@
Server
- 261, 6
+ 274, 6
- 264, 22
+ 277, 22
Import bulk URL from clipboard
- 264, 22
+ 277, 22
Scan QR code on the screen
- 264, 22
+ 277, 22
Update subscription without proxy
- 264, 22
+ 277, 22
Update subscriptions via proxy
- 261, 6
+ 274, 6
- 264, 22
+ 277, 22
Exit
- 265, 221
+ 278, 221
cmsMain
@@ -861,19 +861,19 @@
6, 56
- 182, 22
+ 277, 22
Settings
- 182, 22
+ 277, 22
Update subscription without proxy
- 182, 22
+ 277, 22
Update subscription with proxy
@@ -995,17 +995,11 @@
200, 6
-
+
203, 22
-
- Update GeoSite
-
-
- 203, 22
-
-
- Update GeoIP
+
+ Update Geo files
Magenta
@@ -1619,16 +1613,10 @@
System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
- tsbCheckUpdateGeoSite
+
+ tsbCheckUpdateGeo
-
- System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- tsbCheckUpdateGeoIP
-
-
+
System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
diff --git a/v2rayN/v2rayN/Forms/RoutingRuleSettingForm.cs b/v2rayN/v2rayN/Forms/RoutingRuleSettingForm.cs
index 4db5d2fe..d7a7dc37 100644
--- a/v2rayN/v2rayN/Forms/RoutingRuleSettingForm.cs
+++ b/v2rayN/v2rayN/Forms/RoutingRuleSettingForm.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Threading.Tasks;
using System.Windows.Forms;
using v2rayN.Base;
using v2rayN.Handler;
@@ -345,13 +346,17 @@ namespace v2rayN.Forms
UI.Show(ResUI.MsgNeedUrl);
return;
}
- DownloadHandle downloadHandle = new DownloadHandle();
- string clipboardData = downloadHandle.WebDownloadStringSync(url);
- if (AddBatchRoutingRules(ref routingItem, clipboardData) == 0)
+
+ Task.Run(async () =>
{
- RefreshRoutingsView();
- UI.Show(ResUI.OperationSuccess);
- }
+ DownloadHandle downloadHandle = new DownloadHandle();
+ string result = await downloadHandle.DownloadStringAsync(url, false, "");
+ if (AddBatchRoutingRules(ref routingItem, result) == 0)
+ {
+ RefreshRoutingsView();
+ UI.Show(ResUI.OperationSuccess);
+ }
+ });
}
private int AddBatchRoutingRules(ref RoutingItem routingItem, string clipboardData)
{
@@ -363,8 +368,6 @@ namespace v2rayN.Forms
return ConfigHandler.AddBatchRoutingRules(ref routingItem, clipboardData, blReplace);
}
-
-
#endregion
}
diff --git a/v2rayN/v2rayN/Handler/DownloadHandle.cs b/v2rayN/v2rayN/Handler/DownloadHandle.cs
index 5b84224f..398b2773 100644
--- a/v2rayN/v2rayN/Handler/DownloadHandle.cs
+++ b/v2rayN/v2rayN/Handler/DownloadHandle.cs
@@ -1,7 +1,12 @@
using System;
+using System.Diagnostics;
using System.IO;
using System.Net;
+using System.Net.Http;
+using System.Net.Http.Headers;
using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
using v2rayN.Base;
using v2rayN.Resx;
@@ -29,97 +34,71 @@ namespace v2rayN.Handler
}
}
- private int progressPercentage = -1;
- private long totalBytesToReceive = 0;
- private DateTime totalDatetime = new DateTime();
- private int DownloadTimeout = -1;
-
- public WebClientEx DownloadFileAsync(string url, WebProxy webProxy, int downloadTimeout)
+ public async Task DownloadDataAsync(string url, WebProxy webProxy, int downloadTimeout)
{
- WebClientEx ws = new WebClientEx();
try
{
Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().enableSecurityProtocolTls13);
UpdateCompleted?.Invoke(this, new ResultEventArgs(false, ResUI.Downloading));
- progressPercentage = -1;
- totalBytesToReceive = 0;
-
- //WebClientEx ws = new WebClientEx();
- DownloadTimeout = downloadTimeout;
- if (webProxy != null)
+ var client = new HttpClient(new WebRequestHandler()
{
- ws.Proxy = webProxy;// new WebProxy(Global.Loopback, Global.httpPort);
- }
+ Proxy = webProxy
+ });
- ws.DownloadFileCompleted += ws_DownloadFileCompleted;
- ws.DownloadProgressChanged += ws_DownloadProgressChanged;
- ws.DownloadFileAsync(new Uri(url), Utils.GetPath(Utils.GetDownloadFileName(url)));
+ var progress = new Progress();
+ progress.ProgressChanged += (sender, value) =>
+ {
+ if (UpdateCompleted != null)
+ {
+ string msg = string.Format("{0} M/s", value.ToString("#0.0"));
+ UpdateCompleted(this, new ResultEventArgs(false, msg));
+ }
+ };
+
+ var cancellationToken = new CancellationTokenSource();
+ cancellationToken.CancelAfter(downloadTimeout * 1000);
+ await HttpClientHelper.GetInstance().DownloadDataAsync4Speed(client,
+ url,
+ progress,
+ cancellationToken.Token);
}
catch (Exception ex)
{
- Utils.SaveLog(ex.Message, ex);
-
+ //Utils.SaveLog(ex.Message, ex);
Error?.Invoke(this, new ErrorEventArgs(ex));
}
- return ws;
+ return 0;
}
- void ws_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
- {
- if (UpdateCompleted != null)
- {
- if (totalBytesToReceive == 0)
- {
- totalDatetime = DateTime.Now;
- totalBytesToReceive = e.BytesReceived;
- return;
- }
- totalBytesToReceive = e.BytesReceived;
-
- if (DownloadTimeout != -1)
- {
- if ((DateTime.Now - totalDatetime).TotalSeconds > DownloadTimeout)
- {
- ((WebClientEx)sender).CancelAsync();
- }
- }
- if (progressPercentage != e.ProgressPercentage && e.ProgressPercentage % 10 == 0)
- {
- progressPercentage = e.ProgressPercentage;
- string msg = string.Format("...{0}%", e.ProgressPercentage);
- UpdateCompleted(this, new ResultEventArgs(false, msg));
- }
- }
- }
- void ws_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
+ public void DownloadFileAsync(string url, bool blProxy, int downloadTimeout)
{
try
{
- if (UpdateCompleted != null)
- {
- if (e.Cancelled)
- {
- ((WebClientEx)sender).Dispose();
- TimeSpan ts = (DateTime.Now - totalDatetime);
- string speed = string.Format("{0} M/s", (totalBytesToReceive / ts.TotalMilliseconds / 1000).ToString("#0.0"));
- UpdateCompleted(this, new ResultEventArgs(true, speed.PadLeft(8, ' ')));
- return;
- }
+ Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().enableSecurityProtocolTls13);
+ UpdateCompleted?.Invoke(this, new ResultEventArgs(false, ResUI.Downloading));
- if (e.Error == null
- || Utils.IsNullOrEmpty(e.Error.ToString()))
+ var client = new HttpClient(new WebRequestHandler()
+ {
+ Proxy = GetWebProxy(blProxy)
+ });
+
+ var progress = new Progress();
+ progress.ProgressChanged += (sender, value) =>
+ {
+ if (UpdateCompleted != null)
{
- ((WebClientEx)sender).Dispose();
- TimeSpan ts = (DateTime.Now - totalDatetime);
- string speed = string.Format("{0} M/s", (totalBytesToReceive / ts.TotalMilliseconds / 1000).ToString("#0.0"));
- UpdateCompleted(this, new ResultEventArgs(true, speed.PadLeft(8, ' ')));
+ string msg = string.Format("...{0}%", value);
+ UpdateCompleted(this, new ResultEventArgs(value > 100 ? true : false, msg));
}
- else
- {
- throw e.Error;
- }
- }
+ };
+
+ var cancellationToken = new CancellationTokenSource();
+ _ = HttpClientHelper.GetInstance().DownloadFileAsync(client,
+ url,
+ Utils.GetPath(Utils.GetDownloadFileName(url)),
+ progress,
+ cancellationToken.Token);
}
catch (Exception ex)
{
@@ -129,115 +108,143 @@ namespace v2rayN.Handler
}
}
+ public async Task UrlRedirectAsync(string url, bool blProxy)
+ {
+ Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().enableSecurityProtocolTls13);
+ WebRequestHandler webRequestHandler = new WebRequestHandler
+ {
+ AllowAutoRedirect = false,
+ Proxy = GetWebProxy(blProxy)
+ };
+ HttpClient client = new HttpClient(webRequestHandler);
+
+ HttpResponseMessage response = await client.GetAsync(url);
+ if (response.StatusCode.ToString() == "Redirect")
+ {
+ return response.Headers.Location.ToString();
+ }
+ else
+ {
+ Utils.SaveLog("StatusCode error: " + url);
+ return null;
+ }
+ }
+
///
/// DownloadString
///
///
- public void WebDownloadString(string url, WebProxy webProxy, string userAgent)
+ public async Task DownloadStringAsync(string url, bool blProxy, string userAgent)
{
- string source = string.Empty;
try
{
Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().enableSecurityProtocolTls13);
-
- WebClientEx ws = new WebClientEx();
- ws.Encoding = Encoding.UTF8;
- if (webProxy != null)
+ var client = new HttpClient(new WebRequestHandler()
{
- ws.Proxy = webProxy;
- }
+ Proxy = GetWebProxy(blProxy)
+ });
if (Utils.IsNullOrEmpty(userAgent))
{
userAgent = $"{Utils.GetVersion(false)}";
}
- ws.Headers.Add("user-agent", userAgent);
+ client.DefaultRequestHeaders.UserAgent.TryParseAdd(userAgent);
Uri uri = new Uri(url);
//Authorization Header
if (!Utils.IsNullOrEmpty(uri.UserInfo))
{
- ws.Headers.Add(HttpRequestHeader.Authorization, "Basic " + Utils.Base64Encode(uri.UserInfo));
+ client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Utils.Base64Encode(uri.UserInfo));
}
-
- ws.DownloadStringCompleted += Ws_DownloadStringCompleted;
- ws.DownloadStringAsync(uri);
+ var result = await HttpClientHelper.GetInstance().GetAsync(client, url);
+ return result;
}
catch (Exception ex)
{
Utils.SaveLog(ex.Message, ex);
}
+ return null;
}
- private void Ws_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
+ public int RunAvailabilityCheck(WebProxy webProxy)
{
try
{
- if (e.Error == null
- || Utils.IsNullOrEmpty(e.Error.ToString()))
+ if (webProxy == null)
{
- string source = e.Result;
- UpdateCompleted?.Invoke(this, new ResultEventArgs(true, source));
+ var httpPort = LazyConfig.Instance.GetConfig().GetLocalPort(Global.InboundHttp2);
+ webProxy = new WebProxy(Global.Loopback, httpPort);
}
- else
+
+ Task t = Task.Run(() =>
{
- throw e.Error;
- }
+ try
+ {
+ string status = GetRealPingTime(Global.SpeedPingTestUrl, webProxy, out int responseTime);
+ bool noError = Utils.IsNullOrEmpty(status);
+ return noError ? responseTime : -1;
+ }
+ catch (Exception ex)
+ {
+ Utils.SaveLog(ex.Message, ex);
+ return -1;
+ }
+ });
+ return t.Result;
}
catch (Exception ex)
{
Utils.SaveLog(ex.Message, ex);
-
- Error?.Invoke(this, new ErrorEventArgs(ex));
+ return -1;
}
}
- public string WebDownloadStringSync(string url)
+ public string GetRealPingTime(string url, WebProxy webProxy, out int responseTime)
{
- string source = string.Empty;
+ string msg = string.Empty;
+ responseTime = -1;
try
{
- Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().enableSecurityProtocolTls13);
+ HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(url);
+ myHttpWebRequest.Timeout = 5000;
+ myHttpWebRequest.Proxy = webProxy;
- WebClientEx ws = new WebClientEx();
- ws.Encoding = Encoding.UTF8;
- return ws.DownloadString(new Uri(url));
+ Stopwatch timer = new Stopwatch();
+ timer.Start();
+
+ HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
+ if (myHttpWebResponse.StatusCode != HttpStatusCode.OK
+ && myHttpWebResponse.StatusCode != HttpStatusCode.NoContent)
+ {
+ msg = myHttpWebResponse.StatusDescription;
+ }
+ timer.Stop();
+ responseTime = timer.Elapsed.Milliseconds;
+
+ myHttpWebResponse.Close();
}
catch (Exception ex)
{
Utils.SaveLog(ex.Message, ex);
- return string.Empty;
+ msg = ex.Message;
}
+ return msg;
}
- public WebClientEx DownloadDataAsync(string url, WebProxy webProxy, int downloadTimeout)
+ private WebProxy GetWebProxy(bool blProxy)
{
- WebClientEx ws = new WebClientEx();
- try
+ if (!blProxy)
{
- Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().enableSecurityProtocolTls13);
- UpdateCompleted?.Invoke(this, new ResultEventArgs(false, ResUI.Downloading));
-
- progressPercentage = -1;
- totalBytesToReceive = 0;
-
- DownloadTimeout = downloadTimeout;
- if (webProxy != null)
- {
- ws.Proxy = webProxy;
- }
-
- ws.DownloadProgressChanged += ws_DownloadProgressChanged;
- ws.DownloadDataCompleted += ws_DownloadFileCompleted;
- ws.DownloadDataAsync(new Uri(url));
+ return null;
}
- catch (Exception ex)
+ var httpPort = LazyConfig.Instance.GetConfig().GetLocalPort(Global.InboundHttp2);
+ var webProxy = new WebProxy(Global.Loopback, httpPort);
+ if (RunAvailabilityCheck(webProxy) > 0)
{
- Utils.SaveLog(ex.Message, ex);
-
- Error?.Invoke(this, new ErrorEventArgs(ex));
+ return webProxy;
}
- return ws;
+
+ return null;
}
}
}
diff --git a/v2rayN/v2rayN/Handler/LazyConfig.cs b/v2rayN/v2rayN/Handler/LazyConfig.cs
index ceccc7f3..98b65c51 100644
--- a/v2rayN/v2rayN/Handler/LazyConfig.cs
+++ b/v2rayN/v2rayN/Handler/LazyConfig.cs
@@ -71,8 +71,8 @@ namespace v2rayN.Handler
coreType = ECoreType.v2fly,
coreExes = new List { "wv2ray", "v2ray" },
arguments = "",
- coreUrl = Global.v2flyCoreUrl
-
+ coreUrl = Global.v2flyCoreUrl,
+ match = "V2Ray"
});
coreInfos.Add(new CoreInfo
@@ -80,7 +80,8 @@ namespace v2rayN.Handler
coreType = ECoreType.Xray,
coreExes = new List { "xray" },
arguments = "",
- coreUrl = Global.xrayCoreUrl
+ coreUrl = Global.xrayCoreUrl,
+ match = "Xray"
});
coreInfos.Add(new CoreInfo
diff --git a/v2rayN/v2rayN/Handler/SpeedtestHandler.cs b/v2rayN/v2rayN/Handler/SpeedtestHandler.cs
index c1ea28cf..39199ef8 100644
--- a/v2rayN/v2rayN/Handler/SpeedtestHandler.cs
+++ b/v2rayN/v2rayN/Handler/SpeedtestHandler.cs
@@ -17,12 +17,12 @@ namespace v2rayN.Handler
private List _selecteds;
Action _updateFunc;
- public SpeedtestHandler(ref Config config)
+ public SpeedtestHandler(Config config)
{
_config = config;
}
- public SpeedtestHandler(ref Config config, V2rayHandler v2rayHandler, List selecteds, ESpeedActionType actionType, Action update)
+ public SpeedtestHandler(Config config, V2rayHandler v2rayHandler, List selecteds, ESpeedActionType actionType, Action update)
{
_config = config;
_v2rayHandler = v2rayHandler;
@@ -55,7 +55,7 @@ namespace v2rayN.Handler
}
else if (actionType == ESpeedActionType.Speedtest)
{
- Task.Run(() => RunSpeedTest());
+ Task.Run(() => RunSpeedTestAsync());
}
}
@@ -71,7 +71,7 @@ namespace v2rayN.Handler
}
try
{
- updateFun(it);
+ Task.Run(() => updateFun(it));
}
catch (Exception ex)
{
@@ -122,6 +122,7 @@ namespace v2rayN.Handler
return;
}
+ DownloadHandle downloadHandle = new DownloadHandle();
//Thread.Sleep(5000);
List tasks = new List();
foreach (var it in _selecteds)
@@ -140,7 +141,7 @@ namespace v2rayN.Handler
{
WebProxy webProxy = new WebProxy(Global.Loopback, it.port);
int responseTime = -1;
- string status = GetRealPingTime(_config.constItem.speedPingTestUrl, webProxy, out responseTime);
+ string status = downloadHandle.GetRealPingTime(_config.constItem.speedPingTestUrl, webProxy, out responseTime);
string output = Utils.IsNullOrEmpty(status) ? FormatOut(responseTime, "ms") : status;
_config.GetVmessItem(it.indexId)?.SetTestResult(output);
@@ -165,38 +166,7 @@ namespace v2rayN.Handler
}
}
- public int RunAvailabilityCheck() // alias: isLive
- {
- try
- {
- int httpPort = _config.GetLocalPort(Global.InboundHttp2);
-
- Task t = Task.Run(() =>
- {
- try
- {
- WebProxy webProxy = new WebProxy(Global.Loopback, httpPort);
- int responseTime = -1;
- string status = GetRealPingTime(Global.SpeedPingTestUrl, webProxy, out responseTime);
- bool noError = Utils.IsNullOrEmpty(status);
- return noError ? responseTime : -1;
- }
- catch (Exception ex)
- {
- Utils.SaveLog(ex.Message, ex);
- return -1;
- }
- });
- return t.Result;
- }
- catch (Exception ex)
- {
- Utils.SaveLog(ex.Message, ex);
- return -1;
- }
- }
-
- private void RunSpeedTest()
+ private async Task RunSpeedTestAsync()
{
string testIndexId = string.Empty;
int pid = -1;
@@ -217,10 +187,10 @@ namespace v2rayN.Handler
};
downloadHandle2.Error += (sender2, args) =>
{
- _updateFunc(testIndexId, args.GetException().Message);
+ _updateFunc("", args.GetException().Message);
};
- var timeout = 10;
+ var timeout = 8;
foreach (var it in _selecteds)
{
if (!it.allowTest)
@@ -235,15 +205,9 @@ namespace v2rayN.Handler
if (_config.FindIndexId(it.indexId) < 0) continue;
WebProxy webProxy = new WebProxy(Global.Loopback, it.port);
- var ws = downloadHandle2.DownloadDataAsync(url, webProxy, timeout - 2);
-
- Thread.Sleep(1000 * timeout);
-
- ws.CancelAsync();
- ws.Dispose();
-
- Thread.Sleep(1000 * 2);
+ await downloadHandle2.DownloadDataAsync(url, webProxy, timeout);
}
+
if (pid > 0) _v2rayHandler.V2rayStopPid(pid);
}
@@ -282,37 +246,6 @@ namespace v2rayN.Handler
return responseTime;
}
- private string GetRealPingTime(string url, WebProxy webProxy, out int responseTime)
- {
- string msg = string.Empty;
- responseTime = -1;
- try
- {
- HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(url);
- myHttpWebRequest.Timeout = 5000;
- myHttpWebRequest.Proxy = webProxy;//new WebProxy(Global.Loopback, Global.httpPort);
-
- Stopwatch timer = new Stopwatch();
- timer.Start();
-
- HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
- if (myHttpWebResponse.StatusCode != HttpStatusCode.OK
- && myHttpWebResponse.StatusCode != HttpStatusCode.NoContent)
- {
- msg = myHttpWebResponse.StatusDescription;
- }
- timer.Stop();
- responseTime = timer.Elapsed.Milliseconds;
-
- myHttpWebResponse.Close();
- }
- catch (Exception ex)
- {
- Utils.SaveLog(ex.Message, ex);
- msg = ex.Message;
- }
- return msg;
- }
private string FormatOut(object time, string unit)
{
if (time.ToString().Equals("-1"))
diff --git a/v2rayN/v2rayN/Handler/UpdateHandle.cs b/v2rayN/v2rayN/Handler/UpdateHandle.cs
index 8e318d04..7eefe540 100644
--- a/v2rayN/v2rayN/Handler/UpdateHandle.cs
+++ b/v2rayN/v2rayN/Handler/UpdateHandle.cs
@@ -1,10 +1,9 @@
using System;
using System.Diagnostics;
using System.IO;
-using System.Net;
-using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
+using System.Threading.Tasks;
using System.Windows.Forms;
using v2rayN.Base;
using v2rayN.Mode;
@@ -177,67 +176,49 @@ namespace v2rayN.Handler
return;
}
- for (int k = 1; k <= config.subItem.Count; k++)
+ Task.Run(async () =>
{
- string id = config.subItem[k - 1].id.TrimEx();
- string url = config.subItem[k - 1].url.TrimEx();
- string userAgent = config.subItem[k - 1].userAgent.TrimEx();
- string groupId = config.subItem[k - 1].groupId.TrimEx();
- string hashCode = $"{k}){config.subItem[k - 1].remarks}->";
- if (config.subItem[k - 1].enabled == false)
+ foreach (var item in config.subItem)
{
- continue;
- }
- if (Utils.IsNullOrEmpty(id) || Utils.IsNullOrEmpty(url))
- {
- _updateFunc(false, $"{hashCode}{ResUI.MsgNoValidSubscription}");
- continue;
- }
-
- DownloadHandle downloadHandle3 = new DownloadHandle();
- downloadHandle3.UpdateCompleted += (sender2, args) =>
- {
- if (args.Success)
+ if (item.enabled == false)
{
- _updateFunc(false, $"{hashCode}{ResUI.MsgGetSubscriptionSuccessfully}");
- //string result = Utils.Base64Decode(args.Msg);
- string result = args.Msg;
- if (Utils.IsNullOrEmpty(result))
- {
- _updateFunc(false, $"{hashCode}{ResUI.MsgSubscriptionDecodingFailed}");
- return;
- }
+ continue;
+ }
+ string id = item.id.TrimEx();
+ string url = item.url.TrimEx();
+ string userAgent = item.userAgent.TrimEx();
+ string groupId = item.groupId.TrimEx();
+ string hashCode = $"{item.remarks}->";
+ if (Utils.IsNullOrEmpty(id) || Utils.IsNullOrEmpty(url))
+ {
+ //_updateFunc(false, $"{hashCode}{ResUI.MsgNoValidSubscription}");
+ continue;
+ }
- //ConfigHandler.RemoveServerViaSubid(ref config, id);
- //_updateFunc(false, $"{hashCode}{ResUI.MsgClearSubscription")}");
- // RefreshServers();
+ _updateFunc(false, $"{hashCode}{ResUI.MsgStartGettingSubscriptions}");
+ var result = await (new DownloadHandle()).DownloadStringAsync(url, blProxy, userAgent);
+
+ _updateFunc(false, $"{hashCode}{ResUI.MsgGetSubscriptionSuccessfully}");
+ if (Utils.IsNullOrEmpty(result))
+ {
+ _updateFunc(false, $"{hashCode}{ResUI.MsgSubscriptionDecodingFailed}");
+ }
+ else
+ {
int ret = ConfigHandler.AddBatchServers(ref config, result, id, groupId);
if (ret > 0)
{
- // RefreshServers();
+ _updateFunc(false, $"{hashCode}{ResUI.MsgUpdateSubscriptionEnd}");
}
else
{
_updateFunc(false, $"{hashCode}{ResUI.MsgFailedImportSubscription}");
}
- _updateFunc(true, $"{hashCode}{ResUI.MsgUpdateSubscriptionEnd}");
}
- else
- {
- _updateFunc(false, args.Msg);
- }
- };
- downloadHandle3.Error += (sender2, args) =>
- {
- _updateFunc(false, args.GetException().Message);
- };
-
- WebProxy webProxy = blProxy ? new WebProxy(Global.Loopback, _config.GetLocalPort(Global.InboundHttp2)) : null;
- downloadHandle3.WebDownloadString(url, webProxy, userAgent);
-
- _updateFunc(false, $"{hashCode}{ResUI.MsgStartGettingSubscriptions}");
- }
-
+ _updateFunc(false, $"-------------------------------------------------------");
+ }
+ _updateFunc(true, $"{ResUI.MsgUpdateSubscriptionEnd}");
+ });
}
@@ -269,8 +250,8 @@ namespace v2rayN.Handler
File.Delete(targetPath);
}
File.Move(fileName, targetPath);
- _updateFunc(true, "");
- }
+ //_updateFunc(true, "");
+ }
}
catch (Exception ex)
{
@@ -287,8 +268,8 @@ namespace v2rayN.Handler
_updateFunc(false, args.GetException().Message);
};
}
-
askToDownload(downloadHandle, url, false);
+
}
#region private
@@ -297,19 +278,6 @@ namespace v2rayN.Handler
{
try
{
- Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().enableSecurityProtocolTls13);
- WebRequestHandler webRequestHandler = new WebRequestHandler
- {
- AllowAutoRedirect = false
- };
- if (httpProxyTest() > 0)
- {
- int httpPort = _config.GetLocalPort(Global.InboundHttp2);
- WebProxy webProxy = new WebProxy(Global.Loopback, httpPort);
- webRequestHandler.Proxy = webProxy;
- }
- HttpClient httpClient = new HttpClient(webRequestHandler);
-
string url;
if (type == ECoreType.v2fly)
{
@@ -327,10 +295,11 @@ namespace v2rayN.Handler
{
throw new ArgumentException("Type");
}
- HttpResponseMessage response = await httpClient.GetAsync(url);
- if (response.StatusCode.ToString() == "Redirect")
+
+ var result = await (new DownloadHandle()).UrlRedirectAsync(url, true);
+ if (!Utils.IsNullOrEmpty(result))
{
- responseHandler(type, response.Headers.Location.ToString());
+ responseHandler(type, result);
}
else
{
@@ -352,19 +321,20 @@ namespace v2rayN.Handler
{
try
{
- var core = string.Empty;
- var match = string.Empty;
- if (type == ECoreType.v2fly)
+
+ var coreInfo = LazyConfig.Instance.GetCoreInfo(type);
+ string filePath = string.Empty;
+ foreach (string name in coreInfo.coreExes)
{
- core = "v2ray.exe";
- match = "V2Ray";
+ string vName = string.Format("{0}.exe", name);
+ vName = Utils.GetPath(vName);
+ if (File.Exists(vName))
+ {
+ filePath = vName;
+ break;
+ }
}
- else if (type == ECoreType.Xray)
- {
- core = "xray.exe";
- match = "Xray";
- }
- string filePath = Utils.GetPath(core);
+
if (!File.Exists(filePath))
{
string msg = string.Format(ResUI.NotFoundCore, @"");
@@ -383,7 +353,7 @@ namespace v2rayN.Handler
p.Start();
p.WaitForExit(5000);
string echo = p.StandardOutput.ReadToEnd();
- string version = Regex.Match(echo, $"{match} ([0-9.]+) \\(").Groups[1].Value;
+ string version = Regex.Match(echo, $"{coreInfo.match} ([0-9.]+) \\(").Groups[1].Value;
return version;
}
catch (Exception ex)
@@ -458,24 +428,9 @@ namespace v2rayN.Handler
}
if (blDownload)
{
- if (httpProxyTest() > 0)
- {
- int httpPort = _config.GetLocalPort(Global.InboundHttp2);
- WebProxy webProxy = new WebProxy(Global.Loopback, httpPort);
- downloadHandle.DownloadFileAsync(url, webProxy, 600);
- }
- else
- {
- downloadHandle.DownloadFileAsync(url, null, 600);
- }
+ downloadHandle.DownloadFileAsync(url, true, 600);
}
}
-
- private int httpProxyTest()
- {
- SpeedtestHandler statistics = new SpeedtestHandler(ref _config);
- return statistics.RunAvailabilityCheck();
- }
#endregion
}
}
diff --git a/v2rayN/v2rayN/Mode/CoreInfo.cs b/v2rayN/v2rayN/Mode/CoreInfo.cs
index 2d66b121..8b2726b2 100644
--- a/v2rayN/v2rayN/Mode/CoreInfo.cs
+++ b/v2rayN/v2rayN/Mode/CoreInfo.cs
@@ -13,5 +13,7 @@ namespace v2rayN.Mode
public string arguments { get; set; }
public string coreUrl { get; set; }
+
+ public string match { get; set; }
}
}
diff --git a/v2rayN/v2rayN/v2rayN.csproj b/v2rayN/v2rayN/v2rayN.csproj
index 403a5db0..9cd35aed 100644
--- a/v2rayN/v2rayN/v2rayN.csproj
+++ b/v2rayN/v2rayN/v2rayN.csproj
@@ -99,6 +99,7 @@
+
Component
@@ -195,9 +196,6 @@
-
- Component
-