module Monky.Network.Static
( getReadWrite
, NetworkHandle
, getNetworkHandle
, closeNetworkHandle
)
where
import Monky.Utility
import Data.Time.Clock.POSIX
import Data.IORef
import System.IO.Error (catchIOError)
data NetState
= Down
| Up
| Unknown
| Dormant
getState :: NetworkHandle -> IO NetState
getState (NetH _ _ statef _ _ _) = do
state <- catchIOError (readLine statef) (\_ -> return "down")
return $ case state of
"up" -> Up
"down" -> Down
"unknown" -> Unknown
"dormant" -> Dormant
_ -> error ("Don't know the network state \"" ++ state ++ "\" yet")
data NetworkHandle = NetH File File File (IORef Int) (IORef Int) (IORef POSIXTime)
basePath :: String
basePath = "/sys/class/net/"
readPath :: String
readPath = "/statistics/rx_bytes"
writePath :: String
writePath = "/statistics/tx_bytes"
statePath :: String
statePath = "/operstate"
calculateRates :: Int -> Int -> Int -> Int -> POSIXTime -> POSIXTime -> (Int, Int)
calculateRates oread nread owrite nwrite otime ntime =
let cread = oread nread
cwrite = owrite nwrite
ctime = otime ntime in
((cread * 8) `sdivBound` round ctime,
(cwrite * 8) `sdivBound` round ctime)
getReadWriteReal :: NetworkHandle -> IO (Int, Int)
getReadWriteReal (NetH readf writef _ readref writeref timeref) = do
nread <- readValue readf
nwrite <- readValue writef
ntime <- getPOSIXTime
oread <- readIORef readref
owrite <- readIORef writeref
otime <- readIORef timeref
writeIORef readref nread
writeIORef writeref nwrite
writeIORef timeref ntime
return $ calculateRates oread nread owrite nwrite otime ntime
getReadWrite :: NetworkHandle -> IO (Maybe (Int, Int))
getReadWrite h = do
state <- getState h
case state of
Up -> fmap Just . getReadWriteReal $ h
Unknown -> fmap Just . getReadWriteReal $ h
_ -> return Nothing
getNetworkHandle
:: String
-> IO NetworkHandle
getNetworkHandle dev = do
readf <- fopen $path ++ readPath
writef <- fopen $path ++ writePath
statef <- fopen $path ++ statePath
readref <- newIORef (1 :: Int)
writeref <- newIORef (1 :: Int)
timeref <- newIORef (0 :: POSIXTime)
return $NetH readf writef statef readref writeref timeref
where path = basePath ++ dev
closeNetworkHandle :: NetworkHandle -> IO ()
closeNetworkHandle (NetH readf writef statef _ _ _) =
mapM_ fclose [readf, writef, statef]