Skip to content

Commit 18dafd9

Browse files
authored
Merge pull request #511 from MortezaBashsiz/win-develop
add upload test and bug fix
2 parents 22999c9 + 0e0464f commit 18dafd9

File tree

13 files changed

+709
-327
lines changed

13 files changed

+709
-327
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Net;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
8+
namespace WinCFScan.Classes.Checker
9+
{
10+
internal abstract class AbstractChecker
11+
{
12+
public HttpClient client;
13+
public CheckSettings checkSettings { get; }
14+
public CheckSettings cs { get; } // abbreviated of above checkSettings
15+
public string exceptionMessage = "";
16+
public long checkDuration;
17+
18+
19+
public AbstractChecker(CheckSettings checkSettings)
20+
{
21+
this.checkSettings = cs = checkSettings;
22+
23+
var proxy = new WebProxy();
24+
proxy.Address = new Uri($"socks5://127.0.0.1:{cs.port}");
25+
var handler = new HttpClientHandler
26+
{
27+
Proxy = proxy
28+
};
29+
30+
this.client = new HttpClient(handler);
31+
this.client.Timeout = TimeSpan.FromSeconds(cs.timeout);
32+
}
33+
34+
public abstract bool check();
35+
36+
protected void handleException(Exception ex)
37+
{
38+
string message = ex.Message;
39+
if (isTimeoutException(ex))
40+
{
41+
Tools.logStep($"{checkSettings.checkType} timed out.", cs.isDiagnosing);
42+
}
43+
else
44+
{
45+
Tools.logStep($"{checkSettings.checkType} had exception: {message}", cs.isDiagnosing);
46+
47+
exceptionMessage = message;
48+
49+
if (ex.InnerException != null && ex.InnerException?.Message != "" && !ex.Message.Contains(ex.InnerException?.Message))
50+
{
51+
Tools.logStep($"Inner exception: {ex.InnerException?.Message}", cs.isDiagnosing);
52+
}
53+
}
54+
}
55+
56+
private bool isTimeoutException(Exception ex)
57+
{
58+
string msg = ex.Message;
59+
return msg.Contains("The request was aborted") ||
60+
msg.Contains("A task was canceled.");
61+
}
62+
}
63+
64+
public enum CheckType
65+
{
66+
DOWNLOAD,
67+
UPLOAD,
68+
BOTH
69+
}
70+
71+
}
Lines changed: 69 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -10,54 +10,60 @@
1010
using WinCFScan.Classes.Config;
1111
using WinCFScan.Classes.HTTPRequest;
1212

13-
namespace WinCFScan.Classes
13+
namespace WinCFScan.Classes.Checker
1414
{
1515
internal class CheckIPWorking
1616
{
1717
private readonly string ip;
18-
private Process? process ;
18+
private Process? process;
1919
private string port;
2020
private string v2rayConfigPath;
2121
public long downloadDuration { get; private set; }
22+
public long uploadDuration { get; private set; }
2223
public long frontingDuration { get; private set; }
23-
private ScanSpeed targetSpeed;
24+
private ScanSpeed dlTargetSpeed;
25+
private ScanSpeed upTargetSpeed;
2426
private readonly CustomConfigInfo scanConfig;
25-
private readonly int downloadTimeout;
27+
private readonly int checkTimeout;
2628
public string downloadException = "";
29+
public string uploadException = "";
2730
public string frontingException = "";
2831
private bool isDiagnosing = false;
2932
public bool isV2rayExecutionSuccess = false;
33+
public CheckType checkType { get; private set; }
34+
private CheckResultStatus checkResultStatus;
3035

31-
32-
33-
public CheckIPWorking(string ip, ScanSpeed targetSpeed, CustomConfigInfo scanConfig, int downloadTimeout, bool isDiagnosing = false)
36+
public CheckIPWorking(string ip, ScanSpeed dlTargetSpeed, ScanSpeed upTargetSpeed, CustomConfigInfo scanConfig, CheckType checkType, int checkTimeout, bool isDiagnosing = false)
3437
{
3538
this.ip = ip;
36-
this.port = getPortByIP();
39+
port = getPortByIP();
3740
v2rayConfigPath = $"v2ray-config/generated/config.{ip}.json";
38-
this.targetSpeed = targetSpeed;
41+
this.dlTargetSpeed = dlTargetSpeed;
42+
this.upTargetSpeed = upTargetSpeed;
3943
this.scanConfig = scanConfig;
40-
this.downloadTimeout = downloadTimeout;
44+
this.checkTimeout = checkTimeout;
4145
this.isDiagnosing = isDiagnosing;
46+
this.checkType = checkType;
47+
checkResultStatus = new CheckResultStatus(checkType);
4248
}
4349

4450
public CheckIPWorking()
4551
{
4652
}
4753

48-
public bool check()
54+
public bool check()
4955
{
5056
bool v2rayDLSuccess = false;
5157
Tools.logStep("\n------------ Start IP Check ------------", isDiagnosing);
52-
Tools.logStep("IP: " + this.ip, isDiagnosing);
58+
Tools.logStep("IP: " + ip, isDiagnosing);
5359

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

5763
if (frontingSuccess || isDiagnosing) // on diagnosing we will always test v2ray
5864
{
5965
// don't speed test if that mode is selected by user
60-
if (targetSpeed.isSpeedZero() && !isDiagnosing)
66+
if (dlTargetSpeed.isSpeedZero() && !isDiagnosing)
6167
{
6268
v2rayDLSuccess = true;
6369
}
@@ -70,26 +76,29 @@ public bool check()
7076
}
7177

7278
Tools.logStep(
73-
string.Format(Environment.NewLine + "Fronting Result: {0}", frontingSuccess ? "SUCCESS" : "FAILED") + Environment.NewLine +
79+
string.Format(Environment.NewLine + "Fronting Result: {0}", frontingSuccess ? "SUCCESS" : "FAILED") + Environment.NewLine +
7480
string.Format("v2ray.exe Execution: {0}", isV2rayExecutionSuccess ? "SUCCESS" : "FAILED") + Environment.NewLine +
75-
string.Format("Download Result: {0}", v2rayDLSuccess ? "SUCCESS" : "FAILED"), isDiagnosing
81+
string.Format("Download Result: {0}", checkResultStatus.isDownSuccess() ? "SUCCESS" : "FAILED") + Environment.NewLine +
82+
string.Format("Upload Result: {0}", checkResultStatus.isUpSuccess() ? "SUCCESS" : "FAILED"), isDiagnosing
7683
);
7784

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

8188
}
8289

83-
public bool checkV2ray() {
90+
public bool checkV2ray()
91+
{
8492
bool success = false;
93+
8594
// create config
8695
if (createV2rayConfigFile())
8796
{
8897
// start v2ray.exe process
8998
if (runV2rayProcess())
9099
{
91-
// send download request
92-
if (checkDownloadSpeed())
100+
// send download/upload request
101+
if (checkV2raySpeed())
93102
{
94103
// speed was enough
95104
success = true;
@@ -123,14 +132,14 @@ public bool checkFronting(bool withCustumDNSResolver = true, int timeout = 1)
123132
Stopwatch sw = new Stopwatch();
124133
try
125134
{
126-
135+
127136
string frUrl = "https://" + ConfigManager.Instance.getAppConfig()?.frontDomain;
128137
Tools.logStep($"Fronting check with url: {frUrl}", isDiagnosing);
129138
sw.Start();
130139
var html = client.GetStringAsync(frUrl).Result;
131140
Tools.logStep($"Fronting check done in {sw.ElapsedMilliseconds:n0} ms, content: '{html.Substring(0, 50)}'", isDiagnosing);
132141
frontingDuration = sw.ElapsedMilliseconds;
133-
return true;
142+
return html.StartsWith("0000000000");
134143
}
135144
catch (Exception ex)
136145
{
@@ -156,66 +165,45 @@ public bool checkFronting(bool withCustumDNSResolver = true, int timeout = 1)
156165

157166
}
158167

159-
private bool checkDownloadSpeed()
168+
private bool checkV2raySpeed()
160169
{
161-
var proxy = new WebProxy();
162-
proxy.Address = new Uri($"socks5://127.0.0.1:{port}");
163-
var handler = new HttpClientHandler
170+
// check download
171+
if (checkType is CheckType.DOWNLOAD or CheckType.BOTH || isDiagnosing)
164172
{
165-
Proxy = proxy
166-
};
167-
168-
int timeout = this.downloadTimeout;
169-
170-
var client = new HttpClient(handler);
171-
client.Timeout = TimeSpan.FromSeconds(timeout); // 2 seconds
172-
Tools.logStep(Environment.NewLine + "----- Download Test -----", isDiagnosing);
173-
Tools.logStep($"Start check dl speed, proxy port: {port}, timeout: {timeout} sec, target speed: {targetSpeed.getTargetSpeed():n0} b/s", isDiagnosing);
174-
Stopwatch sw = new Stopwatch();
175-
//ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
176-
177-
try
178-
{
179-
sw.Start();
180-
string dlUrl = "https://" + ConfigManager.Instance.getAppConfig().scanDomain + targetSpeed.getTargetFileSize(timeout);
181-
Tools.logStep($"Starting dl url: {dlUrl}", isDiagnosing);
182-
var data = client.GetStringAsync(dlUrl).Result;
183-
Tools.logStep($"*** Download success in {sw.ElapsedMilliseconds:n0} ms, dl size: {data.Length:n0} bytes for IP {ip}", isDiagnosing);
184-
185-
return data.Length == targetSpeed.getTargetSpeed() * timeout;
186-
}
187-
catch (Exception ex)
188-
{
189-
string message = ex.Message;
190-
if (isTimeoutException(ex))
173+
string dlUrl = "https://" + ConfigManager.Instance.getAppConfig().downloadDomain + dlTargetSpeed.getTargetFileSize(checkTimeout);
174+
var cs = new CheckSettings(ip, port, checkTimeout, dlUrl, isDiagnosing, checkType, dlTargetSpeed);
175+
var dlChecker = new DownloadChecker(cs);
176+
if (dlChecker.check())
191177
{
192-
Tools.logStep("Download timed out.", isDiagnosing);
178+
checkResultStatus.setDownloadSuccess();
179+
downloadDuration = dlChecker.checkDuration;
193180
}
194181
else
195182
{
196-
Tools.logStep($"Download had exception: {message}", isDiagnosing);
197-
// monitor exceptions
198-
downloadException = message;
199-
200-
if (ex.InnerException != null && ex.InnerException?.Message != "" && ! ex.Message.Contains(ex.InnerException?.Message))
201-
{
202-
Tools.logStep($"Inner exception: {ex.InnerException?.Message}", isDiagnosing);
203-
}
183+
this.downloadException = dlChecker.exceptionMessage;
204184
}
205185

206-
return false;
207186
}
208-
finally
209-
{
210-
downloadDuration = sw.ElapsedMilliseconds;
211-
if(downloadDuration > (timeout * 1000) + 500)
187+
188+
// check upload
189+
if (checkType is CheckType.UPLOAD or CheckType.BOTH || isDiagnosing){
190+
string upUrl = "https://" + ConfigManager.Instance.getAppConfig().uploadDomain;
191+
var cs = new CheckSettings(ip, port, checkTimeout, upUrl, isDiagnosing, checkType, upTargetSpeed);
192+
var upChecker = new UploadChecker(cs);
193+
if (upChecker.check())
212194
{
213-
Tools.logStep($"Download took too long! {downloadDuration:n0} ms for IP {ip}", isDiagnosing);
195+
checkResultStatus.setUploadSuccess();
196+
uploadDuration = upChecker.checkDuration;
197+
}
198+
else
199+
{
200+
this.uploadException = upChecker.exceptionMessage;
214201
}
215-
handler.Dispose();
216-
client.Dispose();
217202
}
203+
204+
return checkResultStatus.isSuccess();
218205
}
206+
219207
private bool isTimeoutException(Exception ex)
220208
{
221209
string msg = ex.Message;
@@ -240,15 +228,15 @@ private bool createV2rayConfigFile()
240228
.Replace("HOSTHOST", clientConfig.host)
241229
.Replace("CFPORTCFPORT", clientConfig.port)
242230
.Replace("RANDOMHOST", getRandomSNI(clientConfig.host))
243-
.Replace("IP.IP.IP.IP", this.ip)
231+
.Replace("IP.IP.IP.IP", ip)
244232
.Replace("ENDPOINTENDPOINT", clientConfig.path);
245233
}
246234
else
247235
{ // just replace port and ip for custom v2ray configs
248236
configTemplate = scanConfig.content;
249237
configTemplate = configTemplate
250238
.Replace("PORTPORT", port)
251-
.Replace("IP.IP.IP.IP", this.ip);
239+
.Replace("IP.IP.IP.IP", ip);
252240
}
253241

254242
File.WriteAllText(v2rayConfigPath, configTemplate);
@@ -267,15 +255,15 @@ private string getRandomSNI(string host)
267255
{
268256
var urlParts = host.Split(".");
269257
urlParts[0] = Guid.NewGuid().ToString();
270-
return string.Join(".", urlParts);
258+
return string.Join(".", urlParts);
271259
}
272260

273261
// sum of ip segments plus 3000
274262
private string getPortByIP()
275-
{
276-
int sum = Int32.Parse(
277-
this.ip.Split(".").Aggregate((current, next) =>
278-
(Int32.Parse(current) + Int32.Parse(next)).ToString())
263+
{
264+
int sum = int.Parse(
265+
ip.Split(".").Aggregate((current, next) =>
266+
(int.Parse(current) + int.Parse(next)).ToString())
279267
);
280268

281269
return (3000 + sum).ToString();
@@ -287,10 +275,10 @@ private bool runV2rayProcess()
287275
startInfo.FileName = "v2ray.exe";
288276
//if (!ConfigManager.Instance.enableDebug)
289277
//{
290-
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
291-
startInfo.RedirectStandardOutput = true;
292-
startInfo.RedirectStandardError = true;
293-
startInfo.CreateNoWindow = true;
278+
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
279+
startInfo.RedirectStandardOutput = true;
280+
startInfo.RedirectStandardError = true;
281+
startInfo.CreateNoWindow = true;
294282
//}
295283
startInfo.UseShellExecute = false;
296284
startInfo.Arguments = $"run -config=\"{v2rayConfigPath}\"";
@@ -309,7 +297,7 @@ private bool runV2rayProcess()
309297
{
310298
Tools.logStep($"v2ray.exe execution had exception: {ex.Message}", isDiagnosing);
311299
}
312-
300+
313301
// log error
314302
if (!wasSuccess)
315303
{
@@ -320,14 +308,14 @@ private bool runV2rayProcess()
320308
Tools.logStep(message, isDiagnosing);
321309
downloadException = message;
322310
}
323-
catch (Exception) {}
311+
catch (Exception) { }
324312
}
325313

326314
isV2rayExecutionSuccess = wasSuccess;
327315

328316
return wasSuccess;
329317
}
330318

331-
319+
332320
}
333321
}

0 commit comments

Comments
 (0)