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 -