{-# LINE 1 "src/System/Linux/RTNetlink/Message.hsc" #-}
{-# OPTIONS_HADDOCK prune #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeFamilies #-}
module System.Linux.RTNetlink.Message where
import Control.Applicative ((<$>), (<*>))
import Control.Monad (guard)
import Data.Int (Int32)
import Data.List (nub)
import Data.Monoid (mempty)
import Data.Serialize
import Data.Word (Word16, Word32)
import qualified Data.ByteString as S
import qualified Foreign.C.Error as C
import System.Linux.RTNetlink.Packet
{-# LINE 44 "src/System/Linux/RTNetlink/Message.hsc" #-}
type SequenceNumber = Word32
sequenceNumber :: S.ByteString -> SequenceNumber
sequenceNumber = either (const 0) nlMsgSeqNum . decode
type TypeNumber = Word16
type NLFlags = Word16
data NLMessage header = NLMessage
{ nlmHeader :: header
, nlmAttrs :: AttributeList
, nlmType :: TypeNumber
, nlmFlags :: NLFlags
, nlmSeqNum :: SequenceNumber
} deriving (Show, Eq)
instance Sized header => Sized (NLMessage header) where
size NLMessage {..} = size nlmAttrs + size nlmHeader + 16
{-# LINE 65 "src/System/Linux/RTNetlink/Message.hsc" #-}
instance (Sized header, Serialize header) => Serialize (NLMessage header) where
put m@(NLMessage {..}) = do
put $ NLMsgHdr (size m) nlmType nlmFlags nlmSeqNum 0
put $ nlmHeader
put $ nlmAttrs
get = do
NLMsgHdr {..} <- get
header <- get
attributes <- get
return $ NLMessage header attributes nlMsgType nlMsgFlags nlMsgSeqNum
data NLMsgErr = NLMsgErr
{ nleError :: Int32
, nleHeader :: NLMsgHdr
} deriving (Show, Eq)
instance Sized NLMsgErr where
size = const 20
{-# LINE 85 "src/System/Linux/RTNetlink/Message.hsc" #-}
instance Serialize NLMsgErr where
put NLMsgErr {..} = putInt32host nleError >> put nleHeader
get = NLMsgErr <$> getInt32le <*> get
instance Header NLMsgErr where
emptyHeader = NLMsgErr 0 $ NLMsgHdr 0 0 0 0 0
class (Show h, Eq h, Sized h, Serialize h) => Header h where
emptyHeader :: h
instance Header () where
emptyHeader = ()
class Header (MessageHeader m) => Message m where
type MessageHeader m
messageHeader :: m -> MessageHeader m
messageHeader = const emptyHeader
messageAttrs :: m -> AttributeList
messageAttrs = mempty
toNLMessage ::
m -> TypeNumber -> NLFlags -> SequenceNumber -> NLMessage (MessageHeader m)
toNLMessage m = NLMessage (messageHeader m) (messageAttrs m)
{-# MINIMAL #-}
class Message c => Create c where
createTypeNumber :: c -> TypeNumber
createNLMessage :: c -> SequenceNumber -> NLMessage (MessageHeader c)
createNLMessage c = toNLMessage c (createTypeNumber c) flags
where flags = 1541
{-# LINE 122 "src/System/Linux/RTNetlink/Message.hsc" #-}
{-# MINIMAL createTypeNumber #-}
class Message d => Destroy d where
destroyTypeNumber :: d -> TypeNumber
destroyNLMessage :: d -> SequenceNumber -> NLMessage (MessageHeader d)
destroyNLMessage d = toNLMessage d (destroyTypeNumber d) flags
where flags = 5
{-# LINE 133 "src/System/Linux/RTNetlink/Message.hsc" #-}
{-# MINIMAL destroyTypeNumber #-}
class Message id => Change id c where
changeTypeNumber :: id -> c -> TypeNumber
changeHeader :: id -> c -> MessageHeader id
changeAttrs :: id -> c -> AttributeList
changeNLMessage :: id -> c -> SequenceNumber -> NLMessage (MessageHeader id)
changeNLMessage i c =
NLMessage (changeHeader i c) (changeAttrs i c) (changeTypeNumber i c) flags
where flags = 5
{-# LINE 152 "src/System/Linux/RTNetlink/Message.hsc" #-}
{-# MINIMAL changeTypeNumber, changeHeader, changeAttrs #-}
class Message r => Request r where
requestTypeNumber :: r -> TypeNumber
requestNLFlags :: r -> NLFlags
requestNLFlags = const 1
{-# LINE 162 "src/System/Linux/RTNetlink/Message.hsc" #-}
requestNLMessage :: r -> SequenceNumber -> NLMessage (MessageHeader r)
requestNLMessage r = toNLMessage r (requestTypeNumber r) (requestNLFlags r)
{-# MINIMAL requestTypeNumber #-}
dumpNLFlags :: NLFlags
dumpNLFlags = 769
{-# LINE 172 "src/System/Linux/RTNetlink/Message.hsc" #-}
class Header (ReplyHeader r) => Reply r where
type ReplyHeader r
replyTypeNumbers :: r -> [TypeNumber]
fromNLMessage :: NLMessage (ReplyHeader r) -> Maybe r
{-# MINIMAL replyTypeNumbers, fromNLMessage #-}
instance Reply () where
type ReplyHeader () = ()
replyTypeNumbers () = []
fromNLMessage _ = Nothing
instance (Reply r, Reply s, ReplyHeader r ~ ReplyHeader s) => Reply (r,s) where
type ReplyHeader (r,s) = ReplyHeader r
replyTypeNumbers (r,s) = nub $ replyTypeNumbers r ++ replyTypeNumbers s
fromNLMessage m = (,) <$> fromNLMessage m <*> fromNLMessage m
instance Reply C.Errno where
type ReplyHeader C.Errno = NLMsgErr
replyTypeNumbers _ = [2]
{-# LINE 196 "src/System/Linux/RTNetlink/Message.hsc" #-}
fromNLMessage = Just . C.Errno . abs . fromIntegral . nleError . nlmHeader
fromNLMessage' :: Reply r => NLMessage (ReplyHeader r) -> Maybe r
fromNLMessage' m = do
r <- fromNLMessage m
guard $ nlmType m `elem` replyTypeNumbers r
return r
decodeMaybe :: Serialize a => S.ByteString -> Maybe a
decodeMaybe = either (const Nothing) Just . decode
runGetMaybe :: Get a -> S.ByteString -> Maybe a
runGetMaybe g = either (const Nothing) Just . runGet g