10095
|
1 |
{-# LANGUAGE OverloadedStrings, BangPatterns #-}
|
10090
|
2 |
module FloodDetection where
|
|
3 |
|
10093
|
4 |
import Control.Monad.State.Strict
|
|
5 |
import Data.Time
|
|
6 |
import Control.Arrow
|
|
7 |
----------------
|
|
8 |
import ServerState
|
10090
|
9 |
import CoreTypes
|
10095
|
10 |
import Utils
|
10090
|
11 |
|
10093
|
12 |
registerEvent :: Event -> StateT ServerState IO [Action]
|
|
13 |
registerEvent e = do
|
|
14 |
eventInfo <- client's $ einfo e
|
10094
|
15 |
if (null eventInfo) || 0 == (fst $ head eventInfo) then doCheck eventInfo else updateInfo
|
10095
|
16 |
|
10093
|
17 |
where
|
|
18 |
einfo LobbyChatMessage = eiLobbyChat
|
|
19 |
einfo EngineMessage = eiEM
|
|
20 |
einfo RoomJoin = eiJoin
|
10094
|
21 |
|
10093
|
22 |
transformField LobbyChatMessage f = \c -> c{eiLobbyChat = f $ eiLobbyChat c}
|
10095
|
23 |
transformField EngineMessage f = \c -> c{eiEM = f $ eiEM c}
|
|
24 |
transformField RoomJoin f = \c -> c{eiJoin = f $ eiJoin c}
|
10094
|
25 |
|
10095
|
26 |
boundaries :: Event -> (Int, (NominalDiffTime, Int), (NominalDiffTime, Int), ([Action], [Action]))
|
|
27 |
boundaries LobbyChatMessage = (3, (10, 2), (30, 3), (chat1, chat2))
|
|
28 |
boundaries EngineMessage = (8, (10, 4), (25, 5), (em1, em2))
|
|
29 |
boundaries RoomJoin = (2, (10, 2), (35, 3), (join1, join2))
|
|
30 |
|
|
31 |
chat1 = [Warning $ loc "Warning! Chat flood protection activated"]
|
|
32 |
chat2 = [ByeClient $ loc "Excess flood"]
|
|
33 |
em1 = [Warning $ loc "Game messages flood detected - 1"]
|
|
34 |
em2 = [Warning $ loc "Game messages flood detected - 2"]
|
|
35 |
join1 = [Warning $ loc "Warning! Joins flood protection activated"]
|
|
36 |
join2 = [ByeClient $ loc "Excess flood"]
|
10094
|
37 |
|
10093
|
38 |
doCheck ei = do
|
10094
|
39 |
curTime <- io getCurrentTime
|
10095
|
40 |
let (numPerEntry, (sec1, num1), (sec2, num2), (ac1, ac2)) = boundaries e
|
|
41 |
|
|
42 |
let nei = takeWhile ((>=) sec2 . diffUTCTime curTime . snd) ei
|
|
43 |
let l2 = length nei
|
|
44 |
let l1 = length $ takeWhile ((>=) sec1 . diffUTCTime curTime . snd) nei
|
10094
|
45 |
|
10095
|
46 |
let actions = if l2 >= num2 + 1 || l1 >= num1 + 1 then
|
|
47 |
ac2
|
|
48 |
else
|
|
49 |
if l1 >= num1 || l2 >= num2 then
|
|
50 |
ac1
|
|
51 |
else
|
|
52 |
[]
|
10094
|
53 |
|
10095
|
54 |
return $ (ModifyClient . transformField e . const $ (numPerEntry, curTime) : nei) : actions
|
10094
|
55 |
|
10093
|
56 |
updateInfo = return [
|
10094
|
57 |
ModifyClient $ transformField e
|
|
58 |
$ \(h:hs) -> first (flip (-) 1) h : hs
|
10093
|
59 |
]
|