forked from Enecuum/Node
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathPongClient.hs
69 lines (58 loc) · 2.81 KB
/
PongClient.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
{-# OPTIONS_GHC -fno-warn-orphans #-}
{-# LANGUAGE DuplicateRecordFields #-}
module Enecuum.Samples.Assets.Nodes.TstNodes.PingPong.PongClient 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 PongClientNode = PongClientNode
deriving (Show, Generic)
data instance NodeConfig PongClientNode = PongClientNodeConfig
{ _clientName :: Text
, _pingDelay :: Int
, _pingServerAddress :: D.Address
}
deriving (Show, Generic)
instance Node PongClientNode where
data NodeScenario PongClientNode = PongClient
deriving (Show, Generic)
getNodeScript _ = pongClientNode
getNodeTag _ = PongClientNode
instance ToJSON PongClientNode where toJSON = A.genericToJSON nodeConfigJsonOptions
instance FromJSON PongClientNode where parseJSON = A.genericParseJSON nodeConfigJsonOptions
instance ToJSON (NodeConfig PongClientNode) where toJSON = A.genericToJSON nodeConfigJsonOptions
instance FromJSON (NodeConfig PongClientNode) where parseJSON = A.genericParseJSON nodeConfigJsonOptions
instance ToJSON (NodeScenario PongClientNode) where toJSON = A.genericToJSON nodeConfigJsonOptions
instance FromJSON (NodeScenario PongClientNode) where parseJSON = A.genericParseJSON nodeConfigJsonOptions
-- Accepting pong responses from the server.
acceptPong :: Pong -> connection -> L.NodeL ()
acceptPong (Pong pingsCount) _ =
L.logInfo $ "Pong accepted from server. Pings count: " <> show pingsCount
-- Sending pings to the server.
pingSending :: D.StateVar D.NodeStatus -> NodeConfig PongClientNode -> D.Connection D.Udp -> L.NodeL ()
pingSending status cfg conn = do
L.delay $ _pingDelay cfg
L.logInfo "Sending Ping to the server."
eSent <- L.send conn (Ping $ _clientName cfg)
case eSent of
Right () -> pingSending status cfg conn
Left _ -> do
L.logInfo "Server is gone."
L.close conn
L.writeVarIO status D.NodeFinished
-- Pong client definition node.
pongClientNode :: NodeConfig PongClientNode -> L.NodeDefinitionL ()
pongClientNode cfg = do
status <- L.newVarIO D.NodeActing
-- Connecting to the server.
mbConn <- L.open D.Udp (_pingServerAddress cfg) $
L.handler acceptPong
case mbConn of
Nothing -> L.logError "Ping Server not found"
Just conn -> do
-- Forking separate process of periodical pings.
L.process (pingSending status cfg conn)
-- Waiting when the node is finished.
L.awaitNodeFinished' status