forked from graninas/Node
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPingServer.hs
71 lines (58 loc) · 2.61 KB
/
PingServer.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
{-# OPTIONS_GHC -fno-warn-orphans #-}
{-# LANGUAGE DuplicateRecordFields #-}
module Enecuum.Samples.Assets.Nodes.TstNodes.PingPong.PingServer where
import qualified Data.Aeson as A
import Enecuum.Samples.Assets.Nodes.TstNodes.PingPong.Messages
import Enecuum.Config
import qualified Enecuum.Domain as D
import qualified Enecuum.Language as L
import Enecuum.Prelude
data PingServerNode = PingServerNode
deriving (Show, Generic)
data instance NodeConfig PingServerNode = PingServerNodeConfig
{ _stopOnPing :: Int
, _servingPort :: D.PortNumber
}
deriving (Show, Generic)
instance Node PingServerNode where
data NodeScenario PingServerNode = PingServer
deriving (Show, Generic)
getNodeScript _ = pingServerNode
getNodeTag _ = PingServerNode
instance ToJSON PingServerNode where toJSON = A.genericToJSON nodeConfigJsonOptions
instance FromJSON PingServerNode where parseJSON = A.genericParseJSON nodeConfigJsonOptions
instance ToJSON (NodeConfig PingServerNode) where toJSON = A.genericToJSON nodeConfigJsonOptions
instance FromJSON (NodeConfig PingServerNode) where parseJSON = A.genericParseJSON nodeConfigJsonOptions
instance ToJSON (NodeScenario PingServerNode) where toJSON = A.genericToJSON nodeConfigJsonOptions
instance FromJSON (NodeScenario PingServerNode) where parseJSON = A.genericParseJSON nodeConfigJsonOptions
-- Handling Ping messages.
acceptPing
:: D.StateVar D.NodeStatus
-> D.StateVar Int
-> Int
-> Ping
-> D.Connection D.Udp
-> L.NodeL ()
acceptPing status pingsCount threshold (Ping clientName) conn = do
pings <- L.atomically $ do
L.modifyVar pingsCount (+1)
L.readVar pingsCount
let done = pings + 1 >= threshold
when done $ do
L.close conn
L.writeVarIO status D.NodeFinished
L.logInfo $ "Pings threshold reached: " +|| threshold ||+ ". Finishing."
unless done $ do
L.send conn (Pong pings)
L.logInfo $ "Ping #" +|| pings ||+ " accepted from " +|| clientName ||+ "."
-- Ping server definition node.
pingServerNode :: NodeConfig PingServerNode -> L.NodeDefinitionL ()
pingServerNode cfg = do
let threshold = _stopOnPing cfg
let port = _servingPort cfg
pingsCount <- L.newVarIO 0
status <- L.newVarIO D.NodeActing
-- Starting a separate process for serving on UDP port.
L.serving D.Udp port $
L.handler $ acceptPing status pingsCount threshold
L.awaitNodeFinished' status