81 lines
3 KiB
C#
81 lines
3 KiB
C#
|
using SharpChat.Configuration;
|
|||
|
using SharpChat.Protocol;
|
|||
|
using SharpChat.Users;
|
|||
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
|
|||
|
namespace SharpChat.RateLimiting {
|
|||
|
public class RateLimitManager {
|
|||
|
public const int DEFAULT_USER_SIZE = 15;
|
|||
|
public const int DEFAULT_USER_WARN_SIZE = 10;
|
|||
|
public const int DEFAULT_CONN_SIZE = 30;
|
|||
|
public const int DEFAULT_MINIMUM_DELAY = 5000;
|
|||
|
public const int DEFAULT_KICK_LENGTH = 5;
|
|||
|
public const int DEFAULT_KICK_MULTIPLIER = 2;
|
|||
|
|
|||
|
private CachedValue<int> UserSizeValue { get; }
|
|||
|
private CachedValue<int> UserWarnSizeValue { get; }
|
|||
|
private CachedValue<int> ConnSizeValue { get; }
|
|||
|
private CachedValue<int> MinimumDelayValue { get; }
|
|||
|
private CachedValue<int> KickLengthValue { get; }
|
|||
|
private CachedValue<int> KickMultiplierValue { get; }
|
|||
|
|
|||
|
private readonly object ConnectionsSync = new();
|
|||
|
private Dictionary<string, RateLimiter> Connections { get; } = new();
|
|||
|
|
|||
|
private readonly object UsersSync = new();
|
|||
|
private Dictionary<long, RateLimiter> Users { get; } = new();
|
|||
|
|
|||
|
public RateLimitManager(IConfig config) {
|
|||
|
UserSizeValue = config.ReadCached(@"userSize", DEFAULT_USER_SIZE);
|
|||
|
UserWarnSizeValue = config.ReadCached(@"userWarnSize", DEFAULT_USER_WARN_SIZE);
|
|||
|
ConnSizeValue = config.ReadCached(@"connSize", DEFAULT_CONN_SIZE);
|
|||
|
MinimumDelayValue = config.ReadCached(@"minDelay", DEFAULT_MINIMUM_DELAY);
|
|||
|
KickLengthValue = config.ReadCached(@"kickLength", DEFAULT_KICK_LENGTH);
|
|||
|
KickMultiplierValue = config.ReadCached(@"kickMultiplier", DEFAULT_KICK_MULTIPLIER);
|
|||
|
}
|
|||
|
|
|||
|
private RateLimiter CreateForConnection() {
|
|||
|
return new RateLimiter(
|
|||
|
ConnSizeValue,
|
|||
|
-1,
|
|||
|
MinimumDelayValue
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
private RateLimiter CreateForUser() {
|
|||
|
return new RateLimiter(
|
|||
|
UserSizeValue,
|
|||
|
UserWarnSizeValue,
|
|||
|
MinimumDelayValue
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
public TimeSpan GetKickLength(int kickCount) {
|
|||
|
if(kickCount < 1)
|
|||
|
kickCount = 1;
|
|||
|
return TimeSpan.FromSeconds(KickLengthValue * (KickMultiplierValue * kickCount));
|
|||
|
}
|
|||
|
|
|||
|
public bool UpdateConnection(IConnection conn) {
|
|||
|
lock(ConnectionsSync) {
|
|||
|
string connId = conn.ConnectionId;
|
|||
|
if(!Connections.ContainsKey(connId))
|
|||
|
Connections[connId] = CreateForConnection();
|
|||
|
Connections[connId].Update();
|
|||
|
return Connections[connId].ShouldKick;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public (bool kick, bool warn) UpdateUser(IUser user) {
|
|||
|
lock(UsersSync) {
|
|||
|
long userId = user.UserId;
|
|||
|
if(!Users.ContainsKey(userId))
|
|||
|
Users[userId] = CreateForUser();
|
|||
|
Users[userId].Update();
|
|||
|
return (Users[userId].ShouldKick, Users[userId].ShouldWarn);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|