mirror of
https://github.com/JogmansonReal/Radicade.git
synced 2026-10-25 23:18:56 -07:00
117 lines
2.3 KiB
C#
117 lines
2.3 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using RadicadeServer.DB;
|
|
|
|
namespace RadicadeServer.Utils
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static class GameBlockMonitor
|
|
{
|
|
private static readonly object Lock = new();
|
|
private static readonly SemaphoreSlim RefreshGate = new(1, 1);
|
|
private static Dictionary<string, DateTime?> Active = new();
|
|
private static DateTime LastRefresh = DateTime.MinValue;
|
|
private const double RefreshIntervalSeconds = 10;
|
|
|
|
|
|
|
|
|
|
|
|
public static async Task<bool> IsBlockedAsync(IDbContextFactory<RecDBContext> factory, string ipAddress)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(ipAddress)) return false;
|
|
|
|
DateTime lastRefresh;
|
|
lock (Lock) lastRefresh = LastRefresh;
|
|
if ((DateTime.UtcNow - lastRefresh).TotalSeconds > RefreshIntervalSeconds)
|
|
await RefreshAsync(factory);
|
|
|
|
lock (Lock)
|
|
{
|
|
if (Active.TryGetValue(NormalizeIp(ipAddress), out var expiresAt))
|
|
return !expiresAt.HasValue || expiresAt.Value > DateTime.UtcNow;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static void Invalidate()
|
|
{
|
|
lock (Lock) LastRefresh = DateTime.MinValue;
|
|
}
|
|
|
|
public static async Task RefreshAsync(IDbContextFactory<RecDBContext> factory)
|
|
{
|
|
await RefreshGate.WaitAsync();
|
|
try
|
|
{
|
|
|
|
DateTime lastRefresh;
|
|
lock (Lock) lastRefresh = LastRefresh;
|
|
if ((DateTime.UtcNow - lastRefresh).TotalSeconds <= RefreshIntervalSeconds)
|
|
return;
|
|
|
|
try
|
|
{
|
|
await using var db = await factory.CreateDbContextAsync();
|
|
var now = DateTime.UtcNow;
|
|
var rows = await db.GameBlocks.AsNoTracking().ToListAsync();
|
|
|
|
|
|
|
|
var expired = rows.Where(b => b.ExpiresAt.HasValue && b.ExpiresAt.Value < now).ToList();
|
|
if (expired.Count > 0)
|
|
{
|
|
db.GameBlocks.RemoveRange(expired);
|
|
await db.SaveChangesAsync();
|
|
}
|
|
|
|
var active = new Dictionary<string, DateTime?>();
|
|
foreach (var row in rows.Where(b => !expired.Contains(b)))
|
|
active[NormalizeIp(row.IpAddress)] = row.ExpiresAt;
|
|
|
|
lock (Lock)
|
|
{
|
|
Active = active;
|
|
LastRefresh = DateTime.UtcNow;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
|
|
|
|
lock (Lock) LastRefresh = DateTime.UtcNow;
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
RefreshGate.Release();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static string NormalizeIp(string ip)
|
|
{
|
|
ip = (ip ?? "").Trim();
|
|
if (ip.StartsWith("::ffff:", StringComparison.OrdinalIgnoreCase))
|
|
ip = ip.Substring("::ffff:".Length);
|
|
return ip;
|
|
}
|
|
}
|
|
}
|