Improve ConnectionHandler DownloadService

This commit is contained in:
2dust 2026-05-20 15:42:47 +08:00
parent f18758d4bf
commit a9824fe6ec
2 changed files with 89 additions and 38 deletions

View file

@ -4,6 +4,9 @@ public static class ConnectionHandler
{ {
private static readonly string _tag = "ConnectionHandler"; private static readonly string _tag = "ConnectionHandler";
/// <summary>
/// Runs ping and IP checks and returns a formatted result string.
/// </summary>
public static async Task<string> RunAvailabilityCheck() public static async Task<string> RunAvailabilityCheck()
{ {
var time = await GetRealPingTimeInfo(); var time = await GetRealPingTimeInfo();
@ -12,40 +15,24 @@ public static class ConnectionHandler
return string.Format(ResUI.TestMeOutput, time, ip); return string.Format(ResUI.TestMeOutput, time, ip);
} }
/// <summary>
/// Gets IP information using the default local proxy.
/// </summary>
private static async Task<string?> GetIPInfo() private static async Task<string?> GetIPInfo()
{ {
var url = AppManager.Instance.Config.SpeedTestItem.IPAPIUrl; var webProxy = await GetWebProxy();
if (url.IsNullOrEmpty()) return await GetIPInfo(webProxy);
{
return null;
}
var downloadHandle = new DownloadService();
var result = await downloadHandle.TryDownloadString(url, true, "");
if (result == null)
{
return null;
}
var ipInfo = JsonUtils.Deserialize<IPAPIInfo>(result);
if (ipInfo == null)
{
return null;
}
var ip = ipInfo.ip ?? ipInfo.clientIp ?? ipInfo.ip_addr ?? ipInfo.query;
var country = ipInfo.country_code ?? ipInfo.country ?? ipInfo.countryCode ?? ipInfo.location?.country_code;
return $"({country ?? "unknown"}) {ip}";
} }
/// <summary>
/// Measures real ping time using configured test URL.
/// </summary>
private static async Task<int> GetRealPingTimeInfo() private static async Task<int> GetRealPingTimeInfo()
{ {
var responseTime = -1; var responseTime = -1;
try try
{ {
var port = AppManager.Instance.GetLocalPort(EInboundProtocol.socks); var webProxy = await GetWebProxy();
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{port}");
var url = AppManager.Instance.Config.SpeedTestItem.SpeedPingTestUrl; var url = AppManager.Instance.Config.SpeedTestItem.SpeedPingTestUrl;
for (var i = 0; i < 2; i++) for (var i = 0; i < 2; i++)
@ -66,6 +53,18 @@ public static class ConnectionHandler
return responseTime; return responseTime;
} }
/// <summary>
/// Creates local SOCKS proxy instance.
/// </summary>
private static async Task<WebProxy?> GetWebProxy()
{
var port = AppManager.Instance.GetLocalPort(EInboundProtocol.socks);
return new WebProxy($"socks5://{Global.Loopback}:{port}");
}
/// <summary>
/// Measures response time by sending HTTP requests through proxy.
/// </summary>
public static async Task<int> GetRealPingTime(string url, IWebProxy? webProxy, int downloadTimeout) public static async Task<int> GetRealPingTime(string url, IWebProxy? webProxy, int downloadTimeout)
{ {
var responseTime = -1; var responseTime = -1;
@ -95,4 +94,34 @@ public static class ConnectionHandler
} }
return responseTime; return responseTime;
} }
/// <summary>
/// Gets IP and country information through specified proxy.
/// </summary>
public static async Task<string?> GetIPInfo(IWebProxy? webProxy)
{
var url = AppManager.Instance.Config.SpeedTestItem.IPAPIUrl;
if (url.IsNullOrEmpty())
{
return null;
}
var downloadHandle = new DownloadService();
var result = await downloadHandle.TryDownloadString(url, webProxy, "");
if (result == null)
{
return null;
}
var ipInfo = JsonUtils.Deserialize<IPAPIInfo>(result);
if (ipInfo == null)
{
return null;
}
var ip = ipInfo.ip ?? ipInfo.clientIp ?? ipInfo.ip_addr ?? ipInfo.query;
var country = ipInfo.country_code ?? ipInfo.country ?? ipInfo.countryCode ?? ipInfo.location?.country_code;
return $"({country ?? "unknown"}) {ip}";
}
} }

View file

@ -3,7 +3,7 @@ using System.Net.Http.Headers;
namespace ServiceLib.Services; namespace ServiceLib.Services;
/// <summary> /// <summary>
///Download /// Download
/// </summary> /// </summary>
public class DownloadService public class DownloadService
{ {
@ -13,7 +13,10 @@ public class DownloadService
private static readonly string _tag = "DownloadService"; private static readonly string _tag = "DownloadService";
public async Task<int> DownloadDataAsync(string url, WebProxy webProxy, int downloadTimeout, Func<bool, string, Task> updateFunc) /// <summary>
/// Downloads data with the specified proxy and reports progress messages.
/// </summary>
public async Task<int> DownloadDataAsync(string url, IWebProxy webProxy, int downloadTimeout, Func<bool, string, Task> updateFunc)
{ {
try try
{ {
@ -36,6 +39,9 @@ public class DownloadService
return 0; return 0;
} }
/// <summary>
/// Downloads a file and reports progress through events.
/// </summary>
public async Task DownloadFileAsync(string url, string fileName, bool blProxy, int downloadTimeout) public async Task DownloadFileAsync(string url, string fileName, bool blProxy, int downloadTimeout)
{ {
try try
@ -64,6 +70,9 @@ public class DownloadService
} }
} }
/// <summary>
/// Gets redirect target URL without following redirects automatically.
/// </summary>
public async Task<string?> UrlRedirectAsync(string url, bool blProxy) public async Task<string?> UrlRedirectAsync(string url, bool blProxy)
{ {
var webRequestHandler = new SocketsHttpHandler var webRequestHandler = new SocketsHttpHandler
@ -86,11 +95,23 @@ public class DownloadService
} }
} }
/// <summary>
/// Tries to download string content using proxy switch setting.
/// </summary>
public async Task<string?> TryDownloadString(string url, bool blProxy, string userAgent) public async Task<string?> TryDownloadString(string url, bool blProxy, string userAgent)
{
var webProxy = await GetWebProxy(blProxy);
return await TryDownloadString(url, webProxy, userAgent);
}
/// <summary>
/// Tries to download string content with a specified proxy.
/// </summary>
public async Task<string?> TryDownloadString(string url, IWebProxy? webProxy, string userAgent)
{ {
try try
{ {
var result1 = await DownloadStringAsync(url, blProxy, userAgent, 15); var result1 = await DownloadStringAsync(url, webProxy, userAgent, 15);
if (result1.IsNotEmpty()) if (result1.IsNotEmpty())
{ {
return result1; return result1;
@ -108,7 +129,7 @@ public class DownloadService
try try
{ {
var result2 = await DownloadStringViaDownloader(url, blProxy, userAgent, 15); var result2 = await DownloadStringViaDownloader(url, webProxy, userAgent, 15);
if (result2.IsNotEmpty()) if (result2.IsNotEmpty())
{ {
return result2; return result2;
@ -128,14 +149,12 @@ public class DownloadService
} }
/// <summary> /// <summary>
/// DownloadString /// Downloads string content via HttpClient.
/// </summary> /// </summary>
/// <param name="url"></param> private async Task<string?> DownloadStringAsync(string url, IWebProxy? webProxy, string userAgent, int timeout)
private async Task<string?> DownloadStringAsync(string url, bool blProxy, string userAgent, int timeout)
{ {
try try
{ {
var webProxy = await GetWebProxy(blProxy);
var client = new HttpClient(new SocketsHttpHandler() var client = new HttpClient(new SocketsHttpHandler()
{ {
Proxy = webProxy, Proxy = webProxy,
@ -172,15 +191,12 @@ public class DownloadService
} }
/// <summary> /// <summary>
/// DownloadString /// Downloads string content via DownloaderHelper.
/// </summary> /// </summary>
/// <param name="url"></param> private async Task<string?> DownloadStringViaDownloader(string url, IWebProxy? webProxy, string userAgent, int timeout)
private async Task<string?> DownloadStringViaDownloader(string url, bool blProxy, string userAgent, int timeout)
{ {
try try
{ {
var webProxy = await GetWebProxy(blProxy);
if (userAgent.IsNullOrEmpty()) if (userAgent.IsNullOrEmpty())
{ {
userAgent = Utils.GetVersion(false); userAgent = Utils.GetVersion(false);
@ -200,6 +216,9 @@ public class DownloadService
return null; return null;
} }
/// <summary>
/// Creates local SOCKS proxy when proxy switch is enabled.
/// </summary>
private async Task<WebProxy?> GetWebProxy(bool blProxy) private async Task<WebProxy?> GetWebProxy(bool blProxy)
{ {
if (!blProxy) if (!blProxy)
@ -215,6 +234,9 @@ public class DownloadService
return new WebProxy($"socks5://{Global.Loopback}:{port}"); return new WebProxy($"socks5://{Global.Loopback}:{port}");
} }
/// <summary>
/// Checks whether the specified TCP endpoint is reachable.
/// </summary>
private async Task<bool> SocketCheck(string ip, int port) private async Task<bool> SocketCheck(string ip, int port)
{ {
try try