Files
MeWeb/src/MeWeb.Core/Net/SpeedCheck.cs
T

58 lines
2.1 KiB
C#
Raw Normal View History

using System.Diagnostics;
using MeWeb.Shared;
namespace MeWeb.Core.Net;
public class SpeedReport
{
public double DownMbps { get; set; }
public double UpMbps { get; set; }
public int DownBytes { get; set; }
public int UpBytes { get; set; }
public bool Limited { get; set; }
}
public static class SpeedCheck
{
public static async Task<SpeedReport> Run(HttpClient https, LinkKind kind, CancellationToken ct)
{
var mobile = kind == LinkKind.Mobile;
var report = new SpeedReport { DownBytes = mobile ? 2 * 1024 * 1024 : 12 * 1024 * 1024, UpBytes = mobile ? 1024 * 1024 : 4 * 1024 * 1024 };
try
{
using var timeout = CancellationTokenSource.CreateLinkedTokenSource(ct);
timeout.CancelAfter(TimeSpan.FromSeconds(30));
var clock = Stopwatch.StartNew();
using (var response = await https.GetAsync(Endpoints.Base + Endpoints.Speed.GET_M_Down(report.DownBytes), HttpCompletionOption.ResponseHeadersRead, timeout.Token))
{
if ((int)response.StatusCode == 429)
{
report.Limited = true;
return report;
}
response.EnsureSuccessStatusCode();
await using var body = await response.Content.ReadAsStreamAsync(timeout.Token);
var buffer = new byte[64 * 1024];
long total = 0;
int read;
while ((read = await body.ReadAsync(buffer, timeout.Token)) > 0) total += read;
report.DownMbps = Mbps(total, clock.Elapsed);
}
var payload = new byte[report.UpBytes];
Random.Shared.NextBytes(payload);
clock.Restart();
using (var response = await https.PostAsync(Endpoints.Base + Endpoints.Speed.POST_Up, new ByteArrayContent(payload), timeout.Token))
{
if (response.IsSuccessStatusCode) report.UpMbps = Mbps(payload.Length, clock.Elapsed);
}
}
catch (Exception ex) when (ex is HttpRequestException or TaskCanceledException or IOException && !ct.IsCancellationRequested)
{
}
return report;
}
static double Mbps(long bytes, TimeSpan elapsed) => elapsed.TotalSeconds <= 0 ? 0 : Math.Round(bytes * 8 / elapsed.TotalSeconds / 1_000_000, 1);
}