-----------------------------------------------------------------------------
-- |
-- Module      : System.Information.Network
-- Copyright   : (c) José A. Romero L.
-- License     : BSD3-style (see LICENSE)
--
-- Maintainer  : José A. Romero L. <escherdragon@gmail.com>
-- Stability   : unstable
-- Portability : unportable
--
-- Provides information about network traffic over selected interfaces,
-- obtained from parsing the @\/proc\/net\/dev@ file using some of the
-- facilities provided by the "System.Information.StreamInfo" module.
--
-----------------------------------------------------------------------------

module System.Information.Network ( getNetInfo ) where

import Control.Applicative
import Data.Maybe ( mapMaybe )
import Safe ( atMay, initSafe, readDef )
import System.Information.StreamInfo ( getParsedInfo )

import Prelude

-- | Returns a two-element list containing the current number of bytes
-- received and transmitted via the given network interface (e.g. \"wlan0\"),
-- according to the contents of the @\/proc\/dev\/net@ file.
getNetInfo :: String -> IO (Maybe [Integer])
getNetInfo iface = do
  isUp <- isInterfaceUp iface
  case isUp of
    True -> Just <$> getParsedInfo "/proc/net/dev" parse iface
    False -> return Nothing

parse :: String -> [(String, [Integer])]
parse = mapMaybe tuplize . map words . drop 2 . lines

tuplize :: [String] -> Maybe (String, [Integer])
tuplize s = do
  dev <- initSafe <$> s `atMay` 0
  down <- readDef (-1) <$> s `atMay` 1
  up <- readDef (-1) <$> s `atMay` out
  return (dev, [down, up])
  where
    out = (length s) - 8

isInterfaceUp :: String -> IO Bool
isInterfaceUp iface = do
  state <- readFile $ "/sys/class/net/" ++ iface ++ "/operstate"
  case state of
    'u' : _ -> return True
    _ -> return False