Got at least one data fetching method working; turns out, we can't use a patched LogicStack to get the data

This commit is contained in:
2026-01-14 22:11:11 +01:00
parent 40a8431464
commit 3f7122d30a
350 changed files with 41444 additions and 119 deletions

View File

@@ -0,0 +1,93 @@
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
namespace EmbedIO.Security
{
/// <summary>
/// Represents a maximun requests per second criterion for <see cref="IPBanningModule"/>.
/// </summary>
/// <seealso cref="IIPBanningCriterion" />
public class IPBanningRequestsCriterion : IIPBanningCriterion
{
/// <summary>
/// The default maximum request per second.
/// </summary>
public const int DefaultMaxRequestsPerSecond = 50;
private static readonly ConcurrentDictionary<IPAddress, ConcurrentBag<long>> Requests = new ConcurrentDictionary<IPAddress, ConcurrentBag<long>>();
private readonly int _maxRequestsPerSecond;
private bool _disposed;
internal IPBanningRequestsCriterion(int maxRequestsPerSecond)
{
_maxRequestsPerSecond = maxRequestsPerSecond;
}
/// <summary>
/// Finalizes an instance of the <see cref="IPBanningRequestsCriterion"/> class.
/// </summary>
~IPBanningRequestsCriterion()
{
Dispose(false);
}
/// <inheritdoc />
public Task<bool> ValidateIPAddress(IPAddress address)
{
Requests.GetOrAdd(address, new ConcurrentBag<long>()).Add(DateTime.Now.Ticks);
var lastSecond = DateTime.Now.AddSeconds(-1).Ticks;
var lastMinute = DateTime.Now.AddMinutes(-1).Ticks;
var shouldBan = Requests.TryGetValue(address, out var attempts) &&
(attempts.Count(x => x >= lastSecond) >= _maxRequestsPerSecond ||
(attempts.Count(x => x >= lastMinute) / 60) >= _maxRequestsPerSecond);
return Task.FromResult(shouldBan);
}
/// <inheritdoc />
public void ClearIPAddress(IPAddress address) =>
Requests.TryRemove(address, out _);
/// <inheritdoc />
public void PurgeData()
{
var minTime = DateTime.Now.AddMinutes(-1).Ticks;
foreach (var k in Requests.Keys)
{
if (!Requests.TryGetValue(k, out var requests)) continue;
var recentRequests = new ConcurrentBag<long>(requests.Where(x => x >= minTime));
if (!recentRequests.Any())
Requests.TryRemove(k, out _);
else
Requests.AddOrUpdate(k, recentRequests, (x, y) => recentRequests);
}
}
/// <inheritdoc />
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
if (disposing)
{
Requests.Clear();
}
_disposed = true;
}
}
}