hs-tls/core/Network/TLS/Wire.hs

144 lines
3.6 KiB
Haskell
Raw Normal View History

2010-09-09 21:47:19 +00:00
-- |
-- Module : Network.TLS.Wire
-- License : BSD-style
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
-- Stability : experimental
-- Portability : unknown
--
2011-04-24 12:43:18 +00:00
-- the Wire module is a specialized marshalling/unmarshalling package related to the TLS protocol.
2010-09-09 21:47:19 +00:00
-- all multibytes values are written as big endian.
--
module Network.TLS.Wire
2013-07-12 06:27:28 +00:00
( Get
, runGet
, runGetErr
, runGetMaybe
, remaining
, getWord8
, getWords8
, getWord16
, getWords16
, getWord24
, getBytes
, getOpaque8
, getOpaque16
, getOpaque24
, getInteger16
2013-07-12 06:27:28 +00:00
, getList
, processBytes
, isEmpty
, Put
, runPut
, putWord8
, putWords8
, putWord16
, putWords16
, putWord24
, putBytes
, putOpaque8
, putOpaque16
, putOpaque24
, putInteger16
2013-07-12 06:27:28 +00:00
, encodeWord16
, encodeWord64
) where
2010-09-09 21:47:19 +00:00
2011-06-12 20:38:42 +00:00
import Data.Serialize.Get hiding (runGet)
import qualified Data.Serialize.Get as G
import Data.Serialize.Put
2010-09-19 09:49:42 +00:00
import Control.Applicative ((<$>))
2010-09-09 21:47:19 +00:00
import Control.Monad.Error
import qualified Data.ByteString as B
2010-09-09 21:47:19 +00:00
import Data.Word
import Data.Bits
import Network.TLS.Struct
import Network.TLS.Util.Serialization
2010-09-09 21:47:19 +00:00
runGet :: String -> Get a -> Bytes -> Either String a
2011-06-12 20:38:42 +00:00
runGet lbl f = G.runGet (label lbl f)
2012-05-14 05:36:17 +00:00
runGetErr :: String -> Get a -> Bytes -> Either TLSError a
runGetErr lbl f = either (Left . Error_Packet_Parsing) Right . runGet lbl f
runGetMaybe :: Get a -> Bytes -> Maybe a
runGetMaybe f = either (const Nothing) Just . runGet "" f
2010-09-09 21:47:19 +00:00
getWords8 :: Get [Word8]
getWords8 = getWord8 >>= \lenb -> replicateM (fromIntegral lenb) getWord8
getWord16 :: Get Word16
getWord16 = getWord16be
2010-09-09 21:47:19 +00:00
getWords16 :: Get [Word16]
getWords16 = getWord16 >>= \lenb -> replicateM (fromIntegral lenb `div` 2) getWord16
getWord24 :: Get Int
getWord24 = do
2013-07-12 06:27:28 +00:00
a <- fromIntegral <$> getWord8
b <- fromIntegral <$> getWord8
c <- fromIntegral <$> getWord8
return $ (a `shiftL` 16) .|. (b `shiftL` 8) .|. c
2010-09-09 21:47:19 +00:00
getOpaque8 :: Get Bytes
getOpaque8 = getWord8 >>= getBytes . fromIntegral
getOpaque16 :: Get Bytes
getOpaque16 = getWord16 >>= getBytes . fromIntegral
getOpaque24 :: Get Bytes
getOpaque24 = getWord24 >>= getBytes
getInteger16 :: Get Integer
getInteger16 = os2ip <$> getOpaque16
2012-08-27 13:20:04 +00:00
getList :: Int -> (Get (Int, a)) -> Get [a]
getList totalLen getElement = isolate totalLen (getElements totalLen)
2013-07-12 06:27:28 +00:00
where getElements len
2012-08-27 13:20:04 +00:00
| len < 0 = error "list consumed too much data. should never happen with isolate."
| len == 0 = return []
| otherwise = getElement >>= \(elementLen, a) -> liftM ((:) a) (getElements (len - elementLen))
2010-09-09 21:47:19 +00:00
processBytes :: Int -> Get a -> Get a
processBytes i f = isolate i f
2010-09-09 21:47:19 +00:00
putWords8 :: [Word8] -> Put
putWords8 l = do
2013-07-12 06:27:28 +00:00
putWord8 $ fromIntegral (length l)
mapM_ putWord8 l
2010-09-09 21:47:19 +00:00
putWord16 :: Word16 -> Put
putWord16 = putWord16be
2010-09-09 21:47:19 +00:00
putWords16 :: [Word16] -> Put
putWords16 l = do
2013-07-12 06:27:28 +00:00
putWord16 $ 2 * (fromIntegral $ length l)
mapM_ putWord16 l
2010-09-09 21:47:19 +00:00
putWord24 :: Int -> Put
putWord24 i = do
2013-07-12 06:27:28 +00:00
let a = fromIntegral ((i `shiftR` 16) .&. 0xff)
let b = fromIntegral ((i `shiftR` 8) .&. 0xff)
let c = fromIntegral (i .&. 0xff)
mapM_ putWord8 [a,b,c]
putBytes :: Bytes -> Put
putBytes = putByteString
2010-09-09 21:47:19 +00:00
putOpaque8 :: Bytes -> Put
putOpaque8 b = putWord8 (fromIntegral $ B.length b) >> putBytes b
putOpaque16 :: Bytes -> Put
putOpaque16 b = putWord16 (fromIntegral $ B.length b) >> putBytes b
putOpaque24 :: Bytes -> Put
putOpaque24 b = putWord24 (B.length b) >> putBytes b
putInteger16 :: Integer -> Put
putInteger16 = putOpaque16 . i2osp
encodeWord16 :: Word16 -> Bytes
encodeWord16 = runPut . putWord16
encodeWord64 :: Word64 -> Bytes
encodeWord64 = runPut . putWord64be