/
NetMonitor.hs
64 lines (50 loc) · 2.2 KB
/
NetMonitor.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
{-----------------------------------------------------------------------------
reactive-banana-wx
Example: Minuscule network monitor
------------------------------------------------------------------------------}
import Data.Char
import Data.List
import Data.Maybe
import System.Process
import Graphics.UI.WX hiding (Event)
import Reactive.Banana
import Reactive.Banana.WX
{-----------------------------------------------------------------------------
Main
------------------------------------------------------------------------------}
main :: IO ()
main = start $ do
f <- frame [text := "Network Monitor"]
out1 <- staticText f []
out2 <- staticText f []
set f [layout := minsize (sz 250 70) $ margin 10 $
column 10 [label "TCP network statistics",
grid 5 5 [[label "Packets sent: ", widget out1]
,[label "Packets received: ", widget out2]]
]
]
t <- timer f [ interval := 500 ] -- timer every 500 ms
let networkDescription :: MomentIO ()
networkDescription = do
-- The network statistics are polled when and only when
-- the event network handles an event.
bnetwork <- fromPoll getNetworkStatistics
-- That's why we need a timer that generates regular events to handle.
etick <- event0 t command
let showSent = maybe "parse error" show . fst
showReceived = maybe "parse error" show . snd
sink out1 [ text :== showSent <$> bnetwork ]
sink out2 [ text :== showReceived <$> bnetwork ]
network <- compile networkDescription
actuate network
-- Obtain network statistics from the netstat utility
type NetworkStatistics = (Maybe Int, Maybe Int)
getNetworkStatistics :: IO NetworkStatistics
getNetworkStatistics = do
s <- readProcess "netstat" ["-s", "-p","tcp"] ""
return (readField "packets sent" s
,readField "packets received" s)
readField :: String -> String -> Maybe Int
readField fieldname = id
. fmap (read . filter isDigit) . listToMaybe
. filter (fieldname `isSuffixOf`) . lines