From 2f4aa1b3965a0df306043e0729114fcb53d94a77 Mon Sep 17 00:00:00 2001 From: Stanley Dimant Date: Mon, 11 Nov 2024 12:45:52 +0100 Subject: [PATCH] add speedtest stuff or so --- .../Controllers/JwtController.cs | 1 - .../StaticFilesServerConfiguration.cs | 1 + .../Controllers/ServerFilesController.cs | 14 ++++ .../Controllers/SpeedTestController.cs | 64 +++++++++++++++++++ .../Startup.cs | 8 ++- 5 files changed, 84 insertions(+), 4 deletions(-) create mode 100644 MareSynchronosServer/MareSynchronosStaticFilesServer/Controllers/SpeedTestController.cs diff --git a/MareSynchronosServer/MareSynchronosAuthService/Controllers/JwtController.cs b/MareSynchronosServer/MareSynchronosAuthService/Controllers/JwtController.cs index cca415e..5c4ec8d 100644 --- a/MareSynchronosServer/MareSynchronosAuthService/Controllers/JwtController.cs +++ b/MareSynchronosServer/MareSynchronosAuthService/Controllers/JwtController.cs @@ -9,7 +9,6 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using StackExchange.Redis.Extensions.Core.Abstractions; -using System.Security.Cryptography; namespace MareSynchronosAuthService.Controllers; diff --git a/MareSynchronosServer/MareSynchronosShared/Utils/Configuration/StaticFilesServerConfiguration.cs b/MareSynchronosServer/MareSynchronosShared/Utils/Configuration/StaticFilesServerConfiguration.cs index 7da2d80..b2a16ce 100644 --- a/MareSynchronosServer/MareSynchronosShared/Utils/Configuration/StaticFilesServerConfiguration.cs +++ b/MareSynchronosServer/MareSynchronosShared/Utils/Configuration/StaticFilesServerConfiguration.cs @@ -20,6 +20,7 @@ public class StaticFilesServerConfiguration : MareConfigurationBase public bool UseColdStorage { get; set; } = false; public string ColdStorageDirectory { get; set; } = null; public double ColdStorageSizeHardLimitInGiB { get; set; } = -1; + public int SpeedTestHoursRateLimit { get; set; } = 6; public int ColdStorageUnusedFileRetentionPeriodInDays { get; set; } = 30; [RemoteConfiguration] public Uri CdnFullUrl { get; set; } = null; diff --git a/MareSynchronosServer/MareSynchronosStaticFilesServer/Controllers/ServerFilesController.cs b/MareSynchronosServer/MareSynchronosStaticFilesServer/Controllers/ServerFilesController.cs index e457ba4..ba24df2 100644 --- a/MareSynchronosServer/MareSynchronosStaticFilesServer/Controllers/ServerFilesController.cs +++ b/MareSynchronosServer/MareSynchronosStaticFilesServer/Controllers/ServerFilesController.cs @@ -130,6 +130,20 @@ public class ServerFilesController : ControllerBase return Ok(JsonSerializer.Serialize(response)); } + [HttpGet(MareFiles.ServerFiles_DownloadServers)] + public async Task GetDownloadServers() + { + var allFileShards = new List(_configuration.GetValueOrDefault(nameof(StaticFilesServerConfiguration.CdnShardConfiguration), new List())) + .DistinctBy(f => f.CdnFullUrl).ToList(); + if (!allFileShards.Any()) + { + return Ok(JsonSerializer.Serialize(new List { _configuration.GetValue(nameof(StaticFilesServerConfiguration.CdnFullUrl)).ToString() })); + } + var selectedShards = allFileShards.Where(c => c.Continents.Contains(Continent, StringComparer.OrdinalIgnoreCase)).ToList(); + if (!selectedShards.Any()) selectedShards = allFileShards.Where(c => c.Continents.Contains("*", StringComparer.Ordinal)).ToList(); + return Ok(JsonSerializer.Serialize(selectedShards.Select(t => t.CdnFullUrl.ToString()))); + } + [HttpPost(MareFiles.ServerFiles_FilesSend)] public async Task FilesSend([FromBody] FilesSendDto filesSendDto) { diff --git a/MareSynchronosServer/MareSynchronosStaticFilesServer/Controllers/SpeedTestController.cs b/MareSynchronosServer/MareSynchronosStaticFilesServer/Controllers/SpeedTestController.cs new file mode 100644 index 0000000..7af1663 --- /dev/null +++ b/MareSynchronosServer/MareSynchronosStaticFilesServer/Controllers/SpeedTestController.cs @@ -0,0 +1,64 @@ +using MareSynchronos.API.Routes; +using MareSynchronosShared; +using MareSynchronosShared.Services; +using MareSynchronosShared.Utils.Configuration; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Caching.Memory; + +namespace MareSynchronosStaticFilesServer.Controllers; + +[Route(MareFiles.Speedtest)] +public class SpeedTestController : ControllerBase +{ + private readonly IMemoryCache _memoryCache; + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly IConfigurationService _configurationService; + private const string RandomByteDataName = "SpeedTestRandomByteData"; + private static readonly SemaphoreSlim _speedtestSemaphore = new(10, 10); + + public SpeedTestController(ILogger logger, + IMemoryCache memoryCache, IHttpContextAccessor httpContextAccessor, + IConfigurationService configurationService) : base(logger) + { + _memoryCache = memoryCache; + _httpContextAccessor = httpContextAccessor; + _configurationService = configurationService; + } + + [HttpGet(MareFiles.Speedtest_Run)] + public async Task DownloadTest(CancellationToken cancellationToken) + { + var ip = _httpContextAccessor.GetIpAddress(); + var speedtestLimit = _configurationService.GetValueOrDefault(nameof(StaticFilesServerConfiguration.SpeedTestHoursRateLimit), 6); + if (_memoryCache.TryGetValue(ip, out var value)) + { + var hoursRemaining = value.Subtract(DateTime.UtcNow).TotalHours; + return StatusCode(429, $"Can perform speedtest every {speedtestLimit} hours. {hoursRemaining:F2} hours remain."); + } + + await _speedtestSemaphore.WaitAsync(cancellationToken); + + try + { + var expiry = DateTime.UtcNow.Add(TimeSpan.FromHours(speedtestLimit)); + _memoryCache.Set(ip, expiry, TimeSpan.FromHours(speedtestLimit)); + + var randomByteData = _memoryCache.GetOrCreate(RandomByteDataName, (entry) => + { + byte[] data = new byte[10 * 1024 * 1024]; + new Random().NextBytes(data); + return data; + }); + + return File(randomByteData, "application/octet-stream", "speedtest.dat"); + } + catch (OperationCanceledException) + { + return StatusCode(499, "Cancelled"); + } + finally + { + _speedtestSemaphore.Release(); + } + } +} diff --git a/MareSynchronosServer/MareSynchronosStaticFilesServer/Startup.cs b/MareSynchronosServer/MareSynchronosStaticFilesServer/Startup.cs index c49378b..2d08098 100644 --- a/MareSynchronosServer/MareSynchronosStaticFilesServer/Startup.cs +++ b/MareSynchronosServer/MareSynchronosStaticFilesServer/Startup.cs @@ -186,6 +186,8 @@ public class Startup services.AddHostedService(p => (MareConfigurationServiceClient)p.GetService>()); } + services.AddMemoryCache(); + // controller setup services.AddControllers().ConfigureApplicationPartManager(a => { @@ -194,15 +196,15 @@ public class Startup { a.FeatureProviders.Add(new AllowedControllersFeatureProvider(typeof(MareStaticFilesServerConfigurationController), typeof(CacheController), typeof(RequestController), typeof(ServerFilesController), - typeof(DistributionController), typeof(MainController))); + typeof(DistributionController), typeof(MainController), typeof(SpeedTestController))); } else if (_isDistributionNode) { - a.FeatureProviders.Add(new AllowedControllersFeatureProvider(typeof(CacheController), typeof(RequestController), typeof(DistributionController))); + a.FeatureProviders.Add(new AllowedControllersFeatureProvider(typeof(CacheController), typeof(RequestController), typeof(DistributionController), typeof(SpeedTestController))); } else { - a.FeatureProviders.Add(new AllowedControllersFeatureProvider(typeof(CacheController), typeof(RequestController))); + a.FeatureProviders.Add(new AllowedControllersFeatureProvider(typeof(CacheController), typeof(RequestController), typeof(SpeedTestController))); } });