// WingsEmu // // Developed by NosWings Team using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using PhoenixLib.Logging; using WingsEmu.Core.Generics; namespace GameChannel.Utils { /// /// Todo MOVE to Redis + AlertManager + Prometheus /// public class SmartSpamProtector : ISpamProtector { private const int CONNECTION_ATTEMPTS_BEFORE_BLACKLIST = 2; private static readonly TimeSpan TimeBetweenConnection = TimeSpan.FromMilliseconds(150); private static readonly ThreadSafeHashSet BlacklistedIps = new(); private static readonly ConcurrentDictionary> ConnectionsByIp = new(); public bool CanConnect(string ipAddress) { if (BlacklistedIps.Contains(ipAddress)) { return false; } if (!ConnectionsByIp.TryGetValue(ipAddress, out List dates)) { dates = new List(); ConnectionsByIp[ipAddress] = dates; } DateTime lastConnection = dates.LastOrDefault(); dates.Add(DateTime.UtcNow); if (dates.Count > CONNECTION_ATTEMPTS_BEFORE_BLACKLIST) { BlacklistedIps.Add(ipAddress); Log.Warn($"[SPAM_PROTECTOR] Blacklisted {ipAddress}"); return false; } // should be accepted if (lastConnection.Add(TimeBetweenConnection) >= DateTime.UtcNow) { return false; } dates.Clear(); return true; } } }