/// <summary> /// The rate limit. /// </summary> /// <param name="hostname"> /// The hostname. /// </param> /// <param name="channel"> /// The channel. /// </param> /// <returns> /// true if rate limited, false otherwise /// </returns> private bool RateLimit(string hostname, string channel) { if (string.IsNullOrEmpty(hostname) || string.IsNullOrEmpty(channel)) { // sanity check - this probably chanserv. this.logger.Error("JoinMessage ratelimiting called with null channel or null hostname!"); return true; } try { // TODO: rate limiting needs to be tidyed up a bit lock (this.rateLimitCache) { if (!this.rateLimitCache.ContainsKey(channel)) { this.rateLimitCache.Add(channel, new Cache()); } var channelCache = this.rateLimitCache[channel]; if (channelCache.ContainsKey(hostname)) { this.logger.Debug("Rate limit key found."); var cacheEntry = channelCache[hostname]; if (cacheEntry.Expiry.AddMinutes(RateLimitDuration) >= DateTime.Now) { this.logger.Debug("Rate limit key NOT expired."); if (cacheEntry.Counter >= RateLimitMax) { this.logger.Debug("Rate limit HIT"); // RATE LIMITED! return true; } this.logger.Debug("Rate limit incremented."); // increment counter cacheEntry.Counter++; } else { this.logger.Debug("Rate limit key is expired, resetting to new value."); // Cache expired cacheEntry.Expiry = DateTime.Now; cacheEntry.Counter = 1; } } else { this.logger.Debug("Rate limit not found, creating key."); // Not in cache. var cacheEntry = new RateLimitCacheEntry { Expiry = DateTime.Now, Counter = 1 }; channelCache.Add(hostname, cacheEntry); } // Clean up the channel's cache. foreach (var key in channelCache.Keys.ToList()) { if (channelCache[key].Expiry.AddMinutes(RateLimitDuration) < DateTime.Now) { // Expired. channelCache.Remove(key); } } } } catch (Exception ex) { // ooh dear. Something went wrong with rate limiting. this.logger.Error("Unknown error during rate limit processing.", ex); return false; } return false; }
/// <summary> /// The rate limit. /// </summary> /// <returns> /// The <see cref="bool"/>. /// </returns> private bool RateLimit() { if (this.Source == null || this.Source.Hostname == null) { this.Log.Error("Rate limiting called with no source or no source hostname!"); return true; } // TODO: rate limiting needs to be tidyed up a bit lock (RateLimitCache) { if (RateLimitCache.ContainsKey(this.Source.Hostname)) { this.Log.Debug("Rate limit key found."); var cacheEntry = RateLimitCache[this.Source.Hostname]; if (cacheEntry.Expiry.AddMinutes(RateLimitDuration) >= DateTime.Now) { this.Log.Debug("Rate limit key NOT expired."); if (cacheEntry.Counter >= RateLimitMax) { this.Log.Debug("Rate limit HIT"); // RATE LIMITED! return true; } this.Log.Debug("Rate limit incremented."); // increment counter cacheEntry.Counter++; } else { this.Log.Debug("Rate limit key is expired, resetting to new value."); // Cache expired cacheEntry.Expiry = DateTime.Now; cacheEntry.Counter = 1; } } else { this.Log.Debug("Rate limit not found, creating key."); // Not in cache. var cacheEntry = new RateLimitCacheEntry { Expiry = DateTime.Now, Counter = 1 }; RateLimitCache.Add(this.Source.Hostname, cacheEntry); } // Clean up the cache foreach (var key in RateLimitCache.Keys.ToList()) { if (RateLimitCache[key].Expiry.AddMinutes(RateLimitDuration) < DateTime.Now) { // Expired. RateLimitCache.Remove(key); } } } return false; }