rws-0.1.1.2: src/Gre.hs
{-# LANGUAGE CPP #-}
module Gre where
import Control.Monad
import Data.Binary.Put
import Data.Bits
import qualified Data.ByteString.Lazy as B
import Text.ParserCombinators.Parsec
import Text.ParserCombinators.Parsec.Perm
import Util
import Packet
import Lexer
#ifdef HRWS_TEST
import Debug.Trace
import Test.QuickCheck hiding ((.&.))
import Test.Framework (Test)
import Test.Framework.Providers.QuickCheck2 (testProperty)
import Text.Printf
#endif
parseGrePkt :: Parser Packet -> Parser GrePkt
parseGrePkt f = permute
(tuple <$?> (0x3000, parseIntAttribute "flags")
<|?> (0x0800, parseIntAttribute "protocol")
<|?> (0xcafecafe, parseIntAttribute "key")
<|?> (0, try (parseIntAttribute "seq"))
<|?> ([PPayload defaultPayload], parsePayload f))
where
tuple fl prot k s =
GrePkt (Gre fl prot k s)
greDecl :: Parser Packet -> Parser Packet
greDecl f = do
symbol "gre"
g <- parseGrePkt f
return (PGre g)
greWriteHdr :: Gre -> Put
greWriteHdr p = do
putWord16be (greFlags p)
putWord16be (greProtocol p)
-- Optional Key Field
when (greFlags p .&. 0x2000 == 0x2000) $
putWord32be $ greKey p
when (greFlags p .&. 0x1000 == 0x1000) $
putWord32be $ greSeq p
greWrite :: Gre -> Maybe Packet -> B.ByteString -> Put
greWrite h _ bs = do
greWriteHdr h
putLazyByteString bs
instance PacketWriteable GrePkt where packetWrite p = greWrite (grePktHeader p)
#ifdef HRWS_TEST
{- Unit Tests -}
instance Arbitrary Gre where
arbitrary = do
f <- arbitrary
p <- arbitrary
k <- arbitrary
s <- arbitrary
return (Gre f p k s)
testValidParse :: String -> (Gre -> Bool) -> Bool
testValidParse str fn =
case parse (dummyParsePacket greDecl) "packet parse" str of
Left err -> trace (show err) False
Right val -> fn $ testGrePkt val
testGreDefault :: () -> Bool
testGreDefault _ = let cmp f = defaultGre == f in
testValidParse "(gre)" cmp
testGrePkt :: Packet -> Gre
testGrePkt (PGre f) = grePktHeader f
testGrePkt _ = error "Unexpected packet type"
testGrePacket :: Gre -> Bool
testGrePacket pkt =
let cmp p = pkt == p in
testValidParse (printf "(gre flags=%d protocol=%d key=%d seq=%d)" (greFlags pkt)
(greProtocol pkt) (greKey pkt) (greSeq pkt)) cmp
testGreWrite :: () -> Bool
testGreWrite _ =
let expPkt = B.pack [0x30, 0x00, 0x08, 0x00, 0x12, 0x34, 0x56, 0x78, 0xaa, 0xaa, 0xaa, 0xaa] in
let cmp p = runPut (greWrite p Nothing B.empty) == expPkt in
testValidParse "(gre flags=0x3000 protocol=0x0800 key=0x12345678 seq=0xaaaaaaaa)" cmp
greTests :: [Test]
greTests = [
testProperty "GRE: Default Packet" testGreDefault,
testProperty "GRE: Packet" testGrePacket,
testProperty "GRE: Write" testGreWrite
]
#endif