module Network.LibP2P.Security.Noise.Framing
( encodeFrame
, decodeFrame
, maxNoiseMessageSize
) where
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import Network.LibP2P.Core.Binary (readWord16BE, word16BE)
maxNoiseMessageSize :: Int
maxNoiseMessageSize :: Int
maxNoiseMessageSize = Int
65535
encodeFrame :: ByteString -> ByteString
encodeFrame :: ByteString -> ByteString
encodeFrame ByteString
msg =
let len :: Int
len = ByteString -> Int
BS.length ByteString
msg
in Word16 -> ByteString
word16BE (Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len) ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
msg
decodeFrame :: ByteString -> Either String (ByteString, ByteString)
decodeFrame :: ByteString -> Either String (ByteString, ByteString)
decodeFrame ByteString
bs
| ByteString -> Int
BS.length ByteString
bs Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
2 = String -> Either String (ByteString, ByteString)
forall a b. a -> Either a b
Left String
"decodeFrame: need at least 2 bytes for length"
| Bool
otherwise =
let len :: Int
len = Word16 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Word16
readWord16BE ByteString
bs) :: Int
rest :: ByteString
rest = Int -> ByteString -> ByteString
BS.drop Int
2 ByteString
bs
in if ByteString -> Int
BS.length ByteString
rest Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
len
then String -> Either String (ByteString, ByteString)
forall a b. a -> Either a b
Left (String -> Either String (ByteString, ByteString))
-> String -> Either String (ByteString, ByteString)
forall a b. (a -> b) -> a -> b
$ String
"decodeFrame: expected " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show Int
len String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" bytes but got " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show (ByteString -> Int
BS.length ByteString
rest)
else (ByteString, ByteString) -> Either String (ByteString, ByteString)
forall a b. b -> Either a b
Right (Int -> ByteString -> ByteString
BS.take Int
len ByteString
rest, Int -> ByteString -> ByteString
BS.drop Int
len ByteString
rest)