From 83d6722d31a3deb51b34a18c46bb4a904902dff0 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sat, 6 Aug 2016 22:12:38 +0100 Subject: [PATCH] if a viewer overloads region capability to process RequestMapBlocks, ignore following requests for 300 seconds. This was necessary becaus some viewers like FireStorm are doing it, saturating region and grid services for no usefull reason --- .../World/WorldMap/WorldMapModule.cs | 75 ++++++++++++++++--- 1 file changed, 64 insertions(+), 11 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index 6f10f5153f..959829cf69 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -1060,27 +1060,80 @@ namespace OpenSim.Region.CoreModules.World.WorldMap /// public void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) { - m_log.DebugFormat("[WoldMapModule] RequestMapBlocks {0}={1}={2}={3} {4}", minX, minY, maxX, maxY, flag); +// m_log.DebugFormat("[WoldMapModule] RequestMapBlocks {0}={1}={2}={3} {4}", minX, minY, maxX, maxY, flag); GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag); } + private const double SPAMBLOCKTIMEms = 300000; // 5 minutes + private Dictionary spamBlocked = new Dictionary(); + protected virtual List GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) { - MapBlockRequestData req = new MapBlockRequestData(); + // anti spam because of FireStorm 4.7.7 absurd request repeat rates + // possible others - req.client = remoteClient; - req.minX = minX; - req.maxX = maxX; - req.minY = minY; - req.maxY = maxY; - req.flags = flag; + double now = Util.GetTimeStampMS(); + UUID agentID = remoteClient.AgentId; lock (m_mapBlockRequestEvent) { - if (!m_mapBlockRequests.ContainsKey(remoteClient.AgentId)) - m_mapBlockRequests[remoteClient.AgentId] = new Queue(); - m_mapBlockRequests[remoteClient.AgentId].Enqueue(req); + if(spamBlocked.ContainsKey(agentID)) + { + if(spamBlocked[agentID] < now && + (!m_mapBlockRequests.ContainsKey(agentID) || + m_mapBlockRequests[agentID].Count == 0 )) + { + spamBlocked.Remove(agentID); + m_log.DebugFormat("[WoldMapModule] RequestMapBlocks release spammer {0}", agentID); + } + else + return new List(); + } + else + { + // ugly slow expire spammers + if(spamBlocked.Count > 0) + { + UUID k = UUID.Zero; + bool expireone = false; + foreach(UUID k2 in spamBlocked.Keys) + { + if(spamBlocked[k2] < now && + (!m_mapBlockRequests.ContainsKey(k2) || + m_mapBlockRequests[k2].Count == 0 )) + { + m_log.DebugFormat("[WoldMapModule] RequestMapBlocks release spammer {0}", k2); + k = k2; + expireone = true; + } + break; // doing one at a time + } + if(expireone) + spamBlocked.Remove(k); + } + } + +// m_log.DebugFormat("[WoldMapModule] RequestMapBlocks {0}={1}={2}={3} {4}", minX, minY, maxX, maxY, flag); + + MapBlockRequestData req = new MapBlockRequestData(); + + req.client = remoteClient; + req.minX = minX; + req.maxX = maxX; + req.minY = minY; + req.maxY = maxY; + req.flags = flag; + + if (!m_mapBlockRequests.ContainsKey(agentID)) + m_mapBlockRequests[agentID] = new Queue(); + if(m_mapBlockRequests[agentID].Count < 150 ) + m_mapBlockRequests[agentID].Enqueue(req); + else + { + spamBlocked[agentID] = now + SPAMBLOCKTIMEms; + m_log.DebugFormat("[WoldMapModule] RequestMapBlocks blocking spammer {0} for {1} s",agentID, SPAMBLOCKTIMEms/1000.0); + } m_mapBlockRequestEvent.Set(); }