Files
v2rayN/v2rayN/v2rayN/Handler/DownloadHandle.cs
2023-02-19 13:34:22 +08:00

363 lines
12 KiB
C#

using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Sockets;
using v2rayN.Base;
using v2rayN.Resx;
namespace v2rayN.Handler
{
/// <summary>
///Download
/// </summary>
class DownloadHandle
{
public event EventHandler<ResultEventArgs> UpdateCompleted;
public event ErrorEventHandler? Error;
public class ResultEventArgs : EventArgs
{
public bool Success;
public string Msg;
public ResultEventArgs(bool success, string msg)
{
Success = success;
Msg = msg;
}
}
public async Task<int> DownloadDataAsync(string url, WebProxy webProxy, int downloadTimeout, Action<bool, string> update)
{
try
{
Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().guiItem.enableSecurityProtocolTls13);
var progress = new Progress<string>();
progress.ProgressChanged += (sender, value) =>
{
if (update != null)
{
string msg = $"{value}";
update(false, msg);
}
};
await DownloaderHelper.Instance.DownloadDataAsync4Speed(webProxy,
url,
progress,
downloadTimeout);
}
catch (Exception ex)
{
update(false, ex.Message);
if (ex.InnerException != null)
{
update(false, ex.InnerException.Message);
}
}
return 0;
}
public void DownloadFileAsync(string url, bool blProxy, int downloadTimeout)
{
try
{
Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().guiItem.enableSecurityProtocolTls13);
UpdateCompleted?.Invoke(this, new ResultEventArgs(false, ResUI.Downloading));
var progress = new Progress<double>();
progress.ProgressChanged += (sender, value) =>
{
if (UpdateCompleted != null)
{
string msg = $"...{value}%";
UpdateCompleted(this, new ResultEventArgs(value > 100, msg));
}
};
var webProxy = GetWebProxy(blProxy);
_ = DownloaderHelper.Instance.DownloadFileAsync(webProxy,
url,
Utils.GetTempPath(Utils.GetDownloadFileName(url)),
progress,
downloadTimeout);
}
catch (Exception ex)
{
Utils.SaveLog(ex.Message, ex);
Error?.Invoke(this, new ErrorEventArgs(ex));
if (ex.InnerException != null)
{
Error?.Invoke(this, new ErrorEventArgs(ex.InnerException));
}
}
}
public async Task<string?> UrlRedirectAsync(string url, bool blProxy)
{
Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().guiItem.enableSecurityProtocolTls13);
var webRequestHandler = new SocketsHttpHandler
{
AllowAutoRedirect = false,
Proxy = GetWebProxy(blProxy)
};
HttpClient client = new(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;
}
}
public async Task<string?> TryDownloadString(string url, bool blProxy, string userAgent)
{
try
{
var result1 = await DownloadStringAsync(url, blProxy, userAgent);
if (!Utils.IsNullOrEmpty(result1))
{
return result1;
}
}
catch (Exception ex)
{
Utils.SaveLog(ex.Message, ex);
Error?.Invoke(this, new ErrorEventArgs(ex));
if (ex.InnerException != null)
{
Error?.Invoke(this, new ErrorEventArgs(ex.InnerException));
}
}
try
{
var result2 = await DownloadStringViaDownloader(url, blProxy, userAgent);
if (!Utils.IsNullOrEmpty(result2))
{
return result2;
}
}
catch (Exception ex)
{
Utils.SaveLog(ex.Message, ex);
Error?.Invoke(this, new ErrorEventArgs(ex));
if (ex.InnerException != null)
{
Error?.Invoke(this, new ErrorEventArgs(ex.InnerException));
}
}
try
{
using var wc = new WebClient();
wc.Proxy = GetWebProxy(blProxy);
var result3 = await wc.DownloadStringTaskAsync(url);
if (!Utils.IsNullOrEmpty(result3))
{
return result3;
}
}
catch (Exception ex)
{
Utils.SaveLog(ex.Message, ex);
Error?.Invoke(this, new ErrorEventArgs(ex));
if (ex.InnerException != null)
{
Error?.Invoke(this, new ErrorEventArgs(ex.InnerException));
}
}
return null;
}
/// <summary>
/// DownloadString
/// </summary>
/// <param name="url"></param>
public async Task<string?> DownloadStringAsync(string url, bool blProxy, string userAgent)
{
try
{
Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().guiItem.enableSecurityProtocolTls13);
var client = new HttpClient(new SocketsHttpHandler()
{
Proxy = GetWebProxy(blProxy)
});
if (Utils.IsNullOrEmpty(userAgent))
{
userAgent = $"{Utils.GetVersion(false)}";
}
client.DefaultRequestHeaders.UserAgent.TryParseAdd(userAgent);
Uri uri = new(url);
//Authorization Header
if (!Utils.IsNullOrEmpty(uri.UserInfo))
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Utils.Base64Encode(uri.UserInfo));
}
var cts = new CancellationTokenSource();
cts.CancelAfter(1000 * 30);
var result = await HttpClientHelper.GetInstance().GetAsync(client, url, cts.Token);
return result;
}
catch (Exception ex)
{
Utils.SaveLog(ex.Message, ex);
Error?.Invoke(this, new ErrorEventArgs(ex));
if (ex.InnerException != null)
{
Error?.Invoke(this, new ErrorEventArgs(ex.InnerException));
}
}
return null;
}
/// <summary>
/// DownloadString
/// </summary>
/// <param name="url"></param>
public async Task<string?> DownloadStringViaDownloader(string url, bool blProxy, string userAgent)
{
try
{
Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().guiItem.enableSecurityProtocolTls13);
var webProxy = GetWebProxy(blProxy);
if (Utils.IsNullOrEmpty(userAgent))
{
userAgent = $"{Utils.GetVersion(false)}";
}
var result = await DownloaderHelper.Instance.DownloadStringAsync(webProxy, url, userAgent, 30);
return result;
}
catch (Exception ex)
{
Utils.SaveLog(ex.Message, ex);
Error?.Invoke(this, new ErrorEventArgs(ex));
if (ex.InnerException != null)
{
Error?.Invoke(this, new ErrorEventArgs(ex.InnerException));
}
}
return null;
}
public int RunAvailabilityCheck(WebProxy? webProxy)
{
try
{
if (webProxy == null)
{
var httpPort = LazyConfig.Instance.GetLocalPort(Global.InboundHttp);
webProxy = new WebProxy(Global.Loopback, httpPort);
}
try
{
var config = LazyConfig.Instance.GetConfig();
string status = GetRealPingTime(config.speedTestItem.speedPingTestUrl, webProxy, 10, out int responseTime);
bool noError = Utils.IsNullOrEmpty(status);
return noError ? responseTime : -1;
}
catch (Exception ex)
{
Utils.SaveLog(ex.Message, ex);
return -1;
}
}
catch (Exception ex)
{
Utils.SaveLog(ex.Message, ex);
return -1;
}
}
public string GetRealPingTime(string url, WebProxy webProxy, int downloadTimeout, out int responseTime)
{
string msg = string.Empty;
responseTime = -1;
try
{
HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(url);
myHttpWebRequest.Timeout = downloadTimeout * 1000;
myHttpWebRequest.Proxy = webProxy;
Stopwatch timer = new();
timer.Start();
HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
if (myHttpWebResponse.StatusCode is not HttpStatusCode.OK and not 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 WebProxy? GetWebProxy(bool blProxy)
{
if (!blProxy)
{
return null;
}
var httpPort = LazyConfig.Instance.GetLocalPort(Global.InboundHttp);
if (!SocketCheck(Global.Loopback, httpPort))
{
return null;
}
return new WebProxy(Global.Loopback, httpPort);
}
private bool SocketCheck(string ip, int port)
{
Socket? sock = null;
try
{
IPAddress ipa = IPAddress.Parse(ip);
IPEndPoint point = new(ipa, port);
sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sock.Connect(point);
return true;
}
catch { }
finally
{
if (sock != null)
{
sock.Close();
sock.Dispose();
}
}
return false;
}
}
}