Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add upload test and bug fix #511

Merged
merged 5 commits into from
Apr 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions windows/Classes/Checker/AbstractChecker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace WinCFScan.Classes.Checker
{
internal abstract class AbstractChecker
{
public HttpClient client;
public CheckSettings checkSettings { get; }
public CheckSettings cs { get; } // abbreviated of above checkSettings
public string exceptionMessage = "";
public long checkDuration;


public AbstractChecker(CheckSettings checkSettings)
{
this.checkSettings = cs = checkSettings;

var proxy = new WebProxy();
proxy.Address = new Uri($"socks5://127.0.0.1:{cs.port}");
var handler = new HttpClientHandler
{
Proxy = proxy
};

this.client = new HttpClient(handler);
this.client.Timeout = TimeSpan.FromSeconds(cs.timeout);
}

public abstract bool check();

protected void handleException(Exception ex)
{
string message = ex.Message;
if (isTimeoutException(ex))
{
Tools.logStep($"{checkSettings.checkType} timed out.", cs.isDiagnosing);
}
else
{
Tools.logStep($"{checkSettings.checkType} had exception: {message}", cs.isDiagnosing);

exceptionMessage = message;

if (ex.InnerException != null && ex.InnerException?.Message != "" && !ex.Message.Contains(ex.InnerException?.Message))
{
Tools.logStep($"Inner exception: {ex.InnerException?.Message}", cs.isDiagnosing);
}
}
}

private bool isTimeoutException(Exception ex)
{
string msg = ex.Message;
return msg.Contains("The request was aborted") ||
msg.Contains("A task was canceled.");
}
}

public enum CheckType
{
DOWNLOAD,
UPLOAD,
BOTH
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,54 +10,60 @@
using WinCFScan.Classes.Config;
using WinCFScan.Classes.HTTPRequest;

namespace WinCFScan.Classes
namespace WinCFScan.Classes.Checker
{
internal class CheckIPWorking
{
private readonly string ip;
private Process? process ;
private Process? process;
private string port;
private string v2rayConfigPath;
public long downloadDuration { get; private set; }
public long uploadDuration { get; private set; }
public long frontingDuration { get; private set; }
private ScanSpeed targetSpeed;
private ScanSpeed dlTargetSpeed;
private ScanSpeed upTargetSpeed;
private readonly CustomConfigInfo scanConfig;
private readonly int downloadTimeout;
private readonly int checkTimeout;
public string downloadException = "";
public string uploadException = "";
public string frontingException = "";
private bool isDiagnosing = false;
public bool isV2rayExecutionSuccess = false;
public CheckType checkType { get; private set; }
private CheckResultStatus checkResultStatus;



public CheckIPWorking(string ip, ScanSpeed targetSpeed, CustomConfigInfo scanConfig, int downloadTimeout, bool isDiagnosing = false)
public CheckIPWorking(string ip, ScanSpeed dlTargetSpeed, ScanSpeed upTargetSpeed, CustomConfigInfo scanConfig, CheckType checkType, int checkTimeout, bool isDiagnosing = false)
{
this.ip = ip;
this.port = getPortByIP();
port = getPortByIP();
v2rayConfigPath = $"v2ray-config/generated/config.{ip}.json";
this.targetSpeed = targetSpeed;
this.dlTargetSpeed = dlTargetSpeed;
this.upTargetSpeed = upTargetSpeed;
this.scanConfig = scanConfig;
this.downloadTimeout = downloadTimeout;
this.checkTimeout = checkTimeout;
this.isDiagnosing = isDiagnosing;
this.checkType = checkType;
checkResultStatus = new CheckResultStatus(checkType);
}

public CheckIPWorking()
{
}

public bool check()
public bool check()
{
bool v2rayDLSuccess = false;
Tools.logStep("\n------------ Start IP Check ------------", isDiagnosing);
Tools.logStep("IP: " + this.ip, isDiagnosing);
Tools.logStep("IP: " + ip, isDiagnosing);

// first of all quick test on fronting domain through cloudflare
bool frontingSuccess = checkFronting();

if (frontingSuccess || isDiagnosing) // on diagnosing we will always test v2ray
{
// don't speed test if that mode is selected by user
if (targetSpeed.isSpeedZero() && !isDiagnosing)
if (dlTargetSpeed.isSpeedZero() && !isDiagnosing)
{
v2rayDLSuccess = true;
}
Expand All @@ -70,26 +76,29 @@ public bool check()
}

Tools.logStep(
string.Format(Environment.NewLine + "Fronting Result: {0}", frontingSuccess ? "SUCCESS" : "FAILED") + Environment.NewLine +
string.Format(Environment.NewLine + "Fronting Result: {0}", frontingSuccess ? "SUCCESS" : "FAILED") + Environment.NewLine +
string.Format("v2ray.exe Execution: {0}", isV2rayExecutionSuccess ? "SUCCESS" : "FAILED") + Environment.NewLine +
string.Format("Download Result: {0}", v2rayDLSuccess ? "SUCCESS" : "FAILED"), isDiagnosing
string.Format("Download Result: {0}", checkResultStatus.isDownSuccess() ? "SUCCESS" : "FAILED") + Environment.NewLine +
string.Format("Upload Result: {0}", checkResultStatus.isUpSuccess() ? "SUCCESS" : "FAILED"), isDiagnosing
);

Tools.logStep("\n------------ End IP Check ------------\n", isDiagnosing);
return v2rayDLSuccess;

}

public bool checkV2ray() {
public bool checkV2ray()
{
bool success = false;

// create config
if (createV2rayConfigFile())
{
// start v2ray.exe process
if (runV2rayProcess())
{
// send download request
if (checkDownloadSpeed())
// send download/upload request
if (checkV2raySpeed())
{
// speed was enough
success = true;
Expand Down Expand Up @@ -123,14 +132,14 @@ public bool checkFronting(bool withCustumDNSResolver = true, int timeout = 1)
Stopwatch sw = new Stopwatch();
try
{

string frUrl = "https://" + ConfigManager.Instance.getAppConfig()?.frontDomain;
Tools.logStep($"Fronting check with url: {frUrl}", isDiagnosing);
sw.Start();
var html = client.GetStringAsync(frUrl).Result;
Tools.logStep($"Fronting check done in {sw.ElapsedMilliseconds:n0} ms, content: '{html.Substring(0, 50)}'", isDiagnosing);
frontingDuration = sw.ElapsedMilliseconds;
return true;
return html.StartsWith("0000000000");
}
catch (Exception ex)
{
Expand All @@ -156,66 +165,45 @@ public bool checkFronting(bool withCustumDNSResolver = true, int timeout = 1)

}

private bool checkDownloadSpeed()
private bool checkV2raySpeed()
{
var proxy = new WebProxy();
proxy.Address = new Uri($"socks5://127.0.0.1:{port}");
var handler = new HttpClientHandler
// check download
if (checkType is CheckType.DOWNLOAD or CheckType.BOTH || isDiagnosing)
{
Proxy = proxy
};

int timeout = this.downloadTimeout;

var client = new HttpClient(handler);
client.Timeout = TimeSpan.FromSeconds(timeout); // 2 seconds
Tools.logStep(Environment.NewLine + "----- Download Test -----", isDiagnosing);
Tools.logStep($"Start check dl speed, proxy port: {port}, timeout: {timeout} sec, target speed: {targetSpeed.getTargetSpeed():n0} b/s", isDiagnosing);
Stopwatch sw = new Stopwatch();
//ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;

try
{
sw.Start();
string dlUrl = "https://" + ConfigManager.Instance.getAppConfig().scanDomain + targetSpeed.getTargetFileSize(timeout);
Tools.logStep($"Starting dl url: {dlUrl}", isDiagnosing);
var data = client.GetStringAsync(dlUrl).Result;
Tools.logStep($"*** Download success in {sw.ElapsedMilliseconds:n0} ms, dl size: {data.Length:n0} bytes for IP {ip}", isDiagnosing);

return data.Length == targetSpeed.getTargetSpeed() * timeout;
}
catch (Exception ex)
{
string message = ex.Message;
if (isTimeoutException(ex))
string dlUrl = "https://" + ConfigManager.Instance.getAppConfig().downloadDomain + dlTargetSpeed.getTargetFileSize(checkTimeout);
var cs = new CheckSettings(ip, port, checkTimeout, dlUrl, isDiagnosing, checkType, dlTargetSpeed);
var dlChecker = new DownloadChecker(cs);
if (dlChecker.check())
{
Tools.logStep("Download timed out.", isDiagnosing);
checkResultStatus.setDownloadSuccess();
downloadDuration = dlChecker.checkDuration;
}
else
{
Tools.logStep($"Download had exception: {message}", isDiagnosing);
// monitor exceptions
downloadException = message;

if (ex.InnerException != null && ex.InnerException?.Message != "" && ! ex.Message.Contains(ex.InnerException?.Message))
{
Tools.logStep($"Inner exception: {ex.InnerException?.Message}", isDiagnosing);
}
this.downloadException = dlChecker.exceptionMessage;
}

return false;
}
finally
{
downloadDuration = sw.ElapsedMilliseconds;
if(downloadDuration > (timeout * 1000) + 500)

// check upload
if (checkType is CheckType.UPLOAD or CheckType.BOTH || isDiagnosing){
string upUrl = "https://" + ConfigManager.Instance.getAppConfig().uploadDomain;
var cs = new CheckSettings(ip, port, checkTimeout, upUrl, isDiagnosing, checkType, upTargetSpeed);
var upChecker = new UploadChecker(cs);
if (upChecker.check())
{
Tools.logStep($"Download took too long! {downloadDuration:n0} ms for IP {ip}", isDiagnosing);
checkResultStatus.setUploadSuccess();
uploadDuration = upChecker.checkDuration;
}
else
{
this.uploadException = upChecker.exceptionMessage;
}
handler.Dispose();
client.Dispose();
}

return checkResultStatus.isSuccess();
}

private bool isTimeoutException(Exception ex)
{
string msg = ex.Message;
Expand All @@ -240,15 +228,15 @@ private bool createV2rayConfigFile()
.Replace("HOSTHOST", clientConfig.host)
.Replace("CFPORTCFPORT", clientConfig.port)
.Replace("RANDOMHOST", getRandomSNI(clientConfig.host))
.Replace("IP.IP.IP.IP", this.ip)
.Replace("IP.IP.IP.IP", ip)
.Replace("ENDPOINTENDPOINT", clientConfig.path);
}
else
{ // just replace port and ip for custom v2ray configs
configTemplate = scanConfig.content;
configTemplate = configTemplate
.Replace("PORTPORT", port)
.Replace("IP.IP.IP.IP", this.ip);
.Replace("IP.IP.IP.IP", ip);
}

File.WriteAllText(v2rayConfigPath, configTemplate);
Expand All @@ -267,15 +255,15 @@ private string getRandomSNI(string host)
{
var urlParts = host.Split(".");
urlParts[0] = Guid.NewGuid().ToString();
return string.Join(".", urlParts);
return string.Join(".", urlParts);
}

// sum of ip segments plus 3000
private string getPortByIP()
{
int sum = Int32.Parse(
this.ip.Split(".").Aggregate((current, next) =>
(Int32.Parse(current) + Int32.Parse(next)).ToString())
{
int sum = int.Parse(
ip.Split(".").Aggregate((current, next) =>
(int.Parse(current) + int.Parse(next)).ToString())
);

return (3000 + sum).ToString();
Expand All @@ -287,10 +275,10 @@ private bool runV2rayProcess()
startInfo.FileName = "v2ray.exe";
//if (!ConfigManager.Instance.enableDebug)
//{
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.CreateNoWindow = true;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.CreateNoWindow = true;
//}
startInfo.UseShellExecute = false;
startInfo.Arguments = $"run -config=\"{v2rayConfigPath}\"";
Expand All @@ -309,7 +297,7 @@ private bool runV2rayProcess()
{
Tools.logStep($"v2ray.exe execution had exception: {ex.Message}", isDiagnosing);
}

// log error
if (!wasSuccess)
{
Expand All @@ -320,14 +308,14 @@ private bool runV2rayProcess()
Tools.logStep(message, isDiagnosing);
downloadException = message;
}
catch (Exception) {}
catch (Exception) { }
}

isV2rayExecutionSuccess = wasSuccess;

return wasSuccess;
}


}
}
Loading