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(); }